在高级数据模板中处理数据上下文更改

时间:2019-07-08 08:43:08

标签: c# wpf datacontext

我正在WPF中编写MDI应用程序-文档显示在选项卡中。

由于选项卡显示了完整的文档,因此TabControl的DataTemplate显然非常复杂-包括CodeBehind中的一些初始化/取消初始化代码(没有技巧-这只是我使用的控件(即AvalonEdit)所必需的)。但是问题是,TabControl重用了创建的DataTemplate,并且当我更改活动文档时,仅替换了DataContext-省略了所有在Load / Unloaded事件中执行的初始化/取消初始化过程。

我想到要挂起DataContextChanged事件,但是有一个陷阱:

  

当元素的DataContext更改时,该元素上的所有数据绑定属性都可能受到影响。这适用于作为逻辑树中当前元素的子元素的任何元素,这些元素继承数据上下文以及当前元素本身。所有这些现有绑定都必须重新解释新的DataContext并将重新评估绑定结果。相对于引发DataContextChanged事件,数据绑定引擎不确定这些重新评估的顺序。重新评估可以在事件发生之前,事件发生之后或以任何混合方式进行。

(来源:https://docs.microsoft.com/pl-pl/dotnet/api/system.windows.frameworkelement.datacontextchanged?view=netframework-4.8

因此可能发生的是,所有数据绑定都进行了刷新(包括AvalonEdit接收新文档),而没有进行未初始化/初始化的调用,这将导致异常。

理想的解决方案是强制TabControl每次从DataTemplate实例化视图,但似乎视图重用机制是WPF中的通用规则(ContentControl也使用它)。不太理想但仍然可靠的选项是捕获DataContext更改-但是我必须在DataContext更改之前和之后都可靠地调用代码,而且似乎也不可能。

如何解决此问题?如何在WPF中使用复杂的视图正确维护(初始化/取消初始化)文档?

1 个答案:

答案 0 :(得分:2)

请参阅我对以下问题的回答:

https://stackoverflow.com/a/47763600/5314530

我提供了一个解释/理论和一个工作示例,说明如何使用DataTemplate属性“ {刷新}” x:Shared以及DataTemplateSelector的实现(我发现确保生成新的DataTemplate都是必需的。

总结:

  1. DataTemplate必须与ResourceDictionary放在x:Shared="False"中。

  2. 需要使用DataTemplateSelector来提供关于哪个资源/模板需要的模棱两可的信息,以确保当前的DataTemplate不持久。