学习MVVM设计模式后第一次用于生产

WPF的MVVM设计模式

winform转变到WPF的过程,难点主要还是在MVVM的设计模式。当然,如果依然采用winform的涉及方式,在每个控件背后绑定事件的方式运用在wpf中,依然可行,但是假如GUI改版,其背后绑定的特别为此界面设计的事件不得不多数弃用。而MVVM最大的好处是将一切业务逻辑放在ViewModel中 ,将GUI的操作放在view中,将数据结构放在Model中,如图摘自MSDN

640?wx_fmt=png

实际使用

使用了Prism框架,省去了去构造实现INotifyPropertyChanged的基类,直接继承BindableBase

namespace Prism.Mvvm{    //    // 摘要:    //     Implementation of System.ComponentModel.INotifyPropertyChanged to simplify models.    public abstract class BindableBase : INotifyPropertyChanged    {        protected BindableBase();        //        // 摘要:        //     Occurs when a property value changes.        public event PropertyChangedEventHandler PropertyChanged;        //        // 摘要:        //     Notifies listeners that a property value has changed.        //        // 参数:        //   propertyName:        //     Name of the property used to notify listeners. This value is optional and can        //     be provided automatically when invoked from compilers that support System.Runtime.CompilerServices.CallerMemberNameAttribute.        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null);        //        // 摘要:        //     Raises this object's PropertyChanged event.        //        // 参数:        //   propertyExpression:        //     A Lambda expression representing the property that has a new value.        //        // 类型参数:        //   T:        //     The type of the property that has a new value        protected virtual void OnPropertyChanged<T>(Expression<Func<T>> propertyExpression);        //        // 摘要:        //     Checks if a property already matches a desired value. Sets the property and notifies        //     listeners only when necessary.        //        // 参数:        //   storage:        //     Reference to a property with both getter and setter.        //        //   value:        //     Desired value for the property.        //        //   propertyName:        //     Name of the property used to notify listeners. This value is optional and can        //     be provided automatically when invoked from compilers that support CallerMemberName.        //        // 类型参数:        //   T:        //     Type of the property.        //        // 返回结果:        //     True if the value was changed, false if the existing value matched the desired        //     value.        protected virtual bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null);    }

以及用来构造Command的基类DelegateCommand

namespace Prism.Commands{    //    // 摘要:    //     An System.Windows.Input.ICommand whose delegates do not take any parameters for    //     Prism.Commands.DelegateCommand.Execute and Prism.Commands.DelegateCommand.CanExecute.    public class DelegateCommand : DelegateCommandBase    {        //        // 摘要:        //     Creates a new instance of Prism.Commands.DelegateCommand with the System.Action        //     to invoke on execution.        //        // 参数:        //   executeMethod:        //     The System.Action to invoke when System.Windows.Input.ICommand.Execute(System.Object)        //     is called.        public DelegateCommand(Action executeMethod);        //        // 摘要:        //     Creates a new instance of Prism.Commands.DelegateCommand with the System.Action        //     to invoke on execution and a Func to query for determining if the command can        //     execute.        //        // 参数:        //   executeMethod:        //     The System.Action to invoke when System.Windows.Input.ICommand.Execute(System.Object)        //     is called.        //        //   canExecuteMethod:        //     The System.Func`1 to invoke when System.Windows.Input.ICommand.CanExecute(System.Object)        //     is called        public DelegateCommand(Action executeMethod, Func<bool> canExecuteMethod);        protected DelegateCommand(Func<Task> executeMethod);        protected DelegateCommand(Func<Task> executeMethod, Func<bool> canExecuteMethod);        //        // 摘要:        //     Factory method to create a new instance of Prism.Commands.DelegateCommand from        //     an awaitable handler method.        //        // 参数:        //   executeMethod:        //     Delegate to execute when Execute is called on the command.        //        // 返回结果:        //     Constructed instance of Prism.Commands.DelegateCommand        public static DelegateCommand FromAsyncHandler(Func<Task> executeMethod);        //        // 摘要:        //     Factory method to create a new instance of Prism.Commands.DelegateCommand from        //     an awaitable handler method.        //        // 参数:        //   executeMethod:        //     Delegate to execute when Execute is called on the command. This can be null to        //     just hook up a CanExecute delegate.        //        //   canExecuteMethod:        //     Delegate to execute when CanExecute is called on the command. This can be null.        //        // 返回结果:        //     Constructed instance of Prism.Commands.DelegateCommand        public static DelegateCommand FromAsyncHandler(Func<Task> executeMethod, Func<bool> canExecuteMethod);        //        // 摘要:        //     Determines if the command can be executed.        //        // 返回结果:        //     Returns true if the command can execute, otherwise returns false.        public virtual bool CanExecute();        //        // 摘要:        //     Executes the command.        public virtual Task Execute();        //        // 摘要:        //     Observes a property that is used to determine if this command can execute, and        //     if it implements INotifyPropertyChanged it will automatically call DelegateCommandBase.RaiseCanExecuteChanged        //     on property changed notifications.        //        // 参数:        //   canExecuteExpression:        //     The property expression. Example: ObservesCanExecute((o) => PropertyName).        //        // 返回结果:        //     The current instance of DelegateCommand        public DelegateCommand ObservesCanExecute(Expression<Func<object, bool>> canExecuteExpression);        //        // 摘要:        //     Observes a property that implements INotifyPropertyChanged, and automatically        //     calls DelegateCommandBase.RaiseCanExecuteChanged on property changed notifications.        //        // 参数:        //   propertyExpression:        //     The property expression. Example: ObservesProperty(() => PropertyName).        //        // 类型参数:        //   T:        //     The object type containing the property specified in the expression.        //        // 返回结果:        //     The current instance of DelegateCommand        public DelegateCommand ObservesProperty<T>(Expression<Func<T>> propertyExpression);    }}

第一次使用MVVM设计模式,没有理解在多个ViewModel之间通信,所以不得不采用单一ViewModel和多个view,这样导致了一个ViewModel的臃肿和复杂,看似结构简单,但是实际的逻辑越来越混乱。在没有理解Event Aggregator如何使用的情况下,这是可行方案。

MVVM使用感受

最主要的感受是MVVM将UI和业务逻辑分离,UI就只写UI,不用像WinForm一样在每个事件背后,如果要获得UI某个TextBox的数据,得通过如下获取

public void SomeButton_Clicked(object sender, EventArgs e){	string text = textBox1.Text;	DoSomeThings(text);	...}

同样,后台事件要更新前台UI数据时

pubic void SomeButton_Clicked(object sender, EvnetArgs e){	DoOtherThings();	textBox1.Text = "Some Text";}

这种硬编码的形式,遇到UI的重大变化,必须就将背后事件对应UI的控件名称全部更改才能继续运行。当软件达到一定复杂度,这样做就是灾难性的。

MVVM,使用了数据绑定,虽然增加了一点代码,但是带来的好处巨大。在ViewModel中先定义要绑定的数据

private string name;public string Name{	get{return name;}	set{		if (name != value)		{			name = value;			OnPropertyChanged("Name"); // 实现INotifyPropertyChanged接口	}}}

然后在view中将其和TextBox数据绑定

<TextBox Text="{Binding Name, Mode=TwoWay}">

这里的数据绑定方式是双向绑定,后台数据变化会自动通知前台UI线程更新数据,相反,前台UI线程更改了数据,后台的数据也会相应变化。这样,在实际数据更新时,不用去查看绑定的UI控件名称,也不用担心在其他线程更新控件数据时要用oneControl.Invoke(Action action)

总结

第一次使用MVVM感受到的优点:

  • 数据绑定,不用考虑具体UI控件的名称,不用手动更新UI数据。

  • UI可操作性更大,支持template

  • 业务逻辑和UI分离,界面改版方便

但同样带来了缺点:

  • 代码量明显增加

  • 对于小软件来说,开发没有WinFrom来的敏捷


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值