【问题标题】:How to make an ObservableCollection update when an item property is changed更改项目属性时如何进行 ObservableCollection 更新
【发布时间】:2017-11-19 19:28:26
【问题描述】:

我已经多次看到这个问题发布(并回答)了,但我似乎仍然无法弄清楚我错过了什么......

我有一个带有复选框列表的窗口,我希望能够从代码隐藏中动态启用/禁用列表中的复选框。为此,我有几个单选按钮调用代码隐藏函数来切换 VisibleFeatures 集合中第一个条目的“启用”属性。理想情况下,这会导致第一个复选框 + 文本启用/禁用,但不会发生 UI 更改。

我做错了什么?

视图模型:

public class MyFeature
{
   private bool _supported;
   private bool _enabled;
   private bool _selected;
   public string Name { get; set; }

   public bool Supported
   {
      get { return _supported; }
      set { _supported = value; NotifyPropertyChanged("Supported"); }
   }
   public bool Enabled
   {
      get { return _enabled; }
      set { _visible = value; NotifyPropertyChanged("Enabled"); }
   }
   public bool Selected
   {
      get { return _selected; }
      set { _selected = value; NotifyPropertyChanged("Selected"); }
   }

   public MyFeature(string name)
   {
      Name = name;
      _supported = false;
      _enabled = false;
      _selected = false;
   }

   public event PropertyChangedEventHandler PropertyChanged;
   private void NotifyPropertyChanged(string propertyName)
   {
      if (PropertyChanged != null)
      {
         PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
      }
   }
}

public ObservableCollection<MyFeature> VisibleFeatures { get; set; }

void VisibleFeatures_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
   if (e.NewItems != null)
      foreach (MyFeature item in e.NewItems)
         item.PropertyChanged += MyFeature_PropertyChanged;

   if (e.OldItems != null)
      foreach (MyFeature item in e.OldItems)
         item.PropertyChanged -= MyFeature_PropertyChanged;
}

void MyFeature_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
   // NotifyPropertyChanged() defined again elsewhere in the class
   NotifyPropertyChanged("VisibleFeatures");
}

public Init()
{
   VisibleFeatures = new ObservableCollection<MyFeature>();
   VisibleFeatures.CollectionChanged += VisibleFeatures_CollectionChanged;
   VisibleFeatures.Add(new MyFeature("Feature1"));
   VisibleFeatures.Add(new MyFeature("Feature2"));
   ...
}

XAML:

<StackPanel>
   <ListView ItemsSource="{Binding VisibleFeatures}">
      <ListBox.ItemTemplate>
         <DataTemplate>
            <StackPanel IsEnabled="{Binding Enabled, Mode=TwoWay}">
               <CheckBox IsChecked="{Binding Selected, Mode=TwoWay}">
                  <TextBlock Text="{Binding Name}" />
               </CheckBox>
            </StackPanel>
         </DataTemplate>
      </ListBox.ItemTemplate>
   </ListView>
</StackPanel>

【问题讨论】:

  • 您已经说过“它不起作用”,但您没有说如何它不起作用。您在做什么以及遇到什么行为?
  • 问题更新了我想要实现的目标,以及我想要如何做到这一点。

标签: c# xaml binding observablecollection


【解决方案1】:

您的 MyFeature 类需要声明它实现了接口INotifyPropertyChanged。否则,将不会从 XAML 生成侦听器来侦听您的属性更改通知。

此外,从您的示例中,我认为通知 VisibleFeatures 更改没有用。

【讨论】:

    【解决方案2】:

    从 INotifyPropertyChanged 接口派生您的类“MyFeature”。

    为了在视图中反映您在可观察集合中所做的运行时更改,必须从 INotifyPropertyChanged 接口派生您的视图模型类(此处为 MyFeature 类)。

    此外,建议在任何使用绑定属性的地方使用相同的绑定属性实例,而不是创建新实例。

    【讨论】:

    • 我不确定您在此处指的是什么:“此外,建议在使用绑定属性的任何地方使用相同的绑定属性实例,而不是创建新实例。”
    • 使用首次创建的 VisibleFeatures 属性实例,因为您已将此属性绑定为 ListView 的 ItemsSource。如果您为此属性创建了任何新实例,您在运行时所做的更改可能不会反映在视图中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-05
    • 2012-04-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多