【发布时间】:2011-10-10 13:04:58
【问题描述】:
我对 ComboBox 不反映其 ItemsSource 所绑定的集合的属性的变化感到悲痛。
有一棵树由包含设置对象的类别对象的类别可观察集合组成。某些设置定义了其他设置允许的值域的表示名称。这些分布在多个类别中,但使用 LINQ 的小技巧会产生一个 ObservableCollection,其中 ChannelCategory 公开属性 ChannelNumber 和 ChannelTitle。
ChannelCategory.ChannelTitle 是 StringSetting,ChannelNumber 是 int,ChannelTitle 为其提供显示字符串的不可变标识值。省略大量但不相关的其他节点,我们有以下内容:
Channels
ChannelCategory
ChannelNumber = 1
ChannelTitle = "caption for channel one"
ChannelCategory
ChannelNumber = 2
ChannelTitle = "caption for channel two"
ChannelCategory
ChannelNumber = 3
ChannelTitle = "caption for channel three"
...
这个 Channels 集合由一个类的属性准备和公开,该类实例化并添加到 XAML 中的窗口资源字典(可作为 StaticResource 访问)。这种安排允许我以声明方式将组合框绑定到 Channels
<ComboBox VerticalAlignment="Center" Grid.Column="2"
ItemsSource="{Binding Source={StaticResource cats}, Path=Channels}"
DisplayMemberPath="ChannelTitle.Editor"
SelectedValuePath="ChannelNumber"
SelectedValue="{Binding Editor}"
/>
这一切都有效,但其他地方对 ChannelTitle 值的编辑不会反映在组合框列表中显示的值中。
各种带有断点的调试技巧和 DropDownOpened 事件使我能够确定更新可从 ItemsSource 引用的集合中获得。
最后我们找到了谜团。为什么组合框没有检测到集合元素的更改?集合本身是一个 ObservableCollection,因此它应该通知属性更改。
集合的元素都是ChannelCategory,是一个DependencyObject,ChannelCategory.ChannelTitle是一个DependencyProperty。
我认为问题是我既没有在集合中添加也没有删除项目,所以就集合而言,它具有相同的元素,因此没有改变。
任何人都可以建议一种策略来更改 ChannelTitle 以导致 Channels 集合通知更改以便组合框更新吗?
Rachel 的建议如下所示。在我的应用程序的上下文中,复杂性要高得多,因为每个 ChannelCategory 都拥有一组设置对象,因此更改的值是集合中对象的属性,它是 ItemsSource 绑定到的集合中对象的属性.但雷切尔建议的精髓只需要在两个层面上应用即可。
public class ObservableChannelCollection : ObservableCollection<ChannelCategory>
{
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)
foreach (ChannelCategory channel in e.NewItems)
channel.PropertyChanged += channel_PropertyChanged;
if (e.OldItems != null)
foreach (ChannelCategory channel in e.OldItems)
channel.PropertyChanged -= channel_PropertyChanged;
base.OnCollectionChanged(e);
}
void channel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
OnPropertyChanged(e);
}
}
【问题讨论】:
标签: wpf binding itemssource