仅元素属性发生变化的 ItemsSource 和集合

2024-01-10

我对 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 访问)。这种安排允许我以声明方式将组合框绑定到通道

    <ComboBox VerticalAlignment="Center" Grid.Column="2" 
              ItemsSource="{Binding Source={StaticResource cats}, Path=Channels}"
              DisplayMemberPath="ChannelTitle.Editor"
              SelectedValuePath="ChannelNumber"
              SelectedValue="{Binding Editor}"
              />

这一切都有效,但在其他地方对 ChannelTitle 值进行的编辑不会反映在组合框列表中显示的值中。

使用断点和 DropDownOpened 事件的各种调试技巧使我能够确定更新are可从 ItemsSource 引用的集合中获取。

最后我们揭开了谜底。为什么组合框没有检测到集合元素的更改?集合本身是一个 ObservableCollection,因此它应该通知属性更改。

该集合的元素都是ChannelCategory,它是一个DependencyObject,ChannelCategory.ChannelTitle是一个DependencyProperty。

I think问题是我既没有在集合中添加也没有删除项目,因此就集合而言,它具有相同的元素,因此没有改变。

任何人都可以建议一种策略,使 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);
  }
}

ObservableCollection跟踪 Collection 本身的更改,例如Add, Remove, Reset等,但它不会跟踪集合中单个项目的更改。因此,如果您更新某个项目的属性ObservableCollection,集合不会收到有关某些内容发生更改的通知。

一种替代方法是将事件添加到ObservableCollection.CollectionChanged事件,当添加新项目时,将属性更改挂接到新项目上,这将引发集合更改事件。

void MyObservableCollection_CollectionChanged(object sender, CollectionChangedEventArgs e)
{
    if (e.NewItems != null)
    {
        foreach(MyItem item in e.NewItems)
        {
            MyItem.PropertyChanged += MyItem_PropertyChanged;
        }
    }

    if (e.OldItems!= null)
    {
        foreach(MyItem item in e.OldItems)
        {
            MyItem.PropertyChanged -= MyItem_PropertyChanged;
        }
    }
}

void MyItem_PropertyChanged(object sender, PropertyChange e)
{
    RaisePropertyChanged("MyObservableCollection");
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

仅元素属性发生变化的 ItemsSource 和集合 的相关文章

随机推荐

  • 通过将鼠标悬停在散景中突出显示多个 hex_tiles

    我尝试在十六进制图中可视化我的数据 为此 我在图类中使用 python bokeh 和相应的 hex tile 函数 我的数据属于 8 个不同类别之一 每个类别都有不同的颜色 下图显示了当前的可视化效果 I would like to ad
  • Android:SD 卡有使用功能选项吗?

    谷歌推出的一些较新设备不包含 SD 卡 而且它们似乎正在朝这个方向发展 我的问题 有没有办法将 SD 卡声明为使用功能 以防止没有外部存储的人从 Google Play 查看 下载应用程序 我意识到这不是解决问题的正确方法 但在我可以重新编
  • 在 Eclipse IDE 中运行的 Java 程序的退出代码?

    我正在使用 Eclipse 开发一个 Java 程序 该程序应根据具体条件以不同的代码退出 if veryBadError Runtime getRuntime exit 10 else if notSoBadError Runtime g
  • 使用字符串名称功能创建变量

    我正在尝试生成一个函数来在数据框架上创建一堆具有相同命名约定并使用相同逻辑的列 不幸的是 我在创建变量时遇到了一些奇怪的行为 我希望其他人可以解释这里发生了什么 df lt data frame var1 c 1 2 3 var2 c 3
  • codeigniter 加密/解密函数返回空字符串

    我正在尝试使用 codeigniter 登录 但无法这样做 然后我尝试从数据库复制密码并将其传递给 dycription gt decode 函数 它返回空字符串 这是代码 var dump this gt encryption gt de
  • XML 节点的多个分组

    我正在尝试使用 muenchian 分组按目的地和分类值对下面的输入进行分组 这对我来说是新的 所以我不确定如何正确执行此操作 输入文件将比这大得多 因此性能很重要
  • NUnit.Mocks 文档在哪里? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 NUnit 的模拟库 NUnit Mocks 的文档在哪里 我在他们中找不到任何东西官方文档 http
  • 一次读取 1 个字节的二进制文件

    我试图一次读取一个 C 语言的二进制文件 在互联网上搜索了几个小时后 我仍然无法让它检索除垃圾和 或段错误之外的任何内容 基本上 二进制文件采用列表格式 长度为 256 个项目 每个项目为 1 个字节 0 到 255 之间的无符号整数 我正
  • 修改int为float(mysql)

    我正在尝试将 MySQL 中的数据类型从 INT 更改为 FLOAT 如下所示 ALTER TABLE user MODIFY rate float 5 NOT NULL 但当前数据已被删除 有什么方法可以使用 SQL 将数据从 INT 转
  • 如何从指令调用控制器函数?

    如何从指令调用控制器函数 或者如何从控制器访问指令 ng model 例如 我使用 Angular ui 引导时间组件 当时间改变时 我需要通知控制器中的调用函数 我认为总的来说 这是组件之间双向通信的典型用例 appControllers
  • 持久化 MPMediaItemCollection 对象的方法? (选自 iPod)

    我正在制作一个应用程序 用户可以在其中选择设置选项卡中的歌曲 并根据需要在不同的视图中播放该歌曲 我希望这样 如果用户要关闭应用程序并再次重新打开它 则可以存储该项目 我设法允许用户选择并存储一首歌曲 IBAction showMediaP
  • 使用代码隐藏文件中的 VB.Net 编码填充 ASP.Net DropDownList

    我们在 ASP Net VB Net Web 表单的标记中有一个 DropDownList 我们希望使用数据集设计器创建的数据集中的数据填充 DropDownList 但我们在代码隐藏文件中使用的编码无法使用 FindControl 找到
  • VS2015 VSIX 系统内存不足异常

    我创建了一个新的 VSIX 项目并添加了一个新项目 gt 可扩展性 gt 自定义工具窗口 然后我尝试构建 但出现错误 1 gt Build started Project JSBQ Configuration Debug Any CPU 1
  • Ember数据删除失败,如何回滚

    如果我调用 destroyRecord 并且它在服务器上失败 它也会从本地存储和 UI 中消失 如果删除失败 我需要以某种方式 回滚 我尝试过这样的事情 item destroyRecord then function Notify suc
  • 从命令行构建解决方案

    我正在尝试使用命令行从 cmd 文件构建许多解决方案来处理整个构建 这是构建解决方案的行 for f i in CFG bld lst do set OUT i Release REBUILD call out C Program File
  • Web 应用程序中用于 Retina 显示的启动图像?

    有人知道如何让iOS在使用时显示更高分辨率的启动图像吗 目前 我只能使用 460x380 的图像 在 iPhone 4 的高 dpi 显示屏上显示时 该图像显然看起来很糟糕 我尝试了 2x 技巧 但似乎不起作用 有什么想法或解决方法吗 我从
  • jquery 中的 Twig 无法读取 jquery 变量

    我正在尝试使用 jQuery post 但在使用 twig 语法的路径部分有问题 这是代码 messageSender click function e e preventDefault var threadId this find a d
  • cefSharp ChromiumWebBrowser 大小与页面内容的关系

    您知道如何使 ChromiumBrowser 打开时浏览器大小适合内容吗 现在这个 xaml 位于窗口主体中 当有人单击 MyTextBox 的文本时 ChromiumBrowser 将打开以显示更多信息 Edit 如果没有固定的宽度和高度
  • 在 Jtable 中添加 JCombobox 并在 Swing java 中获取该行和列

    我有一个 Jtable 其中我像这样添加了 JComobox TableColumn sportColumn jTable1 getColumnModel getColumn 2 comboBox new JComboBox comboBo
  • 仅元素属性发生变化的 ItemsSource 和集合

    我对 ComboBox 没有反映其 ItemsSource 绑定到的集合的属性变化感到悲伤 有一个树由包含设置对象的类别对象的可观察类别集合组成 某些设置定义其他设置允许的值域的表示名称 它们分布在多个类别中 但使用 LINQ 的一点魔法会