MVVM模式

1.原理

基于数据绑定和命令模式实现:

  • 数据绑定:视图和视图模型之间通过数据绑定来实现交互。当视图模型中的数据发生变化时,视图会自动更新相应的内容,从而实现了视图和视图模型之间的数据同步。
  • 命令模式:视图和视图模型之间通过命令模式来实现交互。视图中的用户交互事件会被转换为命令,然后传递给视图模型进行处理。

MVVM架构的核心在于将视图和模型完全解耦,视图只负责渲染用户界面,而视图模型负责处理业务逻辑和数据操作。视图和视图模型之间通过数据绑定和命令模式进行交互,从而实现了解耦和职责分离。

 

2.代码解析

实例场景:两个输入值,计算他们的和,得到一个结果

ViewModel基类:

namespace WpfApp1.ViewModels
{    
    class NotificationObject : INotifyPropertyChanged
    {
        //ViewModel的某个属性借助Binding关联到View上的控件属性
        //Binding会侦听该事件的发生(属性值更改时发生),并把改变后的属性值发送到界面
        public event PropertyChangedEventHandler PropertyChanged;

        public void RaisePropertyChanged(string propertyName)
        {
            if(this.PropertyChanged!=null)
            {
                //触发属性更改事件
                this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}

ViewModel类:

namespace WpfApp1.ViewModels
{
    class MainWindowViewModel:NotificationObject
    {
        private double input1;
        //Binding可以传递控件属性到后台,但是属性值改变必须通过RaisePropertyChanged才能通知到前台
        public double Input1
        {
            get { return input1; }
            set{
                input1 = value;
                this.RaisePropertyChanged("Input1");
            }
        }

        private double input2;
        public double Input2
        {
            get { return input2; }
            set
            {
                input2 = value;
                this.RaisePropertyChanged("Input2");
            }
        }

        private double result;
        public double Result
        {
            get { return result; }
            set
            {
                result = value;
                this.RaisePropertyChanged("Result");
            }
        }

        public DelegateCommand AddCommand { get; set; }       

        public MainWindowViewModel()
        {
            //初始化命令
            this.AddCommand = new DelegateCommand(Add);
        }
        
        private void Add(object paramater)
        {
            //属性值改变,触发set,通知binding
            this.Result = Input1 + Input2;
        }
    }
}

CallerMemberName改进:

//CallerMemberName:允许获取方法调用方的方法或属性名称。
public void RaisePropertyChanged([CallerMemberName]string propertyName="")
{
    if(this.PropertyChanged!=null)
    {
        //触发属性更改事件
        this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

private double input1;
public double Input1
{
    get { return input1; }
    set{
        input1 = value;
        this.RaisePropertyChanged();//不需要指定属性名称
    }
}

DelegateCommand类:

namespace WpfApp1.Command
{
    class DelegateCommand : ICommand
    {
        public event EventHandler CanExecuteChanged;
        
        Action<object> ExcuteAction { get; set; }
        public Func<object, bool> CanExcuteFunc { get; set; }  
        
        public DelegateCommand(Action<object> action)
        {
            this.ExcuteAction=action;
        }

        public bool CanExecute(object parameter)
        {
            if (this.CanExcuteFunc == null)
                return true;
            return this.CanExcuteFunc(parameter);
        }
        
        //定义调用此命令时要调用的方法
        public void Execute(object parameter)
        {
            if (ExcuteAction == null)
                return;
            //执行这个委托传递的方法
            ExcuteAction(parameter);
        }
    }
}

扩展:上述Button为例,只有点击Click时才会触发命令发送,显然这是不够的,界面中除了点击行为以外,还有很多其他行为,诸如鼠标移入鼠标移出双击等等,可用使用Triggers绑定命令,如下:

 <!--例子二: 普通控件内的使用-->               
<Button
    Content="ED Label"
    FontSize="20"
    Foreground="Pink">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="xxx">
            <i:InvokeCommandAction Command="{Binding xxx}" CommandParameter="{Binding xxx}"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
</Button>
posted @ 2024-02-24 16:18  茜茜87  阅读(3)  评论(0编辑  收藏  举报