属性 更改时,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;
    }
}