属性 更改时,MVVMLight Toolkit 更改未反映出来
MVVMLight Toolkit changes not reflected when property is changed
我在我的 WPF
项目中使用 MVVMLight Toolkit。我所有的 ViewModel
都来自工具包的 ViewModelBase
class,它为您实现 INotifyPropertyChanged
并完成所有通知工作。
我目前的设置非常简单。我有一个 Person
class 和一个 Name
属性.
public class Person
{
public string Name { get; set; }
}
我的 window 有一个 TextBlock
和一个 Button
,而 TextBlock
我绑定 Name
属性 Person
class 我拥有的对象。 DataContext
使用 ViewModelLocator
class.
设置
<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
在加载 window 时显示在 TextBlock
中(它确实如此),并在单击按钮时更改为 Jane
(它没有't).
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
事件,因为联系setter没有被执行。您可以使用以下技术之一解决此问题:
也在您的模型中实施 INotifyPropertyChanged class
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;
}
}
我在我的 WPF
项目中使用 MVVMLight Toolkit。我所有的 ViewModel
都来自工具包的 ViewModelBase
class,它为您实现 INotifyPropertyChanged
并完成所有通知工作。
我目前的设置非常简单。我有一个 Person
class 和一个 Name
属性.
public class Person
{
public string Name { get; set; }
}
我的 window 有一个 TextBlock
和一个 Button
,而 TextBlock
我绑定 Name
属性 Person
class 我拥有的对象。 DataContext
使用 ViewModelLocator
class.
<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
在加载 window 时显示在 TextBlock
中(它确实如此),并在单击按钮时更改为 Jane
(它没有't).
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
事件,因为联系setter没有被执行。您可以使用以下技术之一解决此问题:
也在您的模型中实施 INotifyPropertyChanged class
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;
}
}