源项目地址:https://github.com/Microsoft/...
以下是把样例转换为简要说明,同时给出实际运行效果及关键代码:
-

AlternatingAppearanceOfItems子项颜色交替变换呈现

clipboard.png

  • 设置集合视图源记分组属性描述项
<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>
  • 子项交替数索引对应颜色的转换器
<!--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>

以上作为资源项。

  • ListBox的分组样式、标题模板、数据模板 设置相对绑定,其中背景色绑定到GroupItem中的附加属性ItemsControl.AlternationIndex中索引转换出的颜色。

ps:AlternationCount 和 ItemsControl.AlternationIndex 属性允许您为两个或更多个交替项容器指定外观。例如,可以为 ItemsControl 中每隔两项的项目指定交替背景色。 ItemsControl.AlternationIndex 被分配给 ItemsControl 中的每一个容器。 ItemsControl.AlternationIndex 从 0 开始,增加到它为 AlternationCount 减 1 为止,然后从 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>
  • 设置ListBox的子项容器样式,子项背景色绑定到自身的附加属性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的资源,包括数据模板、第三层背景色交替项转换器、第三分层数据模板;第二分层字体交替项转换器、第一、二分层数据模板资源
<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>
  • 最后TreeView数据源绑定、子项模板绑定,后续分层模板根据ItemTemplate自动绑定
<TreeView ItemsSource="{Binding Source={StaticResource MyTreeViewData}}"
                          ItemTemplate="{StaticResource Level1Data}"/>

ContentControlStyle内容控件样式

clipboard.png

  • Label的样式及模板资源
<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>
  • 界面xaml代码,Lablel为contentControl的ContentTemplate绑定到数据模板
<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>

EventTriggers事件触发器

clipboard.png

<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>

## FindingElementsInTemplates在模板中查找元素 ##

clipboard.png

  • 内容控件模板查找元素
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));
}
  • 模板控件中查找元素
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;
}

其中查找父元素代码可简化为如下:

static DependencyObject VisualUpwardSearch<T>(DependencyObject source)
{
    while (source != null && source.GetType() != typeof(T))
        source = VisualTreeHelper.GetParent(source);

    return source;
}

IntroToStylingAndTemplating介绍样式与模板

clipboard.png

  • ListBox样式
<!--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>
  • ListBoxItem模板
<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模板
<!--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绑定代码

ps:建议不用设置宽度,源码设置宽度造成滚动条随窗口变化显示不方便

<ListBox ItemsSource="{Binding Source={StaticResource MyPhotos}}"
               Background="Silver"  Margin="10" SelectedIndex="0"/>

李志玮
22 声望34 粉丝

求索~~