【问题标题】:MVVMLight Toolkit changes not reflected when property is changed属性更改时未反映 MVVMLight Toolkit 更改
【发布时间】:2020-05-02 19:45:16
【问题描述】:

我在我的WPF 项目中使用MVVMLight Toolkit。我所有的ViewModels 都派生自工具包的ViewModelBase 类,它为您实现INotifyPropertyChanged 并完成所有通知工作。

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

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

我的窗口有一个TextBlock 和一个Button,并且我将Person 类对象的Name 属性绑定到我拥有的TextBlockDataContext 是使用 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】:

    设置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;
        }
    }
    

    【讨论】:

    • 是的,我知道您可以在模型中实现INotifyPropertyChanged,但希望我不必这样做,因为我拥有的不仅仅是几个属性。另外,用所有垃圾污染模型似乎是一种不好的做法。
    • 我本来希望使用第二种方法,但它仍然无法更新 GUI。
    • 第二种方法的问题是设置Contact.Name甚至不调用setter,所以ContactName中的setter永远不会被调用。
    • 是的,您必须将顶部的 Click 处理程序更改为 Set ContactName
    • 但这完全消除了拥有Contact 属性的需要,但我需要它来处理其他事情,而不仅仅是显示数据。但感谢您清理一切。
    猜你喜欢
    • 2012-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-12
    • 2015-03-06
    • 1970-01-01
    • 2020-05-18
    • 1970-01-01
    相关资源
    最近更新 更多