必须使用传统的silverlight应用程序,我遇到了一段奇怪的代码。 viewmodel具有List依赖项属性作为网格的绑定源。此DP具有默认值,即应用程序中全局使用的其他List。这用于在应用程序的不同部分之间轻松共享实体数据。
DependencyProperty MyEntitiesProperty = DependencyProperty.Register("MyEntities", typeof(List<Entity>), typeof(...), new PropertyMetadata(Global.Entities));
现在,当列表发生更改时(在用户操作上),将从数据库重新填充全局列表,但不会显式设置MyEntities。这不起作用:网格(绑定目标)永远不会改变。所以这是一个错误的解决方案。
我推测所有这一切背后的想法可能如下:如果你有一个给定值的DP而你从未为它设置一个本地值,那么DP的有效值将是默认值。如果更改了“基础”默认值,则更改将反映在有效值中。
如果它有效,那么这是一种在独立视图模型之间共享数据的好方法,而不会摆弄属性变化事件等。
这里有什么问题?对于DP如何工作或者想法是否正常以及错过了一些实施细节,这是一个很大的误解吗?
如果不清楚,请发表评论。
答案 0 :(得分:1)
那么,考虑到你的评论,这是对DP如何运作的一个很大的误解。让我解释一下:
将全局已知列表设置为 MyEntities 的默认值可能不是我推荐的模式,但在技术上没有错误,可以共享列表。 MyEntities 现在拥有对此列表的引用。
如果现在用新列表实例替换全局列表,则旧实例不会停止存在。您的财产 MyEntities 仍然保留对旧列表的引用。 DP的值仅在通过Binding
绑定到与INotifyPropertyChanged
机制或另一个DP连接的普通属性时自动更新。
设置默认值既不是通过Binding
发送到普通属性,也不是通过Binding
发送到另一个DP,它只是一个普通的旧对象引用。
我可以想出几种方法来纠正这种情况:
第一个解决方案
如果全局列表实现INotifyCollectionChanged
(例如ObservableCollection,DependencyObjectCollection),您可以 - 而不是创建新的列表实例 - 只需从列表中删除旧项并添加新项项目。引用该列表的视图会在收到相关的CollectionChanged
事件后立即执行更新。
第二个解决方案
确保Global.Entities
列表可用且始终是根视图的INotifyPropertyChanged
上的公共属性(与DataContext
相连)。现在,当您希望在UI树内部的某个位置连接到此Global.Entities
列表时,您可以将其绑定到根视图的DataContext&#39;公共清单属性。
<MyRootView>
... nested views spread across multiple files ...
<MyNestedEntitiesListDisplay
MyEntities="{Binding
Path=DataConext.GlobalEntities,
RelativeSource={RelativeSource AncestorType=MyRootView}}"/>