WPF DataTemplate resets some dependency properties when unloading

I have a DataTemplate consisting of an environment control that is retrieved from MediaElementBase from the WPF Media Kit library. The MediaElementBase class provides two properties, UnloadedBehavior and UnloadedBehavior , which allow the user to determine what happens when an item is loaded / unloaded.

I find that when using this in a DataTemplate (as follows), these properties get a reset value by default when the template is unloaded, but before calling Unloaded , which means only the default UnloadedBehavior will execute:

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

This does not happen when the control is just an element on the page and Unloaded through a regular transition event.

Debugging the DependencyPropertyChanged EventHandler shows that the internal System.Windows.StyleHelper.InvalidatePropertiesOnTemplateNode method (in PresentationFramework.dll) checks if DependencyProperty potentially inherited, and if it does not, it makes it invalid. Of course, changing the property metadata for UnloadedBehavior / UnloadedBehavior to add FrameworkPropertyMetadataOptions.Inherits stops this property from reset when the template changes.

Does anyone know why this is happening? I can add the Inherits flag as a workaround, since this element has no children that it will affect, but I would like to know why / whether to do it correctly.

If you need more information about what I am doing and why I am changing DataTemplates , you can view this question for a description.

+6
c # wpf datatemplate
source share
1 answer

Instead of putting this element directly in the template, did you try to create a user control that contains your AnalogTvGraphFileElement element, and then use this control in your template?

If the problem here arises from the fact that the template systems that build and disable the properties that it sets in the first place, you need to move the element to the user control, because the properties will no longer be set from the template.

As for why you see the behavior in the first place, as far as I can tell about the relative ordering of the Unloaded event and the loss of properties set using the template is not documented, so you should not depend on any particular order. The fact that you lose property values ​​is documented. (Or at least this is implied from the documents.) The WPF property system treats local values ​​in a template as something other than regular local values ​​outside of a template. See This MSDN Page for Dependency Property Priority - 4b indicates that local properties in the template do not match local properties. (It seems strange to make a distinction, but it should be possible to set property values ​​from both sources by setting them to a template - type 4b - and then at run time, going over and finding the element in a specific instance of the template and setting its local value from code type 3. And for this scenario, you really would like local values ​​of type 3 to have higher priority than local values ​​of type 4b.)

Oddly enough, this can make more sense when you consider that a single template can provide values ​​for multiple instances. You have only one local set of properties that can affect any number of elements. (This means that a simple mental template model like a factory that creates a visual tree and sets properties on this tree would be wrong. This is a factory that creates a visual tree but does not set properties. The property system simply ensures that in the absence of sources of property values with higher priority elements in the visual tree, so that the template will pick values ​​from the setters in the template for something.)

This page will simply tell you that properties of type 4b disappear after the template is no longer active - the template is no longer a template for the template parent, and therefore any local values ​​provided by this template will no longer qualify as a candidate for a value of type 4b (or any other type for that matter) for a property. In short, as soon as a template ceases to be a template for something, it ceases to have any business providing values ​​for this thing or something else. This means that the visual tree for the template instance enters the strange state of limbo, in which it is no longer a template, but has not yet been unloaded.

Of course, it does not seem appropriate for the template to stop providing the values ​​before the corresponding visual tree completes the unloading, but perhaps properties whose value only matters when the element is unloaded is a bit of a strange case, and not one that was specifically designed for. Thinking about this, they probably should never be dependent properties — almost all the functions that make DP useful are actually not really important after unloading from a visual tree. So maybe this is a bug in the Media Kit, which, first of all, is UnloadedBehaviour.

It is inconsistent that the inherited properties (type 10) are closed later than the local property sets of the template (type 4b), but then I'm not sure if it is reasonable to expect any specific order here. It is not obvious that the documentation implies one order or another, so any order is correct ... and WPF seems to use this by choosing one order in one scenario and another in another scenario.

+7
source share

All Articles