我正在MVVMLight Toolkit项目中使用WPF
。我的所有ViewModel
都来自工具箱的ViewModelBase
类,该类为您实现了INotifyPropertyChanged
并完成了所有通知工作。
我当前的设置非常简单。我有一个具有单个Person
属性的Name
类。
public class Person
{
public string Name { get; set; }
}
我的窗口有一个TextBlock
和一个Button
,并将TextBlock
类对象的Name
属性绑定到Person
。 DataContext
是使用ViewModelLocator
类设置的。
<Window x:Class="BindingTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ignore="http://www.galasoft.ch/ignore"
mc:Ignorable="d ignore"
Height="300" Width="300"
Title="MVVM Light Application"
DataContext="{Binding Main, Source={StaticResource Locator}}">
<Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Center"
Text="{Binding Contact.Name}"/>
<Button Grid.Row="1" Content="Click" Command="{Binding ClickCommand}"/>
</Grid>
</Window>
在我的ViewModel
中,我在构造函数中将Name
设置为Tom
,并在单击按钮时对其进行了更改。我希望Tom
会在加载窗口时显示在TextBlock
中(确实如此),并且在单击按钮时会显示为Jane
(实际上没有)。
public class MainViewModel : ViewModelBase
{
private Person _contact = new Person();
public Person Contact
{
get { return _contact; }
set { Set(ref _contact, value); }
}
public RelayCommand ClickCommand { get; private set; }
public MainViewModel(IDataService dataService)
{
Contact = new Person() { Name = "Tom" };
ClickCommand = new RelayCommand(Click);
}
public void Click()
{
Contact.Name = "Jane";
}
}
我想念什么?
设置Contact.Name
不会触发INotifyPropertyChanged.NotifyChanged
事件,因为未执行联系人设置器。您可以通过以下一种方法解决此问题:
在模型类中也实现INotifyPropertyChanged
public class Person : INotifyPropertyChanged
{
private string _name;
public string Name
{
get => _name;
set
{
_name = value;
if (PropertyChanged != null)
PropertyChanged(this, nameof(Name));
}
}
public event PropertyChangedHandler PropertyChanged;
}
或将PersonClass包装在PersonViewModel中
public class PersonViewModel : ViewModelBase
{
private readonly Person _person;
public PersonViewModel(Person person)
{
_person = person;
}
public string Name
{
get => _person.Name;
set
{
var name = _person.Name;
if (Set(ref name, value))
_person.Name = name;
}
}
}
和在MainViewModel中:
private PersonViewModel _contactViewModel
public PersonViewModel Contact
{
get { return _contactViewModel ?? (_contactViewModel = new PersonViewModel(_contact)); }
}
或在MainViewModel中创建一个单独的ContactName属性
...,并在绑定和Click事件处理程序中使用ContactName
而不是Contact.Name
。
public string ContactName
{
get { return _contact.Name; }
set
{
var name = _contact.Name;
if (Set(ref name, value))
_contact.Name = name;
}
}