³õʶ MVVM
̸Æð MVVM Éè¼ÆÄ£Ê½£¬¿ÉÄܵÚÒ»Ó³ÏñÄã»áÏëµ½ WPF/Sliverlight£¬ËûÃÇÌṩÁ˵ÄÊý¾Ý°ó¶¨£¨Data
Binding£©£¬ÃüÁCommand£©µÈ¹¦ÄÜ£¬ÕâÈà MVVM ģʽµÃµ½ºÜºÃµÄʵÏÖ¡£
MVVM Éè¼ÆÄ£Ê½¹ËÃû˼Ò壬ͨ¹ý·ÖÀë¹Ø×¢µã£¬¸÷˾ÆäÖ°¡£Í¨¹ý Data
Binding ¿É´ïµ½Êý¾ÝµÄË«Ïò°ó¶¨£¬¶øÃüÁî Command ¸üÊǽ«´«Í³µÄ Code Behind ʼþ¶ÀÁ¢µ½
ViewModel ÖС£

MVVM Éè¼ÆÄ£Ê½ÔÚ WPF ÖеÄʵÏÖ
ÔÚWPFÖУ¬Äã»áÏñÈçÏÂÕâÑùÈ¥¶¨ÒåÒ»¸öרÃŹÜÀíÊÓͼ View µÄ ViewModel£º
public class SongViewModel : INotifyPropertyChanged { #region Construction /// Constructs the default instance of a SongViewModel public SongViewModel() { _song = new Song { ArtistName = "Unknown", SongTitle = "Unknown" }; } #endregion
#region Members
Song _song;
#endregion
#region Properties
public Song Song
{
get
{
return _song;
}
set
{
_song = value;
}
}
public string ArtistName
{
get { return Song.ArtistName; }
set
{
if (Song.ArtistName != value)
{
Song.ArtistName = value;
RaisePropertyChanged("ArtistName");
}
}
}
#endregion
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
#region Methods
private void RaisePropertyChanged(string propertyName)
{
// take a copy to prevent thread issues
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
} |
ͬʱÔÚ View ÖÐÄãÐèҪʹÓà Binding ½« ViewModel
µÄÊôÐ԰󶨺ͿؼþµÄÄÚÈÝÏà°ó¶¨£º
<TextBox
Content="{Binding ArtistName}" /> |
ÖµµÃ×¢ÒâµÄÊÇ£¬ÒªÊµÏÖ View ºÍ ViewModel Ë«Ïò°ó¶¨£¬ÎÒÃÇµÄ ViewModel ±ØÐëʵÏÖ INotifyPropertyChanged
½Ó¿Ú£¬ÓÉÓÚ WPF Framework Èÿؼþ¼àÌýÁË PropertyChanged ʼþ£¬µ±ÊôÐÔÖµ·¢Éúʱ£¬´¥·¢
PropertyChanged ʼþ£¬ËùÒԿؼþ¾ÍÄÜ×Ô¶¯»ñÈ¡µ½×îеÄÖµ¡£·´Ö®£¬µ±¿Ø¼þµÄÖµ·¢Éú¸Ä±äʱ£¬ÀýÈç TextBox
´¥·¢ OnTextChanged ʼþ£¬×Ô¶¯½«×îеÄֵͬ²½µ½ ViewModel ÏàÓ¦µÄÊôÐÔÖС£
MVP & MVVM
Unity 3D Óë WPF/Sliverlight ²»Í¬£¬ËüûÓÐÌṩÀàËÆµÄ Data Binding£¬Ò²Ã»ÓÐÏñ
XAML Ò»ÑùµÄÊÓͼÓï·¨£¬ÄÇôÔõÑù²ÅÄÜÔÚ Unity 3D ÖÐȥʵÏÖ MVVM ÄØ£¿
ÔÚ ASP.NET WebForm ʱ´ú£¬ÄÇʱ»¹Ã»ÓÐ ASP.Net MVC
¡£ÎÒÃÇΪÁËÈà UI ±íÏÖ²ã·ÖÀ룬³£³£»áʹÓà MVP Éè¼ÆÄ£Ê½£¬ÒÔÏÂÊÇÎÒÔÚ¼¸Äêǰ»µÄÒ»ÕÅÀÏͼ£º

MVP Éè¼ÆÄ£Ê½ºËÐľÍÊÇ£¬Í¨¹ý¶¨ÒåÒ»¸ö View£¬½« UI ³éÏó³öÀ´£¬Ëü²»±Ø¹ØÐÄÊý¾ÝµÄ¾ßÌåÀ´Ô´£¬Ò²²»±Ø¹ØÐĵã»÷°´Å¥Ö®ºóÒµÎñÂß¼µÄʵÏÖ£¬ËüÖ»¹Ø×¢
UI ½»»¥¡£Õâ¾ÍÊǵäÐ͵ķÖÀë¹Ø×¢µã¡£
ÆäʵÕâ¾ÍÊÇÎÒ½ñÌìÏë½²µÄÖ÷Ì⣬¼ÈÈ» Unity 3D ûÓÐÌṩÊý¾Ý°ó¶¨£¬ÄÇôÎÒÃÇÒ²¿ÉÒԲο¼Ö®Ç° MVP
µÄÉè¼ÆÀíÄ
½« UI ³éÏó³É¶ÀÁ¢µÄÒ»¸ö¸ö View£¬½«ÃæÏò Component ¿ª·¢×ª»»ÎªÃæÏò
View ¿ª·¢£¬Ã¿Ò»¸ö View ¶¼ÓжÀÁ¢µÄ ViewModel ½øÐйÜÀí£¬ÈçÏÂËùʾ£º

ÓÉÓÚ Unity 3D ûÓÐ XAML,ҲûÓÐ Data Binding ¼¼Êõ£¬¹ÊÖ»ÄÜÔÚ³éÏó³öÀ´µÄ View
ÖÐȥʵÏÖÀàËÆÓÚ WPF µÄ Data Binding£¬Converter£¬Command µÈ¡£
ÖµµÃ×¢ÒâµÄÊÇ£¬MVP Éè¼ÆÄ£Ê½ÖÐÊý¾ÝµÄ°ó¶¨ÊÇͨ¹ý½«¾ßÌåµÄ View ʵÀý´«µÝµ½
Presenter ÖÐÍê³ÉµÄ£¬¶ø MVVM ÊÇÒÔÊý¾Ý¸Ä±äÒý·¢µÄʼþÖÐÍê³ÉÊý¾Ý¸üеġ£
MVVM Éè¼ÆÄ£Ê½ÔÚ Unity 3D ÖеÄÉè¼ÆÓëʵÏÖ
ÔٻعËһϠWPF ÖÐ ViewModel µÄд·¨¡£ ViewModel ÌṩÁË View ÐèÒªµÄÊý¾Ý£¬²¢ÇÒ
ViewModel ʵÏÖ INotifyPropertyChanged ½Ó¿Ú £¬µ±Êý¾Ý¸ü¸Äʱ£¬´¥·¢ÁË PropertyChanged
ʼþ£¬ÓÉÓڿؼþÒ²¼àÌýÁË´Ëʼþ£¬ÔÚʼþµÄÏìÓ¦º¯ÊýÀïʵÏÖÊý¾ÝµÄ¸üС£
Á˽âÁËÖ®ºó£¬ÎÒÃÇÒª¿¼ÂÇÔõÑùÔÚ Unity 3D ÖÐȥʵÏÖËü¡£¼ÙÉèÎÒÃÇÐèÒªÍê³ÉÈçϵÄÒ»¸ö¹¦ÄÜ£¬²¢ÇÒÊÇʹÓÃ
MVVM Éè¼ÆË¼ÏëʵÏÖ£º

Ê×ÏÈ£¬ÎÒÃÇÒª¶¨ÒåÒ»¸ö View£¬Õâ¸ö View ÊÇ¶Ô UI ÔªËØµÄÒ»¸ö³éÏ󣬵½µ×Òª³éÏóÄÄЩ
UI ÔªËØÄØ£¿¾ÍÕâ¸öÀý×Ó¶øÑÔ£¬InputField£¬Label£¬Slider£¬Toggle£¬Button
ÊÇÐèÒª±»³éÏó³öÀ´µÄ¡£
public class SetupView { public InputField nameInputField; public Text nameMessageText;
public InputField jobInputField;
public Text jobMessageText;
public InputField atkInputField;
public Text atkMessageText;
public Slider successRateSlider;
public Text successRateMessageText;
public Toggle joinToggle;
public Button joinInButton;
public Button waitButton;
} |
¿ÉÒÔ¿´µ½£¬ÕâÊÇÒ»¸öºÜ¼òµ¥µÄ View¡£½Ó×ÅÎÒÃÇÐèÒª¶¨ÒåÒ»¸öרÃÅÓÃÀ´¹ÜÀí
View µÄ ViewModel£¬ËüÒÔÊôÐÔµÄÐÎʽÌṩÊý¾Ý£¬ÒÔ·½·¨µÄÐÎʽÌṩÐÐΪ¡£
ÖµµÃ×¢ÒâµÄÊÇ£¬ViewModel ÖеÄÊôÐÔ²»ÊÇÌØÊâµÄÊôÐÔ£¬Ëü±ØÐë¾ß±¸µ±Êý¾Ý¸ü¸Äʱ֪ͨ¶©ÔÄÕßÕâ¸ö¹¦ÄÜ£¬Ôõô֪ͨ¶©ÔÄÕߣ¿µ±È»ÊÇʼþ£¬¹ÊÎÒ°Ñ´ËÊôÐÔ³ÆÎª
BindableProperty ÊôÐÔ¡£
public class BindableProperty<T> { public delegate void ValueChangedHandler(T oldValue, T newValue);
public ValueChangedHandler OnValueChanged;
private T _value;
public T Value
{
get
{
return _value;
}
set
{
if (!object.Equals(_value, value))
{
T old = _value;
_value = value;
ValueChanged(old, _value);
}
}
}
private void ValueChanged(T oldValue, T newValue)
{
if (OnValueChanged != null)
{
OnValueChanged(oldValue, newValue);
}
}
public override string ToString()
{
return (Value != null ? Value.ToString() : "null");
}
} |
½Ó×Å£¬ÎÒÃÇÔÙ¶¨ÒåÒ»¸ö ViewModel£¬ËüΪ View ÌṩÁËÊý¾ÝºÍÐÐΪ:
public class SetupViewModel : ViewModel { public BindableProperty<string> Name = new BindableProperty<string>(); public BindableProperty<string> Job = new BindableProperty<string>(); public BindableProperty<int> ATK = new BindableProperty<int>(); public BindableProperty<float> SuccessRate = new BindableProperty<float>(); public BindableProperty<State> State = new BindableProperty<State>(); } |
ÓÐÁË View Óë ViewModel Ö®ºó£¬ÎÒÃÇÐèÒª¿¼ÂÇ£º
1¡¢ÔõÑùΪ View Ö¸¶¨Ò»¸ö ViewModel
2¡¢µ± ViewModel ÊôÐÔÖµ¸Ä±äʱ£¬ÔõÑù¶©ÔÄ´¥·¢µÄ OnValueChanged
ʼþ£¬´Ó¶ø´ïµ½ View µÄÊý¾Ý¸üÐÂ
»ùÓÚÒÔÉÏÁ½µã£¬ÎÒÃÇ¿ÉÒÔ¶¨ÒåÒ»¸öͨÓÃµÄ View£¬½«ËüÃüÃûΪ UnityGuiView £º
public interface IView { ViewModel BindingContext { get; set; } }
public class UnityGuiView:MonoBehaviour,IView
{
public readonly BindableProperty<ViewModel>
ViewModelProperty = new BindableProperty<ViewModel>();
public ViewModel BindingContext
{
get { return ViewModelProperty.Value; }
set { ViewModelProperty.Value = value; }
}
protected virtual void OnBindingContextChanged(ViewModel
oldViewModel, ViewModel newViewModel)
{
}
public UnityGuiView()
{
this.ViewModelProperty.OnValueChanged += OnBindingContextChanged;
}
} |
ÉÏÊö´úÂëÖУ¬Ìṩһ¸ö BindingContext ÉÏÏÂÎÄÊôÐÔ£¬ÀàËÆÓÚ WPF ÖÐµÄ DataContext¡£
BindingContext ÊôÐÔÎÒÃDz»Äܽ«ËüÊÓΪһ¸ö¼òµ¥µÄÊôÐÔ £¬ËüÊÇÉÏÊö¶¨Òå¹ýµÄ BindableProperty
ÀàÐÍÊôÐÔ¡£ÄÇôµ±ÎªÒ»¸ö View µÄ BindingContext Ö¸¶¨ ViewModel ʵÀýʱ£¬³õʼ»¯Ê±£¬ÊƱػᴥ·¢
OnValueChanged ʼþ¡£
ÔÚÏìÓ¦º¯Êý OnBindingContextChanged ÖÐ £¬ÎÒÃÇ¿ÉÒÔÔÚ´Ë¶Ô ViewModel
ÖÐʼþ½øÐмàÌý£¬´Ó¶ø´ïµ½Êý¾ÝµÄ¸üС£µ±È»ÕâÊÇÒ»¸öÐé·½·¨£¬ÄãÐèÒªÔÚ×ÓÀà View ÖÐ Override¡£
ËùÒÔÐ޸͍Òå¹ýµÄ SetupView£¬¼Ì³Ð×Ô UnityGuiView:
public class SetupView:UnityGuiView { ...Ê¡ÂÔ²¿·Ö´úÂë
public SetupViewModel ViewModel { get { return
(SetupViewModel)BindingContext; } }
protected override void OnBindingContextChanged(ViewModel
oldViewModel, ViewModel newViewModel)
{
base.OnBindingContextChanged(oldViewModel, newViewModel);
SetupViewModel oldVm = oldViewModel as SetupViewModel;
if (oldVm != null)
{
ViewModel.Name.OnValueChanged -= NameValueChanged;
...
}
if (ViewModel!=null)
{
ViewModel.Name.OnValueChanged += NameValueChanged;
...
}
UpdateControls();
}
private void NameValueChanged(string oldvalue,
string newvalue)
{
nameMessageText.text = newvalue.ToString();
}
} |
ÓÉÓÚ×ÓÀà Override ÁË OnBindingContextChanged ·½·¨£¬¹ÊËü»á¶Ô ViewModel
µÄÊôÐÔÖµ¸Ä±äʼþ½øÐмàÌý£¬µ±´¥·¢Ê±£¬½«×îеÄÊý¾Ýͬ²½µ½ UI ÖС£
ͬÀí£¬¿¼Âǵ½Ë«Ïò°ó¶¨£¬ÄãÒ²¿ÉÒÔÔÚ View Öж¨ÒåÒ»¸ö OnTextBoxValueChanged ÏìÓ¦º¯Êý£¬µ±Îı¾¿òÖеÄÊý¾Ý¸Ä±äʱ£¬ÔÚÏìÓ¦º¯ÊýÖоÍÊý¾Ýͬ²½µ½
ViewModel ÖС£ÔÚÕâÎҾͲ»ÀÛÊöÁË¡£
×îºó£¬ÔÚ Unity 3D Öн« SetupView ¸½¼Óµ½ ÏàÓ¦µÄ GameObjectÉÏ£º

×îºóÔÚÉãÏñ»úÉϼÓÒ»¶Î½Å±¾£¬ºÜ¼òµ¥£¬´«Èë SetupView ¶ÔÏó²¢ÎªÆä°ó¶¨
ViewModel£º
public SetupView setupView; void Start() { //°ó¶¨ÉÏÏÂÎÄ setupView.BindingContext=new SetupViewModel(); } |
С½á
ÕâÊÇÒ»¸ö·Ç³£¼òµ¥µÄ MVVM ¿ò¼Ü£¬Ò²Ö¤Ã÷ÁËÔÚ Unity 3D ÖÐʵÏÖ MVVM Éè¼ÆÄ£Ê½µÄ¿ÉÄÜÐÔ¡£ |