使用依赖项 属性 默认值作为绑定源

Using dependency property default value as binding source

必须使用遗留的 silverlight 应用程序,我 运行 进入了一段 st运行ge 代码。视图模型有一个列表依赖项 属性 作为网格的绑定源。这个DP有一个默认值,一个在app中全局使用的另一个List。这用于在应用程序的不同部分之间轻松共享实体数据。

DependencyProperty MyEntitiesProperty = DependencyProperty.Register("MyEntities", typeof(List<Entity>), typeof(...), new PropertyMetadata(Global.Entities));

现在,当列表更改时(根据用户操作),全局列表将从数据库中重新填充,但 MyEntities 永远不会明确设置。这是行不通的:网格(绑定目标)永远不会改变。所以这是一个错误的解决方案。

我推测所有这一切背后的想法可能如下:如果您有一个具有给定值的 DP,并且您从未为其设置本地值,那么 DP 的有效值将是默认值.如果更改 'underlying' 默认值,更改将反映在有效值中。

如果可行,这是一种在独立视图模型之间共享数据的好方法,而无需摆弄 属性 更改事件等。

这里有什么问题?是对 DP 的工作方式有很大的误解,还是想法没问题而遗漏了一些实现细节?

有什么不明白的地方请评论。

好吧,考虑到您的评论,这是对 DP 工作方式的很大误解。让我解释一下:

将全球已知的列表设置为 MyEntities 的默认值可能不是我推荐的模式,但在技术上没有错误并且可以共享列表。 MyEntities 现在拥有对此列表的引用。

如果您现在用新的列表实例替换全局列表,旧实例不会不复存在。您的 属性 MyEntities 仍然保留对旧列表的引用。 DP 的值只有在通过 Binding 绑定到与 INotifyPropertyChanged 机制连接的普通 属性 或另一个 DP 时才会自动更新。

设置默认值既不会通过 Binding 到普通的 属性 也不会通过 Binding 到另一个 DP,它只是一个普通的旧对象引用。

我可以想出几种方法来纠正这种情况:

第一个解决方案

如果全局列表实现 INotifyCollectionChanged(例如 ObservableCollection, DependencyObjectCollection),您可以 - 而不是创建新的列表实例 - 只需从列表中删除旧项目并添加新项目。引用列表的视图将在收到关联的 CollectionChanged 事件后立即执行更新。

第二种解法

确保 Global.Entities 列表可用并且始终是最新的 public 属性(连接 INotifyPropertyChanged)在 DataContext 的根视图。现在,当您想要将 UI 树深处某处的嵌套视图连接到此 Global.Entities 列表时,您可以将其绑定到根视图的 DataContext' public 列表 属性 .

<MyRootView>
    ... nested views spread across multiple files ...
    <MyNestedEntitiesListDisplay
        MyEntities="{Binding
            Path=DataConext.GlobalEntities,
            RelativeSource={RelativeSource AncestorType=MyRootView}}"/>