[MVVMLight Toolkit的更改不会在更改属性时反映出来

问题描述 投票:0回答:1

我正在MVVMLight Toolkit项目中使用WPF。我的所有ViewModel都来自工具箱的ViewModelBase类,该类为您实现了INotifyPropertyChanged并完成了所有通知工作。

我当前的设置非常简单。我有一个具有单个Person属性的Name类。

public class Person
{
    public string Name { get; set; }
}

我的窗口有一个TextBlock和一个Button,并将TextBlock类对象的Name属性绑定到PersonDataContext是使用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";
    }
}

我想念什么?

c# wpf data-binding mvvm-light inotifypropertychanged
1个回答
0
投票

设置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;
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.