2010-11-24 10 views
6

Tengo un DataTemplate que consiste en un elemento de control de medios derivado de MediaElementBase de la biblioteca WPF Media Kit. La clase MediaElementBase proporciona las dos propiedades, LoadedBehavior y UnloadedBehavior, que permiten al usuario especificar qué sucede cuando el elemento se carga/descarga.WPF DataTemplate restablece algunas propiedades de dependencia cuando se descarga

Estoy descubriendo que cuando se utiliza esta en un DataTemplate (a continuación), estas propiedades reconfiguradas a su valor por defecto cuando se descarga la plantilla, pero antes del evento Unloaded se llama, es decir, sólo el valor por defecto UnloadedBehavior jamás ejecutar:

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

Esto no se produce cuando el control es simplemente un elemento de una página y Unloaded se produce a través de un evento normal de navegar-lejos.

Depuración del DependencyPropertyChanged EventHandler revela que un método interno System.Windows.StyleHelper.InvalidatePropertiesOnTemplateNode (en PresentationFramework.dll) comprueba si un DependencyProperty es potencialmente hereditaria, y si no lo es, lo invalida. Efectivamente, al cambiar los metadatos de la propiedad para LoadedBehavior/UnloadedBehavior para agregar FrameworkPropertyMetadataOptions.Inherits se detiene esta propiedad para que no se restablezca cuando la plantilla cambie.

¿Alguien sabe por qué ocurre esto? Puedo agregar el indicador Inherits como una solución, ya que este elemento no tiene elementos secundarios que se verían afectados por esto, pero me gustaría saber por qué y si es lo correcto.

Si busca más información sobre lo que estoy haciendo y por qué estoy cambiando DataTemplates, puede ver this question para una descripción.

+0

¿Qué versión del kit de medios WPF está utilizando? ¿La versión binaria actual o estás compilando desde la fuente? En el momento de escribir este comentario, el binario actual (v1.5) está a un año del árbol fuente. Jez corrigió algunos errores relacionados con los valores de las propiedades que cambiaban repentinamente. No creo que la solución esté directamente relacionada con las propiedades que está utilizando, pero para reproducir el problema, sería útil saber qué versión está utilizando. –

+0

Estoy compilando desde la fuente. El problema no es específico del WPF Media Kit: puedo reproducirlo en una simple aplicación independiente. – jeffora

+0

El problema tal como se describe es acerca de UnloadedBehavior. Entiendo que la causa raíz (el hecho de que las propiedades se restablezcan en una descarga) sería universal, pero ¿qué problemas causa en general? En el Kit de medios de WPF es un problema porque tienes esta propiedad donde solo te importa cuál es el valor después de la descarga. ¿Con qué frecuencia importa eso? –

Respuesta

7

En lugar de poner este elemento directamente en la plantilla, ¿ha intentado crear un control de usuario que contenga su elemento AnalogTvGraphFileElement y luego usar ese control de usuario en su plantilla?

Si el problema aquí está causado por los sistemas de plantillas que van y desarman las propiedades que estableció en primer lugar, mover su elemento a un control de usuario debería ayudar, porque las propiedades ya no se establecerían desde la plantilla.

En cuanto a por qué está viendo el comportamiento en primer lugar, hasta donde puedo decir el orden relativo del evento descargado y la pérdida de propiedades establecidas a través de la plantilla no está documentado, por lo que no debe depender en cualquier orden particular. El hecho de que perderá los valores de propiedad está documentado. (O al menos, está implícito en los documentos). El sistema de propiedades de WPF trata los valores locales en una plantilla como algo diferente a los valores locales normales fuera de una plantilla. Consulte esta página de MSDN en dependency property precedence - 4b indica que los conjuntos de propiedades locales en la plantilla no son lo mismo que las propiedades locales. (Parece extraño hacer una distinción, pero debería ser posible establecer valores de propiedad de ambas fuentes estableciéndolos en la plantilla - tipo 4b - y luego en tiempo de ejecución, yendo y encontrando el elemento en una instancia particular de la plantilla y configuración su valor local del código - tipo 3. Y para ese escenario, realmente desearía que los valores locales tipo 3 tengan mayor precedencia que los valores locales tipo 4b.)

Por extraño que parezca, podría tener más sentido si se considera que una sola plantilla puede proporcionar valores para varias instancias. Solo tienes un establecimiento local de propiedades que podría afectar cualquier cantidad de elementos. (Esto significa que un modelo mental simple de una plantilla como una fábrica que construye un árbol visual y establece propiedades en ese árbol sería incorrecto).Es una fábrica que construye un árbol visual, pero no establece propiedades. El sistema de propiedad simplemente garantiza que, en ausencia de fuentes de valores de propiedad de precedencia más alta, los elementos en un árbol visual que es la plantilla de algo recogerán valores de los instaladores en la plantilla).

Esa página apenas dice usted que las propiedades del tipo 4b desaparecerán una vez que la plantilla deja de estar activa: la plantilla ya no es la plantilla del elemento primario con plantilla, por lo que los valores locales proporcionados por esa plantilla ya no califican como valores candidatos del tipo 4b (o cualquier otro tipo) para el caso) para la propiedad. En resumen, una vez que la plantilla deja de ser la plantilla para algo, deja de tener un negocio que proporcione valores para esa cosa o algo en ella. Esto implica que el árbol visual para una instancia de una plantilla ingresa en un estado de limbo extraño en el que ya no es la plantilla para nada, pero aún no se ha descargado.

Por supuesto, no parece útil para la plantilla de dejar de prestar los valores antes de que el árbol visual relevante ha terminado la descarga, pero quizás propiedades cuyo valor sólo es significativo cuando un elemento se descargue son un poco de un caso raro , y no uno que fue diseñado específicamente para. Pensando en ello, probablemente nunca deberían ser propiedades de dependencia: casi todas las características que hacen que los DP sean útiles realmente no significan mucho una vez que se descarga del árbol visual. Así que podría decirse que es un error en el kit de medios que UnloadedBehaviour es un DP en primer lugar.

No es consistente que las propiedades heredadas (tipo 10) se cierren más tarde que los conjuntos de propiedades de la plantilla local (tipo 4b), pero entonces no estoy seguro de que sea razonable esperar algún orden en particular aquí. No es obvio que la documentación implica un orden u otro, por lo tanto, el orden es correcto ... y WPF parece hacer uso de eso seleccionando un orden en un escenario y el otro en otro escenario.

+0

Esto detiene el comportamiento descrito en la pregunta, siempre que el UserControl no tenga ningún DependencyProperties utilizado para pasar valores a AnalogTvGraphFileElement. Esencialmente, simplemente crea otra capa y realmente no explica por qué las propiedades no heredables se restablecen cuando las propiedades heredables no lo son. – jeffora

+0

Esperaba que se despegara rápidamente, y estaba esperando averiguar si era una versión de kit de medios antes de indagar. Supongo que la razón por la que se restablecen las propiedades es porque las propiedades establecidas usando la sintaxis de la propiedad local se consideran una fuente distinta, y cuando la plantilla desaparece, los valores de propiedad desaparecen. El hecho de que los heredados permanezcan suena como un error ... –

+0

OK, he editado esa respuesta para agregar algo de información sobre cómo el sistema de propiedad puede llegar a hacer esto en primer lugar. Esto probablemente no ayude mucho, el resultado es "no hagas eso". Pero sugiere que realmente necesita una capa adicional, como un control de usuario. Intente usar propiedades regulares en lugar de DP. O en su defecto, haga una instantánea del valor de la propiedad en el evento Loaded de UserControl o use DependencyPropertyHelper para descubrir de dónde proviene el valor e ignórelo cuando vuelva a una fuente de baja precesión. –

Cuestiones relacionadas