Why do some properties require a default value defined in the style before the DataTrigger takes effect?

Why do some dependency properties need to have a default style installer before running setters take effect?

For instance,

<ContentControl> <ContentControl.Resources> <DataTemplate x:Key="DefaultTemplate"> <TextBlock Text="Default Template" /> </DataTemplate> <DataTemplate x:Key="MouseOverTemplate"> <TextBlock Text="MouseOver Template" /> </DataTemplate> </ContentControl.Resources> <ContentControl.Style> <Style TargetType="{x:Type ContentControl}"> <!-- Triggered setter will work without this default setter --> <!--<Setter Property="ContentTemplate" Value="{StaticResource DefaultTemplate}" />--> <Style.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="ContentTemplate" Value="{StaticResource MouseOverTemplate}" /> </Trigger> </Style.Triggers> </Style> </ContentControl.Style> </ContentControl> 

I saw a good explanation for this somewhere, but I can’t remember where. I remember that this had something to do with the order in which WPF applies the values ​​of dependency properties , but I can’t remember the details or why some properties are needed. The default value defined before the triggers will take effect, while others will not.

+4
source share
1 answer

I would be very surprised if your first Style does not work, if your ContentControl not defined as:

 <ContentControl ContentTemplate="{StaticResource DefaultTemplate}" /> 

If so, it will be associated with the priority value. From your link, the installation, as in my example, will be on # 3. Thus, the only thing that could override this would be animation or if the value was forced. Neither Style nor ControlTemplate (if any) can change the ContentControl.ContentTemplate property.

With the second Style you can define your ContentControl as follows:

 <ContentControl /> 

In this case, the Setter for DefaultTemplate is at # 8, so triggers can override it (since they are at # 6).

Assuming you have:

 <ContentControl ContentTemplate="{StaticResource DefaultTemplate}" /> 

Then you can override the DataTemplate used in the ControlTemplate , but you cannot change the value of ContentControl.ContentTemplate . Sort of:

 <Style TargetType="{x:Type ContentControl}"> <Setter Property="ControlTemplate"> <Setter.Value> <ControlTemplate TargetType="{x:Type ContentControl}"> <ContentPresenter x:Name="presenter" /> <ControlTemplate.Triggers> <DataTrigger Binding="{Binding SomeProperty}" Value="A"> <Setter TargetName="presenter" Property="ContentTemplate" Value="{StaticResource TemplateA}" /> </DataTrigger> <DataTrigger Binding="{Binding SomeProperty}" Value="B"> <Setter TargetName="presenter" Property="ContentTemplate" Value="{StaticResource TemplateB}" /> </DataTrigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> 

Here we switch the DataTemplate used by ContentPresenter, so it effectively ignores the ContentControl.ContentTemplate property.

However, based on your updates, there is no “more" for the mouse. ContentControl did nothing (not even a transparent pixel), so it will not receive any mouse events. You can do something like this to fix this:

 <Style TargetType="{x:Type ContentControl}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ContentControl}"> <Border Background="{TemplateBinding Background}"> <ContentPresenter /> </Border> </ControlTemplate> </Setter.Value> </Setter> <Style.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="ContentTemplate" Value="{StaticResource MouseOverTemplate}" /> </Trigger> </Style.Triggers> </Style> 

And you need to set Background = "Transparent" to ContentControl.

+1
source

All Articles