C#语法——消息,MVVM的核心技术。

在C#中消息有两个指向,一个指向Message,一个指向INotify。这里主要讲INotify。html

INotify也有人称之为[通知],无论叫消息仍是通知,都是一个意思,就是传递信息。前端

消息的定义架构

INotify消息实际上是一个接口,接口名叫INotifyPropertyChanged。接口定义以下:async

 //向客户端发出某一属性值已更改的通知。
 public interface INotifyPropertyChanged
 {
     //在更改属性值时发生。
     event PropertyChangedEventHandler PropertyChanged;
 }

定义很简单,咱们能够看到这个接口只定义了一个事件属性——PropertyChanged。因此这个PropertyChanged就是消息的核心了。学习

那么学习应用消息的方法就出现了,即,建立一个继承INotifyPropertyChanged接口的类,而后在类内,实现PropertyChanged就能够了。优化

消息的应用this

上面介绍消息是用来传递信息的。那么可能会有同窗好奇,引用类型的对象不就能够封装传递信息吗?为何还要用消息呢?spa

由于有些数据是存储在非引用类型的对象中的。好比字符串,或数字等。双向绑定

为了让字符串、数字等数据的修改也能如引用类型同样,能够传递回给源,就须要使用消息了。xml

下面咱们来看下消息的基础用法。

首先,咱们使用WPF建立一个项目,而后建立一个页面,起名为WindowNotify,编辑内容以下:

<Window x:Class="WpfApplication.WindowNotify"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="WindowNotify" Height="120" Width="200">
    <Grid>
        <StackPanel>
            <TextBox Name="txtName" VerticalAlignment="Top" Height="24" ></TextBox>
            <TextBox Name="txtNameNotify" VerticalAlignment="Top"  Height="24" ></TextBox>
            <Button Click="Button_Click" Height="30" Content="查看结果"></Button>
        </StackPanel>
    </Grid>
</Window>

接下来,编辑Xaml对于的cs文件,内容以下:

public partial class WindowNotify : Window
{ 
    private string _KName = "Kiba518"; 
    public string KName
    {
        get { return _KName; }
        set { _KName = value; }
    }
    WindowNotifyViewModel vm;
    public WindowNotify()
    {
        InitializeComponent();
        vm = new WindowNotifyViewModel(); 
        Binding bding = new Binding();
        bding.Path = new PropertyPath("KName");
        bding.Mode = BindingMode.TwoWay; 
        bding.Source = vm; 
        txtNameNotify.SetBinding(TextBox.TextProperty, bding);  
        txtName.Text = KName;
        txtNameNotify.Text = vm.KName; 
    }
    private void Button_Click(object sender, RoutedEventArgs e)
    {
        MessageBox.Show("[txtName:" + KName + "]     |    [txtNameNotify:" + vm.KName + "]");
    } 
}
public class WindowNotifyViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    private string _KName = "Kiba518Notify";
    public string KName
    {
        get { return _KName; }
        set
        {
            _KName = value;
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs("KName"));
            }
        }
    }
}

这里咱们建立了一个ViewModel——WindowNotifyViewModel,咱们让这个VM继承INotifyPropertyChanged,而后定义了一个KName属性,并定义了PropertyChanged事件触发的位置。

有同窗可能会好奇,PropertyChanged事件是什么时候被赋值的呢?别心急,请耐心往下看。

ViewModel定义完成以后,咱们再看Xaml对应的cs文件。这里咱们也定义了一个KName属性。而后初始化时,将cs文件的KName和VM的KName分别赋值给前台定义的两个TextBox控件。

这里用vm的KName属性赋值时,稍微有点特别,稍后再介绍。

而后咱们运行页面,并修改两个文本框内的值。再点击查看结果按钮。获得界面以下:

能够从图中看到,界面修改了TextBox的Text属性,WindowNotifyViewModel的KName属性对修改的值进行了同步,而WindowNotify的KName没有同步。

看完结果,咱们回过来看下VM的KName的奇怪赋值方式。咱们先看第一句:

Binding bding = new Binding();

这里的Binding是绑定的意思,这行代码很明显是用来定义一个绑定。

绑定是个很差理解的词,咱们该如何理解呢?

很简单,咱们能够将绑定理解为套索,既然是套索,那么就该有两个属性,一个是套头,一个是套尾。

那么声明了套索以后,咱们便须要为套索的索尾赋值了,即数据源的这一方。 

代码里,咱们经过Binding的Path和Source设置了索尾的数据源和数据源绑定的属性。以后咱们还设置了绑定模式是双向绑定,即双方修改都会进行数据传递。

设置好了套索后,咱们在让TextBox控件本身转进套头里,并设置了TextBox控件绑定的属性。代码以下:

txtNameNotify.SetBinding(TextBox.TextProperty, bding);  

在咱们TextBox控件本身转进套头里的时候,会对数据源的PropertyChanged进行赋值,这样咱们就实现了字符串数据的传输。

固然,这样赋值看起来比较笨拙。那么有更简便的方法吗。

答案固然是:有。

MVVM的基础应用

上面的代码已经实现了ViewModel,那么只要在这个基础上进行优化,便可实现最简单的MVVM的应用。

优化Xaml代码以下:

<StackPanel> 
    <TextBox Name="txtNameNotify" Text="{Binding KName}" VerticalAlignment="Top"  Height="24" ></TextBox>
    <Button Click="Button_Click" Height="30" Content="查看结果"></Button>
</StackPanel>

优化Xaml.cs代码以下: 

 public partial class WindowNotify : Window
 {  
     public WindowNotify()
     {
         InitializeComponent();
         this.DataContext = new WindowNotifyViewModel(); 
      
     }
     private void Button_Click(object sender, RoutedEventArgs e)
     {
         var vm = this.DataContext as WindowNotifyViewModel;
         MessageBox.Show("[txtNameNotify:" + vm.KName + "]");
     } 
 }
 public class WindowNotifyViewModel : INotifyPropertyChanged
 {
     public event PropertyChangedEventHandler PropertyChanged;
     private string _KName = "Kiba518";
     public string KName
     {
         get { return _KName; }
         set
         { 
             _KName = value;
             if (this.PropertyChanged != null)
             {
                 this.PropertyChanged(this, new PropertyChangedEventArgs("KName"));
             }
         }
     }
 }

从上面的代码中,咱们能够看到在Xaml文件中,Text属性可使用{Binding KName}这种简写的模式,来实现刚才那个复杂的binding赋值。

而在Xaml.cs文件中,咱们将VeiwMode赋值给了DataContext这个数据上下文,而后,咱们就看到了,前台直接使用了VM里的属性。

这样简单的MVVM就实现了。

简洁的ViewModel

在上面咱们看到了ViewModel的建立和使用,但ViewMode中每一个属性都要设置成如此复杂的形态,稍微有点难受。

那么,咱们来用CallerMemberName继续简化这个ViewModel。

优化后的代码以下:

public class WindowNotifyViewModel : BaseViewModel
{ 
    private string _KName = "Kiba518";
    public string KName
    {
        get { return _KName; }
        set
        { 
            _KName = value;
            OnPropertyChanged(); 
        }
    }
}
public class BaseViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged([CallerMemberName]string propertyName = "")
    { 
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    } 
}

如上所示,咱们定义了一个BaseViewModel,并在BaseViewModel里面定义方法OnPropertyChanged,并在里面实现事件PropertyChanged的触发定义。

最后咱们经过CallerMemberName特性,在方法OnPropertyChanged里来获取触发该方法的属性的名称。

而后咱们就实现了,比较简洁的ViewModel。

PS:CallerMemberName的用法就好像param参数同样,只要如上所示,写进去便可。

结语

到此,消息的应用就讲完了。消息毫无疑问是MVVM的技术核心。学会消息才能更好的理解MVVM。

而且学会消息,还能帮助咱们更好的理解如今流行的前端JS的MVVM。虽然实现方式不同,但道理是同样的。

C#语法——元组类型

C#语法——泛型的多种应用

C#语法——await与async的正确打开方式

C#语法——委托,架构的血液

C#语法——事件,逐渐边缘化的大哥。

我对C#的认知。

----------------------------------------------------------------------------------------------------

注:此文章为原创,任何形式的转载都请联系做者得到受权并注明出处!
若您以为这篇文章还不错,请点击下方的推荐】,很是感谢!

 

相关文章
相关标签/搜索