3

我的 MVVM 应用程序有许多从基本用户控件继承的视图,这些控件公开了一个“ID”属性。在 XAML 中,这绑定到视图的基础视图模型上的 ID 属性,简单地说:

Id="{Binding Path=Id}"

视图模型实现了 INotifyPropertyChanged,它的 ID 在构造函数中设置。ID 用于唯一标识每个视图/视图模型,主要由“桌面管理器”用于管理主窗口中的用户控件,就像 MDI 应用程序一样。当我的应用程序启动时,我实例化各种视图模型及其视图,并将视图模型分配给视图DataContext。然后我将视图传递给桌面管理器,桌面管理器将它们放置在画布上,定位它们等。

我遇到的问题是,此时视图的 ID 仍然为空,并且似乎只是在一段时间后才绑定到数据上下文(也许当 UI 被渲染时?)。我试过像这样强制绑定,但它没有帮助: -

var bindingExpression = widget.GetBindingExpression(DesktopElement.IdProperty);
bindingExpression.UpdateTarget();

这不是世界末日,因为我可以将我的视图视图模型中的 ID 传递给桌面管理器,但感觉有点 hacky。我很想知道绑定发生在控件/窗口生命周期的哪个时间点,以及是否有其他方法可以强制绑定发生?

提前感谢安迪

4

2 回答 2

1

为了了解绑定是如何传输的,您需要了解Dispatcher. 基本上,它是一个优先队列。布局、绑定、渲染、输入等内容以不同的优先级放置在队列中。

现在,从它的声音来看,你永远不会让执行回到Dispatcher. 这意味着Binding值无法传输(当您手动调用时,UpdateTarget您只是将其安排在 上Dispatcher)。因此,简而言之,您需要Dispatcher在完成初始化之前让队列中的操作执行。

最简单的方法是调用BeginInvoke较低DispatcherPriority的方法来完成初始化。由于布局系统的工作原理,有时选择正确的优先级可能会很棘手,但如果您使用DispatcherPriority.Loaded.

于 2013-06-27T20:38:06.287 回答
0

我的建议是有一个您的视图模型实现的接口,它公开 Id 属性。然后,您可以让您的桌面管理器通过将其转换为适当的接口来从 DataContext 中获取 Id。这可能是更清晰的职责分离,因为您的桌面管理器可能应该尽可能少地了解具体视图(为了可测试性。)

于 2013-06-27T20:44:43.497 回答