Source project address: https://github.com/Microsoft/…
The following is to convert the sample into a brief description, and give the actual operation results and key codes at the same time:
–
Alternating Appearance OfItems Subitem Color Alternating Rendering
- Setting Group Property Description Items for Collection View Sources
<local:Places x:Key="Places"/>
<!--Group the items by State.-->
<CollectionViewSource Source="{StaticResource Places}" x:Key="GroupedData">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="State"/>
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
- Subitem Alternating Number Index Corresponding to Color Converter
<!--Returns a Brush for the header of a GroupItem.-->
<AlternationConverter x:Key="GroupHeaderBackgroundConverter">
<SolidColorBrush>LightBlue</SolidColorBrush>
<SolidColorBrush>LightSteelBlue</SolidColorBrush>
</AlternationConverter>
<!--Returns a Brush for a ListBoxItem.-->
<AlternationConverter x:Key="BackgroundConverter">
<SolidColorBrush>Silver</SolidColorBrush>
<SolidColorBrush>LightGray</SolidColorBrush>
<SolidColorBrush>GhostWhite</SolidColorBrush>
</AlternationConverter>
The above is considered as a resource item.
- ListBox sets relative bindings for grouping style, Title template, and data template, where background color is bound to the color converted by the index in the additional attribute ItemsControl. AlternationIndex in GroupItem.
Ps: The AlternationCount and ItemsControl. AlternationIndex properties allow you to specify the appearance of two or more alternate item containers. For example, you can specify alternating background colors for every two items in ItemsControl. ItemsControl. AlternationIndex is assigned to each container in ItemsControl. ItemsControl. AlternationIndex starts at 0, increases to 1 minus AlternationCount, and then restarts from 0.
<ListBox ItemsSource="{Binding Source={StaticResource GroupedData}}"
DisplayMemberPath="CityName" AlternationCount="3" Name="lb">
<ListBox.GroupStyle>
<!--Set alternating backgrounds on the header of each group.-->
<GroupStyle AlternationCount="2">
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock FontWeight="Bold"
Text="{Binding Path=Name}"
Background="{Binding
RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type GroupItem}},
Path=(ItemsControl.AlternationIndex),
Converter={StaticResource
GroupHeaderBackgroundConverter}}"/>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListBox.GroupStyle>
- Set the subitem Container style of ListBox, and bind the background color of the subitem to the color converted by its additional attribute ItemsControl. AlternationIndex
<ListBox.ItemContainerStyle>
<!--Set alternating backgrounds on the items in the ListBox.-->
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Background"
Value="{Binding RelativeSource={RelativeSource Self},
Path=(ItemsControl.AlternationIndex),
Converter={StaticResource BackgroundConverter}}"/>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
- TreeView resources, including data template, third layer background color alternating item converter, third layer data template; second layer font alternating item converter, first and second layer data template resources
<Grid.Resources>
<local:ListLeagueList x:Key="MyTreeViewData"/>
<!--Returns alternating brushes.-->
<AlternationConverter x:Key="TeamsBackgroundConverter">
<SolidColorBrush>LimeGreen</SolidColorBrush>
<SolidColorBrush>SpringGreen</SolidColorBrush>
<SolidColorBrush>Chartreuse</SolidColorBrush>
</AlternationConverter>
<!--The DataTemplate used by TreeViewItems in the third level
of the TreeView.-->
<DataTemplate x:Key="Level3Data">
<TextBlock Text="{Binding Path=Name}"
Background="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type TreeViewItem}},
Path=(ItemsControl.AlternationIndex),
Converter={StaticResource TeamsBackgroundConverter}}"/>
</DataTemplate>
<!--Returns altnernating FontStyles.-->
<AlternationConverter x:Key="LeagueFontStyleConverter">
<FontStyle >Italic</FontStyle>
<FontStyle >Normal</FontStyle>
</AlternationConverter>
<!--The HierarchicalDataTemplate used by TreeViewItems
in the second level of the TreeView.-->
<HierarchicalDataTemplate x:Key="Level2Data"
ItemsSource="{Binding Path=Teams}"
ItemTemplate="{StaticResource Level3Data}"
AlternationCount="3">
<TextBlock Text="{Binding Path=Name}"
FontStyle="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type TreeViewItem}},
Path=(ItemsControl.AlternationIndex),
Converter={StaticResource LeagueFontStyleConverter}}"/>
</HierarchicalDataTemplate>
<!--The HierarchicalDataTemplate used by TreeViewItems
in the first level of the TreeView.-->
<HierarchicalDataTemplate x:Key="Level1Data"
ItemsSource="{Binding Path=Divisions}"
ItemTemplate="{StaticResource Level2Data}"
AlternationCount="2">
<TextBlock Text="{Binding Path=Name}" FontWeight="Bold"/>
</HierarchicalDataTemplate>
<Style TargetType="TreeViewItem">
<Setter Property="IsExpanded" Value="True"/>
</Style>
</Grid.Resources>
- Finally, TreeView data source binding, sub-item template binding, and subsequent hierarchical template binding automatically according to ItemTemplate
<TreeView ItemsSource="{Binding Source={StaticResource MyTreeViewData}}"
ItemTemplate="{StaticResource Level1Data}"/>
ContentControl Style Content Control Style
- Label’s Style and Template Resources
<Grid.Resources>
<Style x:Key="ContentCtrl" TargetType="{x:Type ContentControl}">
<Setter Property="Background" Value="Red"/>
<Setter Property="Foreground" Value="Green"/>
<Setter Property="FontSize" Value="20"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ContentControl}">
<Grid>
<!--Keep the Ellipse a circle when ContentControl.Width
is set.-->
<Ellipse Width="{TemplateBinding Width}"
Height="{TemplateBinding Width}"
Fill="{TemplateBinding Background}"/>
<ContentPresenter VerticalAlignment="Center"
HorizontalAlignment="Center"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<DataTemplate x:Key="Template1">
<TextBlock Text="{Binding}" FontSize="12" FontWeight="Bold" TextWrapping="Wrap" />
</DataTemplate>
</Grid.Resources>
- Interface XAML code, Lablel is the ContentTemplate of contentControl bound to the data template
<Label Margin="10, 10, 3, 3" Grid.Column="0" Grid.Row="2">
<ContentControl Width="75" Style="{StaticResource ContentCtrl}"
Content="Hello"/>
</Label>
<!--Put the ContentControl in a Label just to keep the margin and
Grid cruft out of the snippet.-->
<Label Margin="10, 10, 3, 3" Grid.Column="0" Grid.Row="3"
Background="LightBlue">
<ContentControl Name="contCtrl" ContentTemplate="{StaticResource Template1}"
Content="This is the content of the content control."/>
</Label>
Event Triggers Event Triggers Event Triggers
<Style.Triggers>
<EventTrigger RoutedEvent="MouseEnter">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation To="300" Duration="0:0:1.5"
AccelerationRatio="0.10" DecelerationRatio="0.25"
Storyboard.TargetProperty="(Canvas.Width)" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="MouseLeave">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0:0:1.5"
AccelerationRatio="0.10" DecelerationRatio="0.25"
Storyboard.TargetProperty="(Canvas.Width)" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Style.Triggers>
## Finding Elements InTemplates Finding Elements in Templates##
- Content control template lookup element
private void ControlTemplateFindElement(object sender, RoutedEventArgs e)
{
// Finding the grid that is generated by the ControlTemplate of the Button
var gridInTemplate = (Grid) myButton1.Template.FindName("grid", myButton1);
// Do something to the ControlTemplate-generated grid
MessageBox.Show("The actual width of the grid in the ControlTemplate: "
+ gridInTemplate.GetValue(ActualWidthProperty));
}
- Finding Elements in Template Controls
private void DataTemplateFindElement(object sender, RoutedEventArgs e)
{
// Getting the currently selected ListBoxItem
// Note that the ListBox must have
// IsSynchronizedWithCurrentItem set to True for this to work
var myListBoxItem =
(ListBoxItem) (myListBox.ItemContainerGenerator.ContainerFromItem(myListBox.Items.CurrentItem));
// Getting the ContentPresenter of myListBoxItem
var myContentPresenter = FindVisualChild<ContentPresenter>(myListBoxItem);
// Finding textBlock from the DataTemplate that is set on that ContentPresenter
var myDataTemplate = myContentPresenter.ContentTemplate;
var myTextBlock = (TextBlock) myDataTemplate.FindName("textBlock", myContentPresenter);
// Do something to the DataTemplate-generated TextBlock
MessageBox.Show("The text of the TextBlock of the selected list item: "
+ myTextBlock.Text);
}
private TChildItem FindVisualChild<TChildItem>(DependencyObject obj)
where TChildItem : DependencyObject
{
for (var i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
var child = VisualTreeHelper.GetChild(obj, i);
if (child is TChildItem)
return (TChildItem) child;
var childOfChild = FindVisualChild<TChildItem>(child);
if (childOfChild != null)
return childOfChild;
}
return null;
}
The code for finding parent elements can be simplified as follows:
static DependencyObject VisualUpwardSearch<T>(DependencyObject source)
{
while (source != null && source.GetType() != typeof(T))
source = VisualTreeHelper.GetParent(source);
return source;
}
IntroToStyling AndTemplating introduces styles and templates
- ListBox style
<!--Horizontal ListBox Control Template-->
<Style TargetType="ListBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBox">
<Border CornerRadius="5" Background="{TemplateBinding ListBox.Background}">
<ScrollViewer HorizontalScrollBarVisibility="Auto" >
<StackPanel Orientation="Horizontal"
VerticalAlignment="Center"
HorizontalAlignment="Center"
IsItemsHost="True"/>
</ScrollViewer>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
- ListBox Item template
<Style TargetType="ListBoxItem">
<Setter Property="Opacity" Value="0.5" />
<Setter Property="MaxHeight" Value="75" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Trigger.Setters>
<Setter Property="Opacity" Value="1.0" />
</Trigger.Setters>
</Trigger>
<EventTrigger RoutedEvent="Mouse.MouseEnter">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Duration="0:0:0.2"
Storyboard.TargetProperty="MaxHeight"
To="90" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
<EventTrigger RoutedEvent="Mouse.MouseLeave">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Duration="0:0:1"
Storyboard.TargetProperty="MaxHeight" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
</Style>
- ListBox template
<!--DataTemplate to display Photos as images
instead of text strings of Paths-->
<DataTemplate DataType="{x:Type local:Photo}">
<Border Margin="3">
<Image Source="{Binding Source}"/>
</Border>
</DataTemplate>
- ListBox binding code
Ps: It is not recommended to set the width. The width of the source code makes it inconvenient for the scrollbar to display as the window changes.
<ListBox ItemsSource="{Binding Source={StaticResource MyPhotos}}"
Background="Silver" Margin="10" SelectedIndex="0"/>