首页 > 解决方案 > WPF - 触发包含在普通属性与 ObservableCollection 属性中的字段的更改

问题描述

在下面的代码示例中,Person 类型的属性与 ObesrvableCollection 类型的属性发生了不同的行为。在这两种情况下,TextBox 都必须编辑 Person.Name 字段。对于这两种情况,TextBlock 都用于在字段上显示更新的值。在 ObservableCollection 的情况下,TextBlock 在 TextBox 上完成编辑后,在“淡出焦点”事件之后更新。在普通属性的情况下,当 TextBox 中的值发生变化时,TextBlock 不会更新,从而淡出焦点。有什么区别?在 ObservableColletion 的情况下,字段值得到更新,幕后发生了什么?

Xaml 视图:

<UserControl ...>
    <StackPanel>
        <ListBox ItemsSource="{Binding People}" Height="100">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <TextBox Text="{Binding Name}"/>
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

        <TextBlock Text="{Binding People[0].Name}"/>

        <TextBox Text="{Binding Mike.Name}"/>
        <TextBlock Text="{Binding Mike.Name}"/>
    </StackPanel>
</UserControl>

视图模型:

class MainViewModel : BindableBase
    {

        private Person _mike;
        public Person Mike
        {
            get { return _mike; }
            set { SetProperty(ref _mike, value); }
        }

        public ObservableCollection<Person> People { get; set; } = new ObservableCollection<Person>();

        public MainViewModel()
        {

            People.Add(new Person("Lisa"));
            People.Add(new Person("Chris"));
            People.Add(new Person("Orlando"));
        }
    }

人物类:

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

    public Person(string name)
    {
        Name = name;
    }
}

编辑:

我在我的代码中发现了这个问题。就是属性 Mike 从来没有被赋值为 person 类型的值。因此它不会在 TextBlock 中更新。但我的问题仍然存在:为什么 TextBlock 会更新,即使 person 的 Name 属性没有实现 INotifyChanged 机制?

class MainViewModel : BindableBase
    {

        private Person _mike = new Person("Mike");
        public Person Mike
        {
            get { return _mike; }
            set { SetProperty(ref _mike, value); }
        }

        public ObservableCollection<Person> People { get; set; } = new ObservableCollection<Person>();

        public MainViewModel()
        {

            People.Add(new Person("Lisa"));
            People.Add(new Person("Chris"));
            People.Add(new Person("Orlando"));
        }
    }

标签: c#wpfxamlinotifypropertychanged

解决方案


Person 需要实现BindableBase(假设为 implements INotifyPropertyChanged),您需要Name像这样设置属性:

private string _name;
public string Name
{
    get { return _name; }
    set { SetProperty(ref _name, value); }
}

目的是在添加移动删除ObservableCollection项目时发出通知;它不跟踪项目的属性。


推荐阅读