【问题标题】:WPF - Trigger a change of a field contained in a normal property vs ObservableCollection propertyWPF - 触发包含在普通属性与 ObservableCollection 属性中的字段的更改
【发布时间】:2021-12-03 14:26:03
【问题描述】:

在下面的代码示例中,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 中更新。但我的问题仍然存在:为什么即使 person 的 Name 属性没有实现 INotifyChanged 机制,TextBlock 也会更新?

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# wpf xaml inotifypropertychanged


    【解决方案1】:

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

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

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

    【讨论】:

      【解决方案2】:

      使用INotifyPropertyChanged:

      class CarList : INotifyPropertyChanged
          {
             
              public string ModelNumber { get; set; }
      
              private string modelName;
              public string ModelName
              {
                  get { return modelName; }
                  set
                  {
                      modelName = value;
                      OnPropertyChanged("ModelName");
                  }
              }
      
              public event PropertyChangedEventHandler PropertyChanged;
              public void OnPropertyChanged([CallerMemberName] string pchange = "")
              {
                  if (PropertyChanged != null)
                      PropertyChanged(this, new PropertyChangedEventArgs(pchange));
              }
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-11-25
        • 2013-03-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多