Обработка изменения контекста данных в расширенном шаблоне данных - PullRequest
2 голосов
/ 08 июля 2019

Я пишу MDI-приложение в WPF - документы отображаются на вкладках.

Поскольку на вкладке отображается весь документ, DataTemplate для TabControl, очевидно, довольно сложный, включая некоторый код инициализации / деинициализации в CodeBehind (без хаков - это просто требуется для используемых мной элементов управления, а именно AvalonEdit). Однако проблема заключается в том, что TabControl повторно использует созданный DataTemplate, и когда я меняю активный документ, заменяется только DataContext, исключая все процедуры инициализации / деинициализации, которые выполняются в событиях Loaded / 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 Ответ

2 голосов
/ 08 июля 2019

Пожалуйста, смотрите мой ответ на следующий вопрос:

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

Я предоставил объяснение / теорию и рабочий пример того, как "полностью обновить" DataTemplateиспользуя атрибут x:Shared, а также реализацию DataTemplateSelector (я обнаружил, что оба были необходимы для обеспечения генерации нового DataTemplate).

Подводя итог:

  1. DataTemplate должен находиться в ResourceDictionary с x:Shared="False".

  2. A DataTemplateSelector необходимо использовать для обеспечения неопределенности относительно того, какой ресурс / шаблонтребуется, чтобы гарантировать, что текущий DataTemplate не сохраняется.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...