使用依赖项 属性 默认值作为绑定源
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}}"/>
必须使用遗留的 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}}"/>