|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
|
Announcements
Services
Chapters
Feature Zones
|
Table of contents
IntroductionThis is the fourth article in an introductory series about the Windows Presentation Foundation. In the previous article we examined data binding and how it is used to display information in WPF user interfaces. In this article we examine data templating and triggers, and how they are used in the WPF Horse Race demo application (which is available for download at the top of the first article in this series). Just like the other articles in this series, this article does not cover its subject matter in exhaustive detail. Instead we will examine just enough of the basics so that we can see how those features are put to use in the demo app. If you want to learn more about how data templating and triggers can be used, refer to the External links section for additional information. BackgroundSo far in this series of articles, we have seen how XAML, layout panels, and data binding are used to create user interfaces that display simple data. Those fundamental building blocks, however, serve as the foundation upon which more powerful and compelling features of WPF depend. One of those higher-level features allows you to easily describe how an object of any type can be rendered. In other words, it enables you to create a template, in XAML, of visual elements which can be "expanded" at runtime to render a data object. Of course, the feature I'm referring to is known as "data templating". Data templates are only one type of template in WPF. This article, in fact this entire series of articles, will not examine the other types of templates because the WPF Horse Race demo application does not use them. In case you are interested, there are also control templates, items panel templates, and hierarchical data templates. Refer to the Other templates sub-section in the External links section toward the bottom of this article for links to information about them. Another feature of WPF covered in this article is called "triggers". Triggers are another fundamental building block in WPF, upon which many parts of the framework depend. They are, in general, a means of conditionally applying values to properties. Triggers are especially useful when you are writing XAML because they provide a means of evaluating properties at runtime and taking certain actions based on their values. In that sense triggers are a gray area somewhere between the declarative world of XAML markup and the imperative world of the code-behind. The DataTemplate classAll of WPF's templating functionality is based on the It is far more straightforward and expedient to create a Without a DataTemplateBefore we dive into the data template used in the WPF Horse Race application let's see how a simple example works. First take a look at a simple class which represents a river: namespace WPF_Test
{
public class River
{
string name;
int milesLong;
public string Name
{
get { return name; }
set { name = value; }
}
public int MilesLong
{
get { return milesLong; }
set { milesLong = value; }
}
}
}
If we were to display an instance of this class in a <StackPanel>
<StackPanel.Resources>
<local:River x:Key="theRiver" Name="Colorado River" MilesLong="1450" />
</StackPanel.Resources>
<ContentControl Content="{StaticResource theRiver }" />
</StackPanel>
The UI created by that XAML looks like the following:
That certainly isn't too impressive. What you see above is what gets displayed as a result of calling The example above creates an instance of the With a DataTemplateNow that we've seen how boring a <StackPanel>
<StackPanel.Resources>
<DataTemplate DataType="{x:Type local:River}">
<Border BorderBrush="Blue" BorderThickness="3" CornerRadius="12">
<Grid Margin="4">
<TextBlock>
<Run Text="The"/>
<TextBlock Text="{Binding Name}"/>
<Run Text="is"/>
<TextBlock Text="{Binding MilesLong}" />
<Run Text="miles long." />
</TextBlock>
</Grid>
</Border>
</DataTemplate>
<local:River x:Key="theRiver" Name="Colorado River" MilesLong="1450" />
</StackPanel.Resources>
<ContentControl Content="{StaticResource theRiver}" />
</StackPanel>
This is how that XAML renders:
The TriggersAnother feature of WPF often used in conjunction with templates is known as "triggers". In general a trigger is somewhat like an For example, here is a modified version of the XAML seen in the previous section. This time the <StackPanel>
<StackPanel.Resources>
<DataTemplate DataType="{x:Type local:River}">
<Border x:Name="bdr"
BorderBrush="Blue" BorderThickness="3" CornerRadius="12"
>
<Grid Margin="4">
<TextBlock x:Name="txt">
<Run Text="The"/>
<TextBlock Text="{Binding Name}"/>
<Run Text="is"/>
<TextBlock Text="{Binding MilesLong}" />
<Run Text="miles long." />
</TextBlock>
</Grid>
</Border>
<DataTemplate.Triggers>
<Trigger SourceName="bdr" Property="IsMouseOver" Value="True">
<Setter TargetName="bdr" Property="Background" Value="LightGray"/>
<Setter TargetName="txt" Property="Foreground" Value="Red"/>
</Trigger>
</DataTemplate.Triggers>
</DataTemplate>
<local:River x:Key="theRiver" Name="Colorado River" MilesLong="1450" />
</StackPanel.Resources>
<ContentControl Content="{StaticResource theRiver}" />
</StackPanel>
When that XAML is used, the UI looks like this when the cursor is over the
When the cursor is moved away from the
There are several kinds of triggers, each has a different way of determining when it should execute. In the remainder of this article, we will only focus on the two types of triggers used in the WPF Horse Race demo application: Triggers can be used in other places outside of templates, such as within How the WPF Horse Race uses data templates and triggersThe WPF Horse Race demo application has one custom The visuals for a RaceHorseThe visuals elements in the <Border>
<Grid>
<StackPanel Orientation="Horizontal">
<!-- This Rectangle is the "progress indicator"
which follows the horse. -->
<Rectangle />
<!--This Image displays the picture of a race horse. -->
<Image />
</StackPanel>
<!-- Displays the horse's name. -->
<TextBlock />
</Grid>
</Border>
Here is a visual explanation for how the elements in the template correspond to what you see as a
(Note: The yellow rectangle in the image above, which represents the The root The Setting properties on the winner of a raceAfter the template's visuals are declared, there are also some trigger declarations. One of them is a <!-- Set special values for the winner of the race. -->
<DataTrigger Binding="{Binding IsWinner}" Value="True">
<Setter TargetName="progressIndicator"
Property="Fill" Value="{StaticResource WinnerBrush}" />
<Setter TargetName="horseName"
Property="Foreground" Value="Black" />
<Setter TargetName="horseName"
Property="FontWeight" Value="Bold" />
<Setter TargetName="horseName"
Property="HorizontalAlignment" Value="Center" />
</DataTrigger>
That The In the screenshot below, the
When the next race starts and Fresh Spice's In case you are curious as to how the Fading away losing RaceHorsesWhen a In order to change the color of and fade away a <!-- This MultiDataTrigger affects losers of the race. -->
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding IsFinished}" Value="True" />
<Condition Binding="{Binding IsWinner}" Value="False" />
</MultiDataTrigger.Conditions>
<!-- Apply the "finished the race" brush to
the horse's progress indicator. -->
<Setter TargetName="progressIndicator"
Property="Fill" Value="{StaticResource FinishedBrush}" />
<!-- Fade the race pit in and out if the horse lost the race. -->
<MultiDataTrigger.EnterActions>
<!-- Fade away the RaceHorse's Border element when it loses a race. -->
</MultiDataTrigger.EnterActions>
<MultiDataTrigger.ExitActions>
<!-- Fade in the RaceHorse's Border element when a new race starts. -->
</MultiDataTrigger.ExitActions>
</MultiDataTrigger>
External linksDataTemplatesTriggersOther templatesHistory
|
||||||||||||||||||||||