在Xaml里面写的控件绑定的是属性,那么在MainViewModel里面一定要有相应的属性,并且在构造函数里面要用属性接收相应的参数。
<Grid>
<StackPanel>
<TextBox Text="{Binding Name}"/>
<Button Command="{Binding ShowCommand}" Height="50" Content="Show"/>
</StackPanel>
</Grid>
public class MainViewModel
{
public Mycommand ShowCommand { get; set; }
public string Name { get; set; }
public MainViewModel()
{
Name = "Hello";
//刚好需要一个委托参数,把Show方法传进去
ShowCommand = new Mycommand(Show);
}
}
这样才能在MainWindow里面用上下文接收到MainViewModel
namespace WPFTest
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
//整个MainViewModel作为数据源传给xmal
this.DataContext = new MainViewModel();
}
}
}
但是可以发现,<TextBox/>
响应的是MainViewModel
构造函数里面的属性set和get值,而<Button/>
拿到的ShowCommand
属性接受的 Mycommand()
类实例化时传进来的委托函数Show()
,而Show()
方法里面Name
属性已经改为了 "Hello"
;因此两个控件出线的结果不一致,这个时候如果要想一致,需要一个通知。
通知INotifyPropertyChanged
在MainViewModel上继承一个接口INotifyPropertyChanged
public class MainViewModel:INotifyPropertyChanged
引用名称空间:
using System.ComponentModel;
实现接口
public event PropertyChangedEventHandler PropertyChanged;
这个接口实现出来了一个事件,用来侦听属性设置值的改变的,因此需要将需要被侦听的属性改为propfulll形式,在set里面将事件Invoke出来
public string Name
{
get { return name; }
set
{
name = value;
//若事件不为空,则Invoke
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Name"));
}
}
ViewModelBase封装INotifyPropertyChanged
如果每个属性都要这么去写,那么代码就会有累赘,所以将这个属性侦听封装一个类
namespace WPFTest
{
class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
//加上特性[CallerMemberName],参数默认为空
public void OnPropertyChanged([CallerMemberName] string propertyName="")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
当界面初始化时,用上下文时,发现有类继承了INotifyPropertyChanged
,则自动订阅事件PropertyChanged
。