我想编写一个ViewModel,它总是知道View中某些只读依赖项属性的当前状态。
具体地说,我的GUI包含FlowDocumentPageViewer,它一次显示FlowDocument中的一个页面。FlowDocumentPageViewer公开两个名为CanGoToPreviousPage和CanGoToNextPage的只读依赖项属性。我希望我的ViewModel总是知道这两个View属性的值。
我想我可以用OneWayToSource数据绑定来做到这一点:
<FlowDocumentPageViewer
CanGoToNextPage="{Binding NextPageAvailable, Mode=OneWayToSource}" ...>
如果这是允许的,那将是完美的:无论何时FlowDocumentPageViewer的CanGoToNextPage属性发生变化,新的值都会被下推到ViewModel的NextPageAvailable属性中,这正是我想要的。
不幸的是,这不编译:我得到一个错误,说**'CanGoToPreviousPage'属性是只读的,不能从标记设置。**显然只读属性不支持任何类型的数据绑定,甚至不支持与该属性相关的只读数据绑定。
我可以让我的ViewModel的属性是DependencyProperties,并以另一种方式进行OneWay绑定,但我对关注点分离违规并不疯狂(ViewModel需要对View的引用,MVVM数据绑定应该避免)。
FlowDocumentPageViewer不公开CanGoToNextPageChanged事件,我不知道有什么好方法可以从DependencyProperty获取更改通知,除了创建另一个DependencyProperty来绑定它,这似乎有点过头了。
如何让我的ViewModel知道视图的只读属性的变化?
7条答案
按热度按时间6ojccjat1#
是的,我以前用
ActualWidth
和ActualHeight
属性做过,这两个属性都是只读的。我创建了一个附加行为,它具有ObservedWidth
和ObservedHeight
附加属性。它还有一个Observe
属性,用于执行初始连接。用法如下:因此,视图模型具有
Width
和Height
属性,这些属性始终与ObservedWidth
和ObservedHeight
附加属性同步。Observe
属性只是附加到FrameworkElement
的SizeChanged
事件。在句柄中,它更新其ObservedWidth
和ObservedHeight
属性。因此,视图模型的Width
和Height
始终与UserControl
的ActualWidth
和ActualHeight
同步。也许不是完美的解决方案(我同意-只读DP * 应该 * 支持
OneWayToSource
绑定),但它可以工作,并且支持MVVM模式。显然,ObservedWidth
和ObservedHeight
DP不是只读的。UPDATE:下面是实现上述功能的代码:
h4cxqtbf2#
我使用了一个通用的解决方案,它不仅适用于ActualWidth和ActualHeight,而且适用于任何你可以至少在阅读模式下绑定的数据。
如果ViewportWidth和ViewportHeight是视图模型的属性,则标记如下所示
下面是自定义元素的源代码
lsmepo6l3#
如果有人感兴趣,我在这里编写了一个近似的肯特解决方案:
请在您的应用程序中使用它。效果很好。(谢谢肯特!)
fumotvh34#
下面是我在博客中提到的这个“bug”的另一个解决方案:
OneWayToSource Binding for ReadOnly Dependency Property
它通过使用两个依赖项属性(Listener和Mirror)来工作。Listener绑定OneWay到TargetProperty,在PropertyChangedCallback中,它更新Mirror属性,该属性绑定OneWayToSource到Binding中指定的任何内容。我称之为
PushBinding
,它可以在任何只读的依赖属性上设置,像这样Download Demo Project Here。
它包含源代码和简短的示例用法。
8fq7wneg5#
我喜欢Dmitry Tashkinov的解决方案!然而,它崩溃了我的VS在设计模式。这就是为什么我在OnSourceChanged方法中添加了一行代码:
xytpbqjk6#
我觉得可以简单一点:
示例1:
cs:
dgenwo3n7#
类似于@eriksmith200的想法-它可以用
Behavior
更简单地完成,没有对属性数量的限制,下面是ActualHeight
和ActualWidth
的示例:示例1:
cs: