Изменения MVVMLight Toolkit не отражаются при изменении свойства - PullRequest
0 голосов
/ 16 января 2020

Я использую 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";
    }
}

Что мне не хватает?

1 Ответ

1 голос
/ 16 января 2020

Настройка 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)); }
}

Или создайте отдельное свойство ContactName в MainViewModel

... и используя ContactName вместо Contact.Name в привязке и обработчике события Click.

public string ContactName
{
    get { return _contact.Name; }
    set 
    {
        var name = _contact.Name;
        if (Set(ref name, value))
            _contact.Name = name;
    }
}
...