WPF DataTemplate сбрасывает некоторые свойства зависимостей при выгрузке - PullRequest
6 голосов
/ 24 ноября 2010

У меня есть DataTemplate, состоящий из элемента управления медиа-элементом, который получен из MediaElementBase из библиотеки WPF Media Kit .Класс MediaElementBase предоставляет два свойства LoadedBehavior и UnloadedBehavior, которые позволяют пользователю указать, что происходит при загрузке / выгрузке элемента.

Я обнаружил, что при использовании этогов DataTemplate (как показано ниже) эти свойства сбрасываются до значения по умолчанию при выгрузке шаблона, но до вызова события Unloaded, что означает, что будет выполняться только значение по умолчанию UnloadedBehavior:

<DataTemplate DataType="{x:Type Channels:AnalogChannel}">
    <Controls:AnalogTvGraphFileElement
        LoadedBehavior="Play"
        UnloadedBehavior="Stop"
        Channel="{Binding}" />
</DataTemplate>

Это не происходит, когда элемент управления является просто элементом на странице, а Unloaded происходит через обычное событие отклонения.

Отладка DependencyPropertyChanged EventHandler показывает, что внутренний метод System.Windows.StyleHelper.InvalidatePropertiesOnTemplateNode(в PresentationFramework.dll) проверяет, является ли DependencyProperty потенциально унаследованным, и, если это не так, делает его недействительным.Конечно, изменение метаданных свойства для LoadedBehavior / UnloadedBehavior для добавления FrameworkPropertyMetadataOptions.Inherits останавливает сброс этого свойства при изменении шаблона.

Кто-нибудь знает, почему это происходит?Я могу добавить флаг Inherits в качестве обходного пути, так как у этого элемента нет дочерних элементов, на которые это может повлиять, но я хотел бы знать, почему / правильно ли это делать.

Если вам нужна дополнительная информация о том, что я делаю и почему я меняю DataTemplates, вы можете просмотреть этот вопрос для описания.

1 Ответ

7 голосов
/ 29 ноября 2010

Вместо того, чтобы помещать этот элемент непосредственно в шаблон, пытались ли вы создать пользовательский элемент управления, содержащий ваш элемент AnalogTvGraphFileElement, а затем использовать этот элемент управления в шаблоне?

Если проблема здесь вызвана тем, что системы шаблонов запускают и отменяют свойства, которые он установил в первую очередь, перемещение вашего элемента в пользовательский элемент управления должно помочь, потому что свойства больше не будут устанавливаться из шаблона.

Что касается того, почему вы видите поведение в первую очередь, насколько я могу судить, относительный порядок события Unloaded и потеря свойств, установленных с помощью шаблона, не задокументированы, поэтому вы не должны зависеть от любой конкретный порядок. Тот факт, что вы потеряете значения свойств , задокументирован. (Или, по крайней мере, это неявно из документов.) Система свойств WPF рассматривает локальные значения в шаблоне как нечто иное, чем обычные локальные значения вне шаблона. См. Эту страницу MSDN на приоритет свойства зависимостей - 4b указывает, что наборы локальных свойств в шаблоне - это не то же самое, что локальные свойства. (Кажется странным проводить различие, но должна быть возможность установить значения свойств из обоих источников, задав их в шаблоне - тип 4b - и затем во время выполнения, найти и найти элемент в конкретном экземпляре шаблона и установить его локальное значение из кода - тип 3. И для этого сценария вы действительно хотели бы, чтобы локальные значения типа 3 имели более высокий приоритет, чем локальные значения типа 4b.)

Как ни странно, это может иметь больше смысла, если учесть, что один шаблон может предоставлять значения для нескольких экземпляров. У вас есть только один локальный установщик свойств, который может повлиять на любое количество элементов. (Это означает, что простая мысленная модель шаблона как фабрики, которая строит визуальное дерево и устанавливает свойства для этого дерева, была бы неправильной. Это фабрика, которая строит визуальное дерево, но не устанавливает свойства. Система свойств просто гарантирует, что в отсутствие источников значений свойств с более высоким приоритетом элементы в визуальном дереве, которые являются шаблоном для чего-либо, получат значения из установщиков в шаблоне.)

Эта страница фактически сообщает вам, что свойства типа 4b исчезнут, как только шаблон перестанет быть активным - шаблон больше не является шаблоном для шаблонного родителя, и поэтому любые локальные значения, предоставленные этим шаблоном, больше не считаются кандидатами. значения типа 4b (или любого другого типа в этом отношении) для свойства. Короче говоря, как только шаблон перестает быть шаблоном для чего-либо, он перестает иметь какой-либо бизнес, предоставляющий значения для этой вещи или чего-либо в ней. Это подразумевает, что визуальное дерево для экземпляра шаблона входит в странное неопределенное состояние, в котором он больше не является шаблоном для чего-либо, но еще не выгружен.

Конечно, не полезно , чтобы шаблон прекратил предоставлять значения до завершения выгрузки соответствующего визуального дерева, но, возможно, свойства, значение которых имеет значение только тогда, когда элемент выгружается, немного странный случай, а не тот, который был специально разработан для. Подумав об этом, они, вероятно, никогда не должны быть свойствами зависимостей - почти все функции, которые делают DP полезными, на самом деле мало что значат, когда вы выгружаетесь из визуального дерева. Можно утверждать, что это ошибка в Media Kit, что UnloadedBehaviour является DP в первую очередь.

Неверно, что унаследованные свойства (тип 10) закрываются позже, чем локальные наборы свойств шаблона (тип 4b), но тогда я не уверен, что разумно ожидать какого-либо конкретного порядка здесь. Не очевидно, что документация подразумевает один или другой заказ, поэтому любой заказ является правильным ... и WPF, по-видимому, использует его, выбирая один заказ в одном сценарии, а другой - в другом сценарии.

...