The previous Post on ControlTempalte only describes how to define the appearance. For complicated custom controls, we usually need to use Resource in ControlTemplate. Obviously, Resource is designed to facilitate element reuse. In addition, our custom templates are usually completed in XAML, because code implementation is very cumbersome. For small applications, this ControlTemplate is generally directly defined in the root element of XAML. For large applications, the root element is ResourceDictionary, which should usually be defined in specialized resource XAML files.
No matter where it is defined, in addition to defining the appearance with Style and implementing element reuse with Resource, ControlTemplate includes a Trigger element, it describes how the widget looks when its properties change. For example, when you define a Button, consider the appearance of the widget when you move the mouse over the Button. The Trigger element is also optional, such as a text tag element, which generally does not include a Trigger.
It is easy to use resources in ControlTemplate, just like the resources in other elements:
<ControlTemplate x: Key = "templateThermometer" TargetType = "{x: Type ProgressBar}">
<ControlTemplate. Resources>
<RadialGradientBrush x: Key = "brushBowl"
GradientOrigin = "0.3 0.3">
<GradientStop Offset = "0" Color = "Pink"/>
<GradientStop Offset = "1" Color = "Red"/>
</RadialGradientBrush>
</ControlTemplate. Resources>
<! -- Ignore other related content -->
</ControlTemplate>
Next we will use the Trigger. With the Trigger object, we can receive attribute changes or events and make appropriate responses accordingly. Trigger itself supports multiple types. The following is an example of attribute Trigger:
<Style TargetType = "ListBoxItem">
<Setter Property = "Opacity" Value = "0.5" type = "parmname" text = "parmname"/>
<Style. Triggers>
<Trigger Property = "IsSelected" Value = "True">
<Setter Property = "Opacity" Value = "1.0" type = "parmname" text = "parmname"/>
<! -- Other Setters->
</Trigger>
</Style. Triggers>
</Style>
In this Code, set the default value of the Opacity attribute of ListBoxItem to 0.5. However, when the IsSelected attribute is True, the Opacity attribute value of ListBoxItem is 1. The code above also shows that after one condition is met, multiple behaviors can be triggered (multiple Setters can be defined ). Similarly, the preceding Triggers is also a set, and multiple Triggers can be added.
Note that the preceding triggers are independent of each other and will not affect each other. In another case, an action is triggered only when multiple conditions are met. Therefore, WPF provides MultiTrigger to meet this requirement. For example:
<Style TargetType = "{x: Type Button}">
<Style. Triggers>
<MultiTrigger>
<MultiTrigger. Conditions>
<Condition Property = "IsMouseOver" Value = "True"/>
<Condition Property = "Content" Value = "{x: Null}"/>
</MultiTrigger. Conditions>
<Setter Property = "Background" Value = "Yellow"/>
</MultiTrigger>
</Style. Triggers>
</Style>
This indicates that the Background is set to Yellow only when IsMouseOver is True and Content is NULL.
The above triggers are all based on element attributes. WPF has a dedicated EventTrigger for processing mouse movement and other events. However, EventTrigger is usually used with Storyboard. Therefore, I will introduce EventTrigger in detail later.
On the other hand, the Trigger discussed now is based on attribute values or events. WPF also supports another Trigger: DataTrigger. Obviously, this type of data Trigger is used when data changes, that is, the attribute of the Trigger condition is bound to Data. Similarly, the data Trigger supports multiple conditions: MultiDataTrigger. Their usage is similar to the previous Trigger.
Next Post I will analyze the example of ControlTemplateExamples in Windows SDK. This example involves the use of many control templates.