我正在 WPF 中编写 MDI 应用程序 - 文档显示在选项卡中。
由于选项卡显示完整的文档,TabControl 的 DataTemplate 显然相当复杂 - 包括 CodeBehind 中的一些初始化/取消初始化代码(没有黑客 - 这只是我使用的控件(即 AvalonEdit)所需要的)。但问题是,TabControl 重用创建的 DataTemplate,并且当我更改事件文档时,仅替换 DataContext - 忽略在加载/卸载事件中执行的所有初始化/取消初始化过程。
我想过 Hook DataContextChanged
事件,但有一个问题:
When the DataContext for an element changes, all data-bound properties on this element are potentially affected. This applies to any elements that are child elements of the current element in the logical tree, which inherit the data context, and also the current element itself. All such existing bindings must re-interpret the new DataContext and will reevaluate the binding results. The data binding engine is not deterministic about the order of these reevaluations, relative to the raising of the DataContextChanged event. The reevaluations can occur before the event, after the event, or in any mixture.
因此可能会发生这样的情况:所有数据绑定(bind)都在没有去初始化/初始化调用的情况下刷新(包括 AvalonEdit 接收新文档),这将导致异常。
理想的解决方案是强制 TabControl 每次从 DataTemplate 实例化 View ,但 View 重用机制似乎是 WPF 中的一般规则(ContentControl 也使用它)。不太理想但仍然可靠的选择是捕获 DataContext 更改 - 但我必须在 DataContext 更改之前和之后可靠地调用代码,而且似乎也是不可能的。
如何解决这个问题?如何在 WPF 中正确维护(初始化/取消初始化)具有复杂 View 的文档?
最佳答案
请参阅我对以下问题的回答:
https://stackoverflow.com/a/47763600/5314530
我提供了一个解释/理论和一个工作示例,说明如何使用 x:Shared
属性“完全刷新”DataTemplate
以及实现DataTemplateSelector
(我发现两者都是确保生成新的 DataTemplate
所必需的)。
总结一下:
<DataTemplate
需要位于带有x:Shared="False"
的ResourceDictionary
中。需要使用
DataTemplateSelector
来明确需要哪个资源/模板,以确保当前的DataTemplate
不会被保留。
关于c# - 处理高级数据模板中的数据上下文更改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56931236/