20240216 WPF 实现数据修改后,主动通知界面更改以及MVVMLight 的使用

1)按钮和下面的文本框分别关联的对应的函数和一个属性;

2)关联对应的实例化的一个数据;

3)这个类中需要指定INotifyPropertyChanged接口,然后实现该接口对应的事件声明public event PropertyChangedEventHandler PropertyChanged;

4)Name参数,需要使用完全方式声明,在set中,增加对事件的调用,相当于,每次修改值的时候就出发事件,然后界面会收到该事件;发送事件中,一个参数中包括了事件的Name,形成对应;

5)界面收到后,会根据该参数进行更新。

            <Button Name="bt1" Content="点击我" Command="{Binding myCommand}"  Margin="5" Height="30"/>
            <TextBox Name="tx1" Text="{Binding Name}"  Margin="5" Height="30"/>


指定对应的数据源
            this.bt1.DataContext = new MainViewModel();
            this.tx1.DataContext = this.bt1.DataContext;

声明的类
    public class MainViewModel:INotifyPropertyChanged
    {
        private string name;

        public string Name
        {
            get { return name; }
            set { 
                name = value;
                PropertyChanged?.Invoke(this,new PropertyChangedEventArgs("Name"));
            }
        }

        public ClassMyCommand myCommand { get; set; }
        public MainViewModel() {
            myCommand = new ClassMyCommand(Show);
            Name = "first";
        }

        public event PropertyChangedEventHandler PropertyChanged;

        public void Show()
        {
            Name = "点击了我。";
            MessageBox.Show(Name);
        }
    }

6)在上面基础上修改简化,

首先声明一个基类,依然使用原来的通知接口,里面实现一个方法,用于实现参数修改后,调用事件

    public class NotifyPropertyChangedBaseClass : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged([CallerMemberName]string propertyname = "")//通过该方法可以直接获取调用者的名称 前提是需要有默认参数
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyname));
        }
    }



    public class MainViewModel: NotifyPropertyChangedBaseClass  //INotifyPropertyChanged 修改原来基于接口,现在基于基类
    {
        private string name;

        public string Name
        {
            get { return name; }
            set { 
                name = value;
                //PropertyChanged?.Invoke(this,new PropertyChangedEventArgs("Name"));
                //OnPropertyChanged("Name");//参数可以不写,
                OnPropertyChanged();//参数可以不写,

            }
        }

        public ClassMyCommand myCommand { get; set; }
        public MainViewModel() {
            myCommand = new ClassMyCommand(Show);
            Name = "first";
        }

        //public event PropertyChangedEventHandler PropertyChanged;//删除掉这个

        public void Show()
        {
            Name = "点击了我。";
            MessageBox.Show(Name);
        }
    }

7)使用MVVMLight

通过NuGet安装该安装包后,上面自己写的命令绑定和通知都可以删除;直接使用社区包中已经封装好的函数

    public class MainViewModel: ViewModelBase //现在基于基类
    {
        private string name;
        public string Name
        {
            get { return name; }
            set { 
                name = value;
                RaisePropertyChanged();//调用事件

            }
        }
        public RelayCommand myCommand { get; set; }//定义命令
        public MainViewModel() {
            myCommand = new RelayCommand(Show);
            Name = "first";
        }
        public void Show()
        {
            Name = "点击了我。";
            MessageBox.Show(Name);
        }
    }

其中是三个点

基类——ViewModelBase //现在基于基类

事件调用——RaisePropertyChanged();//调用事件

命令定义——public RelayCommand myCommand { get; set; }//定义命令

命令赋值——myCommand = new RelayCommand(Show);

其中命令 有两个重载,一个带参数,一个努努带参数,带参数的调用函数的时候需要传递带参数的函数。根据需要调用。

GalaSoft.MvvmLight.CommandWpf.RelayCommand

GalaSoft.MvvmLight.CommandWpf.RelayCommand<T>

如果是传递参数

        public RelayCommand<string> myCommand{ get; set; }//定义命令
        public MainViewModel() {
            myCommand = new RelayCommand<string> (Show);
            Name = "first";
        }
        public void Show(string txt )
        {
            Name = "点击了我。";
            MessageBox.Show(txt);
        }


XAML中需要将参数传递进来
        Command="{Binding myCommand}" 
        CommandParameter="{Binding ElementName=tx2, Path=Text}"

8)MVVMLight中的 消息注册和发送

      //启动的时候定义一个消息接收器,当接收到消息,且关键字是 myToken1,这可以自定义,后就会自己执行委托 Show  
      Messenger.Default.Register<string>(this,"myToken1",Show);

          Messenger.Default.Send( txt, "myToken1");//传递需要参数和 标识,用于和注册的匹配

9)使用Microsoft.Toolkit.Mvvm 包或者CommunityToolkit.Mvvm 两个是一样使用的,建议使用后面的。

消息注册换了一个名字

            //启动的时候定义一个消息接收器,当接收到消息,且关键字是 myToken1,这可以自定义,后就会自己执行委托 Show  

            //Messenger.Default.Register<string>(this, "myToken1", Show);
            WeakReferenceMessenger.Default.Register<string, string>(this, "myToken1", (o, e) => {
                Show(e);
            });
  public class MainViewModel: ObservableObject //ViewModelBase  MVVMLight //现在基于基类Microsoft.Toolkit.Mvvm.ComponentModel.ObservableObject
  {
      private string name;
      public string Name
      {
          get { return name; }
          set { 
              name = value;
              //RaisePropertyChanged();//调用事件
              OnPropertyChanged();//调用事件

          }
      }
      public RelayCommand<string> myCommand{ get; set; }//定义命令
      public MainViewModel() {
          myCommand = new RelayCommand<string> (Show);
          Name = "first";
      }
      public void Show(string txt )
      {
          Name = "点击了我。";
          //MessageBox.Show(txt);
          WeakReferenceMessenger.Default.Send( txt, "myToken1");//传递需要参数和 标识,用于和注册的匹配
      }
  }

其他都没有变。

基类——ObservableObject//现在基于基类

事件调用——OnPropertyChanged();//调用事件

命令定义——public RelayCommand myCommand { get; set; }//定义命令

命令定义——public RelayCommand<string> myCommand{ get; set; }//定义命令 带参数的

命令赋值——myCommand = new RelayCommand<string> (Show);

通过命令牌发送消息 触发事件——

//Messenger.Default.Send( txt, "myToken1");//传递需要参数和 标识,用于和注册的匹配 MVVMLight
WeakReferenceMessenger.Default.Send( txt, "myToken1");//传递需要参数和 标识,用于和注册的匹配

注册事件——

            //启动的时候定义一个消息接收器,当接收到消息,且关键字是 myToken1,这可以自定义,后就会自己执行委托 Show  

            //Messenger.Default.Register<string>(this, "myToken1", Show);
            WeakReferenceMessenger.Default.Register<string, string>(this, "myToken1", (o, e) => {
                Show(e);})

说明  o 的类型是 this  <string, string> 第一个string 对应的是e,第二个对应的是 "myToken1" 如果传递的不是string就要在注册的时候也修改

对于有些public RelayCommand myCommand 执行过程中这个命令不想被再次执行,例如执行程序时会比较长时间,或者开启了子进程之类的,这时不想该命令再次执行时,可以通过下面的方式处理:

1)首先命令初始化的时候,之前一直使用传递一个参数,还有一个可以传递两个参数的,就是可以传递一个返回bool的函数;

 RelayCommand = new RelayCommand(() => { }, () => { return true; });

具体两个函数可以自己添加逻辑,如果返回的是false就不能再执行,如果要想动态改变,则可以提前定义个属性(带通知的),然后返回这个值;通过再任意位置修改这个值,就可以修改他的可执行属性。

  //
  private bool  _isCanexecute = true;
  public bool  IsCanExecute { get { return _isCanexecute; } set { _isCanexecute = value; OnPropertyChanged(); } }

public RelayCommand RelayCommand { get; set; }

          RelayCommand = new RelayCommand(() => { 
              Task.Run(() => {
                  IsCanExecute = false; 
                  for (int i = 0; i < 1000; )
                  {
                     #自己的逻辑
                  }
                  IsCanExecute = true;
              });
          }, () => { return IsCanExecute; });

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值