我正在WPF中编写MDI应用程序-文档显示在选项卡中。
由于选项卡显示了完整的文档,因此TabControl的DataTemplate显然非常复杂-包括CodeBehind中的一些初始化/取消初始化代码(没有技巧-这只是我使用的控件(即AvalonEdit)所必需的)。但是问题是,TabControl重用了创建的DataTemplate,并且当我更改活动文档时,仅替换了DataContext-省略了所有在Load / Unloaded事件中执行的初始化/取消初始化过程。
我想到要挂起DataContextChanged
事件,但是有一个陷阱:
当元素的DataContext更改时,该元素上的所有数据绑定属性都可能受到影响。这适用于作为逻辑树中当前元素的子元素的任何元素,这些元素继承数据上下文以及当前元素本身。所有这些现有绑定都必须重新解释新的DataContext并将重新评估绑定结果。相对于引发DataContextChanged事件,数据绑定引擎不确定这些重新评估的顺序。重新评估可以在事件发生之前,事件发生之后或以任何混合方式进行。
因此可能发生的是,所有数据绑定都进行了刷新(包括AvalonEdit接收新文档),而没有进行未初始化/初始化的调用,这将导致异常。
理想的解决方案是强制TabControl每次从DataTemplate实例化视图,但似乎视图重用机制是WPF中的通用规则(ContentControl也使用它)。不太理想但仍然可靠的选项是捕获DataContext更改-但是我必须在DataContext更改之前和之后都可靠地调用代码,而且似乎也不可能。
如何解决此问题?如何在WPF中使用复杂的视图正确维护(初始化/取消初始化)文档?
答案 0 :(得分:2)
请参阅我对以下问题的回答:
https://stackoverflow.com/a/47763600/5314530
我提供了一个解释/理论和一个工作示例,说明如何使用DataTemplate
属性“ {刷新}” x:Shared
以及DataTemplateSelector
的实现(我发现确保生成新的DataTemplate
都是必需的。
总结:
DataTemplate
必须与ResourceDictionary
放在x:Shared="False"
中。
需要使用DataTemplateSelector
来提供关于哪个资源/模板需要的模棱两可的信息,以确保当前的DataTemplate
不持久。