ListView控件

ListView继承自简单的没有特色的ListBox,增加了对基于列显示的支持,并增加了快速切换视图或显示模式的能力,而不需要重新绑定数据以重新构建列表。

ListView类继承自ListBox类,并使用View属性进行扩展(可以创建丰富的列表)。通过两个样式来设置View,一个用于ListView控件,一个用于ListView控件的项。

使用GridView创建列

GridView类继承自ViewBase类,表示具有多列的列表视图,通过GridView.Columns集合添加GridViewColumn对象来定义列。

<ListView ItemsSource="{Binding DataList}">
            <ListView.View>
                <GridView>
                    <GridViewColumn Width="80" Header="{ex:Lang Key={x:Static langs:LangKeys.Index}}" DisplayMemberBinding="{Binding Index}"/>
                    <GridViewColumn Width="100" Header="{ex:Lang Key={x:Static langs:LangKeys.Name}}" DisplayMemberBinding="{Binding Name}"/>
                    <GridViewColumn Width="200" Header="{ex:Lang Key={x:Static langs:LangKeys.Remark}}" DisplayMemberBinding="{Binding Remark}"/>
                </GridView>
            </ListView.View>
        </ListView>

Head属性提供放在列顶部的文本,DisplayMemberBinding设置每个数据项要显示的信息。

  • 改变列的尺寸,可以设置固定宽度,但是会出现过长的数据被截断。没有MaxWidth和MinWidth属性。如果希望完全禁止改变列的尺寸,唯一办法就是为标题提供新模板
  • 单元格模板,为了显示数据,可以使用更高级的方式,为每个列设置CellTemplate属性(使用数据模板)
<ListView Margin="5" Name="lstProducts" GridViewColumnHeader.Click="gridViewColumn_Click">      
  <!--<ListView.ItemContainerStyle>
    <Style>
      <Setter Property="ListViewItem.Background" Value="{Binding Converter={StaticResource PriceToBackgroundConverter}}" />
    </Style>
  </ListView.ItemContainerStyle>-->
  <ListView.View>        
    <GridView>          
      <GridView.Columns>
        <GridViewColumn Header="Name" DisplayMemberBinding="{Binding Path=ModelName}" >              
        </GridViewColumn>
        <GridViewColumn Header="Model" DisplayMemberBinding="{Binding Path=ModelNumber}" />
        <GridViewColumn Header="Description" Width="300">
          <GridViewColumn.CellTemplate>
            <DataTemplate>
              <TextBlock Text="{Binding Path=Description}" TextWrapping="Wrap"></TextBlock>
            </DataTemplate>
          </GridViewColumn.CellTemplate>
        </GridViewColumn>
        <GridViewColumn Header="Picture" >
          <GridViewColumn.CellTemplate>
            <DataTemplate>
              <Image Source="{Binding Path=ProductImagePath, Converter={StaticResource ImagePathConverter}}"></Image>
            </DataTemplate>
          </GridViewColumn.CellTemplate>
        </GridViewColumn>
        <GridViewColumn Header="Price" DisplayMemberBinding="{Binding Path=UnitCost, StringFormat={}{0:C} }" >              
        </GridViewColumn>
      </GridView.Columns>
    </GridView>
  </ListView.View>
</ListView>
  • 自定义列标题,如果希望用自己的内容填充列标题,但又不希望单独给每列指定内容,可以使用GridViewColumn.HeaderTemplate属性定一个数据模板,这个数据模板可以绑定到Header属性中指定内容。如果希望重新定义指定列的标题,可以使用GridViewColumn.HeaderContainerStyle属性提供样式。如果希望以相同的方式重新定义所有列的标题,就需要使用GridView.ColumnHeaderContainerStyle属性。可以使用GridViewColumn.HeaderTemplate和GridView.ColumnHeaderTemplate改变指定列和所有列的外观。

自定义ListView的样式

可以通过改变ListView的样式来实现自定义的样式和模板

<Style x:Key="GridViewColumnHeaderGripper" TargetType="Thumb">
    <Setter Property="Canvas.Right" Value="-9"/>
    <Setter Property="Width" Value="18"/>
    <Setter Property="Height" Value="{Binding ActualHeight, RelativeSource={RelativeSource TemplatedParent}}"/>
    <Setter Property="Padding" Value="0"/>
    <Setter Property="Background" Value="Transparent"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Thumb">
                <Border Background="Transparent" Padding="{TemplateBinding Padding}">
                    <Rectangle Fill="{TemplateBinding Background}" HorizontalAlignment="Center" Width="1"/>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
<Style TargetType="GridViewColumnHeader">
    <Setter Property="VerticalContentAlignment" Value="Center"/>
    <Setter Property="HorizontalContentAlignment" Value="Left"/>
    <Setter Property="Foreground" Value="{DynamicResource PrimaryTextBrush}"/>
    <Setter Property="Padding" Value="12,6,12,12"/>
    <Setter Property="MinHeight" Value="44"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="GridViewColumnHeader">
                <hc:SimplePanel SnapsToDevicePixels="true">
                    <Border x:Name="HeaderBorder" BorderBrush="{TemplateBinding BorderBrush}" Background="Transparent">
                        <ContentPresenter x:Name="HeaderContent" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                    </Border>
                    <Canvas>
                        <Thumb x:Name="PART_HeaderGripper" Style="{StaticResource GridViewColumnHeaderGripper}"/>
                    </Canvas>
                </hc:SimplePanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
<Style x:Key="ListViewItemBaseStyle" TargetType="ListViewItem">
    <Setter Property="Background" Value="{DynamicResource RegionBrush}"/>
    <Setter Property="BorderThickness" Value="0"/>
    <Setter Property="Foreground" Value="{DynamicResource PrimaryTextBrush}"/>
    <Setter Property="SnapsToDevicePixels" Value="true"/>
    <Setter Property="Margin" Value="0,0,0,4"/>
    <Setter Property="Padding" Value="{StaticResource DefaultControlPadding}"/>
    <Setter Property="MinHeight" Value="44"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ListViewItem">
                <Border CornerRadius="4" x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
                    <GridViewRowPresenter Content="{TemplateBinding Content}" Columns="{TemplateBinding GridView.ColumnCollection}"/>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <Trigger Property="IsMouseOver" Value="true">
            <Setter Property="Background" Value="{DynamicResource DarkDefaultBrush}"/>
        </Trigger>
        <Trigger Property="IsSelected" Value="True">
            <Setter Property="Background" Value="{DynamicResource PrimaryBrush}"/>
            <Setter Property="TextElement.Foreground" Value="{DynamicResource TextIconBrush}"/>
        </Trigger>
        <MultiTrigger>
            <MultiTrigger.Conditions>
                <Condition Property="IsSelected" Value="true"/>
                <Condition Property="Selector.IsSelectionActive" Value="false"/>
            </MultiTrigger.Conditions>
            <Setter Property="Background" Value="{DynamicResource DarkDefaultBrush}"/>
            <Setter Property="Foreground" Value="{DynamicResource PrimaryTextBrush}"/>
        </MultiTrigger>
    </Style.Triggers>
</Style>
<Style TargetType="ListView">
    <Setter Property="Background" Value="{DynamicResource SecondaryRegionBrush}"/>
    <Setter Property="BorderBrush" Value="{DynamicResource BorderBrush}"/>
    <Setter Property="BorderThickness" Value="1"/>
    <Setter Property="Padding" Value="6"/>
    <Setter Property="Foreground" Value="{DynamicResource PrimaryTextBrush}"/>
    <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
    <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
    <Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
    <Setter Property="ScrollViewer.PanningMode" Value="Both"/>
    <Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
    <Setter Property="VerticalContentAlignment" Value="Center"/>
    <Setter Property="ItemContainerStyle" Value="{StaticResource ListViewItemBaseStyle}"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ListView">
                <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="True">
                    <hc:ToggleBlock IsChecked="{Binding HasItems,RelativeSource={RelativeSource TemplatedParent},Mode=OneWay}" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch">
                        <hc:ToggleBlock.CheckedContent>
                            <ScrollViewer>
                                <Grid Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
                                    <Grid.RowDefinitions>
                                        <RowDefinition Height="Auto"/>
                                        <RowDefinition Height="*"/>
                                    </Grid.RowDefinitions>
                                    <GridViewHeaderRowPresenter AllowsColumnReorder="{Binding View.AllowsColumnReorder, RelativeSource={RelativeSource TemplatedParent}}" ColumnHeaderContainerStyle="{Binding View.ColumnHeaderContainerStyle, RelativeSource={RelativeSource TemplatedParent}}" ColumnHeaderToolTip="{Binding View.ColumnHeaderToolTip, RelativeSource={RelativeSource TemplatedParent}}" ColumnHeaderContextMenu="{Binding View.ColumnHeaderContextMenu, RelativeSource={RelativeSource TemplatedParent}}" ColumnHeaderTemplate="{Binding View.ColumnHeaderTemplate, RelativeSource={RelativeSource TemplatedParent}}" Columns="{Binding View.Columns, RelativeSource={RelativeSource TemplatedParent}}" Margin="2,0" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                                    <ItemsPresenter Grid.Row="1"  SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                                </Grid>
                            </ScrollViewer>
                        </hc:ToggleBlock.CheckedContent>
                        <hc:ToggleBlock.UnCheckedContent>
                            <hc:Empty />
                        </hc:ToggleBlock.UnCheckedContent>
                    </hc:ToggleBlock>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <MultiTrigger>
            <MultiTrigger.Conditions>
                <Condition Property="IsGrouping" Value="true"/>
                <Condition Property="VirtualizingPanel.IsVirtualizingWhenGrouping" Value="false"/>
            </MultiTrigger.Conditions>
            <Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
        </MultiTrigger>
    </Style.Triggers>
</Style>

TreeView控件

TreeView是层次化容器,这意味着可创建多层数据展示。例如,可创建在第一级中显示类别组,并在每个类别节点中显示相关产品的TreeView控件。

TreeView控件本质上时驻留TreeViewItem对象的特殊ItemsControl控件。每个TreeViewItem对象都是单独的ItemsControl控件,所以可以嵌套的包含更多的TreeViewItem对象。

数据绑定

我们可以通过下面的数据源进行绑定到TreeView的ItemsSrouce。通过创建属性提供另一个集合的集合,是实现数据绑定导航父子关系的诀窍。

public class TreeItem : BindableBase
    {
        public TreeItem(object Item)
        {
            this.Item = Item;
        }
        //父
        public TreeItem Parent { get => _parent; set => SetProperty(ref _parent, value); }
        private TreeItem _parent;
        //子
        public ObservableCollection<TreeItem> Children { get; set; } = new ObservableCollection<TreeItem>();
        //级别
        public int IndexLevel { get; set; }
        //节点的数据
        public object Item { get => _item; set => SetProperty(ref _item, value); }
        private object _item;
        //节点图标路径
        public string ItemIcon { get; set; }
        //是否展开
        public bool IsExpanded { get => _isExpanded; set => SetProperty(ref _isExpanded, value); }
        private bool _isExpanded;         //CheckBox是否选中
        public bool? IsChecked { get => _isChecked; set => SetIsChecked(value, true, true); }
        private bool? _isChecked;
        private void SetIsChecked(bool? value, bool checkedChildren, bool checkedParent)
        {
            if (_isChecked == value) return;
            _isChecked = value;
            //选中和取消子类
            if (checkedChildren && value.HasValue && Children != null)
                Children.ToList().ForEach(ch => ch.SetIsChecked(value, true, false));
            //选中和取消父类
            if (checkedParent && this.Parent != null)
                this.Parent.CheckParentCheckState();
            //通知更改
            this.SetProperty(ref _isChecked, value);
        }
        //检查父类是否选中(如果父类的子类中有一个和第一个子类的状态不一样父类ischecked为null)
        private void CheckParentCheckState()
        {
            bool? _currentState = this.IsChecked;
            bool? _firstState = null;
            for (int i = 0; i < this.Children.Count(); i++)
            {
                bool? childrenState = this.Children[i].IsChecked;
                if (i == 0)
                {
                    _firstState = childrenState;
                }
                else if (_firstState != childrenState)
                {
                    _firstState = null;
                }
            }
            if (_firstState != null) _currentState = _firstState;
            SetIsChecked(_firstState, false, true);
        }         //选中的行 IsSelected
        public bool? IsSelected
        {
            get => _isSelected;
            set
            {
                _isSelected = value;
                this.SetProperty(ref _isSelected, value);
                if (value.HasValue && value.Value)
                {
                    SelectedTreeItem = this;
                    //MessageBox.Show("选中的是" + SelectedTreeItem.Name);
                }
                else
                    SelectedTreeItem = null;
            }
        }
        private bool? _isSelected;         //选中的数据
        public TreeItem SelectedTreeItem { get; set; }         //创建树
        public void CreateTreeWithChildren(TreeItem children, bool? isChecked = null)
        {
            this.Children.Add(children);
            children.Parent = this;
            children.IsChecked = isChecked;
        }
    }

TreeViewItem类继承自HeaderedItemsControl类,添加了Header属性,该属性包含了希望为树中每个项显示的内容(通常是文本)。如果显示非文本内容,最好使用TreeViewItem封装器,并通过TreeViewItem.Header属性提供内容,如果显示非UIElement对象,也可以通过HeaderTemplate属性的数据模板设置格式。

<TreeView ItemsSource="{Binding TreeItemsOrganization}" Style="{DynamicResource TreeViewStyleMain}" 
Background="White" BorderThickness="0" 
SelectedItemChanged="TreeView_SelectedItemChanged" >
    <!--cm:Message.Attach="[Event SeletedItemChanged] = [Action SeletedItemChanged]"> -->
    <TreeView.ItemContainerStyle>
        <Style TargetType="{x:Type TreeViewItem}">
            <Setter Property="IsExpanded" Value="{Binding Path=IsExpanded,Mode=TwoWay}" />
            <Setter Property="IsSelected" Value="{Binding Path=IsSelected,Mode=TwoWay}"/>
        </Style>
    </TreeView.ItemContainerStyle>
    <TreeView.Resources>
        <HierarchicalDataTemplate DataType="{x:Type local:TreeItem}" ItemsSource="{Binding Path=Children,Mode=OneWay}" >
            <StackPanel x:Name="My_SP"  Orientation="Horizontal" Margin="2">
                <Image VerticalAlignment="Center" Source="{Binding itemIcon}" />
                <ContentPresenter  Content="{Binding Path=Item,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" Margin="2,0"/>
            </StackPanel>
        </HierarchicalDataTemplate>
    </TreeView.Resources>
</TreeView>

上述代码中,通过HierarchicalDataTemplate来设置TreeView.ItemTemplate属性,而不是DataTemplate对象。前者能够封装第二个模板,然后HierarchicalDataTemplate就可以从第一层数据中提起项的集合,提供给第二层的模板:

<TreeView.ItemTemplate>



</TreeView.ItemTemplate>

更复杂一点的就是:

实际上,上述代码有两个模板,每个模板用于书控件中的每个层次。第二个模板使用从第一个模板中选择的项作为其数据源。

自定义控件的样式和模板:

<Style x:Key="ExpandCollapseToggleStyle" TargetType="ToggleButton">
        <Setter Property="Focusable" Value="False" />
        <Setter Property="Width" Value="16" />
        <Setter Property="Height" Value="16" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="ToggleButton">
                    <Border Width="16" Height="16" Padding="4" Background="Transparent">
                        <Path x:Name="ExpandPath" Data="{StaticResource TreeArrow}" Fill="{Binding Foreground, RelativeSource={RelativeSource AncestorType=TreeViewItem}}" RenderTransformOrigin="0.5,0.5" Stretch="Uniform">
                            <Path.RenderTransform>
                                <RotateTransform Angle="-90" />
                            </Path.RenderTransform>
                        </Path>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsChecked" Value="True">
                            <Setter TargetName="ExpandPath" Property="RenderTransform">
                                <Setter.Value>
                                    <RotateTransform Angle="0" />
                                </Setter.Value>
                            </Setter>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <Style x:Key="TreeViewItemBaseStyle" BasedOn="{StaticResource BaseStyle}" TargetType="TreeViewItem">
        <Setter Property="FocusVisualStyle" Value="{StaticResource FocusVisualRadius0Margin0}" />
        <Setter Property="Background" Value="Transparent" />
        <Setter Property="Padding" Value="10,0" />
        <Setter Property="BorderThickness" Value="0" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="TreeViewItem">
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition MinHeight="{StaticResource DefaultControlHeight}" />
                            <RowDefinition />
                        </Grid.RowDefinitions>
                        <Border
                            x:Name="Bd"
                            Padding="{TemplateBinding Padding}"
                            Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            CornerRadius="{Binding Path=(hc:BorderElement.CornerRadius), RelativeSource={RelativeSource TemplatedParent}}"
                            SnapsToDevicePixels="true">
                            <DockPanel Margin="{Binding Converter={StaticResource TreeViewItemMarginConverter}, RelativeSource={RelativeSource TemplatedParent}}" LastChildFill="True">
                                <ToggleButton x:Name="Expander" ClickMode="Press" IsChecked="{Binding IsExpanded, RelativeSource={RelativeSource TemplatedParent}}" Style="{StaticResource ExpandCollapseToggleStyle}" />
                                <ContentPresenter x:Name="PART_Header" VerticalAlignment="Center" ContentSource="Header" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                            </DockPanel>
                        </Border>
                        <ItemsPresenter x:Name="ItemsHost" Grid.Row="1" />
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger SourceName="Bd" Property="IsMouseOver" Value="true">
                            <Setter TargetName="Bd" Property="Background" Value="{DynamicResource SecondaryRegionBrush}" />
                        </Trigger>
                        <Trigger Property="IsExpanded" Value="false">
                            <Setter TargetName="ItemsHost" Property="Visibility" Value="Collapsed" />
                        </Trigger>
                        <Trigger Property="HasItems" Value="false">
                            <Setter TargetName="Expander" Property="Visibility" Value="Hidden" />
                        </Trigger>
                        <Trigger Property="IsSelected" Value="true">
                            <Setter TargetName="Bd" Property="Background" Value="{DynamicResource PrimaryBrush}" />
                            <Setter Property="Foreground" Value="{DynamicResource TextIconBrush}" />
                        </Trigger>
                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="IsSelected" Value="true" />
                                <Condition Property="IsSelectionActive" Value="false" />
                            </MultiTrigger.Conditions>
                            <Setter TargetName="Bd" Property="Background" Value="{DynamicResource DarkDefaultBrush}" />
                            <Setter Property="Foreground" Value="{DynamicResource PrimaryTextBrush}" />
                        </MultiTrigger>
                        <Trigger Property="IsEnabled" Value="false">
                            <Setter Property="Foreground" Value="{StaticResource {x:Static SystemColors.GrayTextBrushKey}}" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <Style x:Key="TreeViewBaseStyle" BasedOn="{StaticResource BaseStyle}" TargetType="TreeView">
        <Setter Property="Focusable" Value="False" />
        <Setter Property="Background" Value="{DynamicResource RegionBrush}" />
        <Setter Property="BorderBrush" Value="{DynamicResource BorderBrush}" />
        <Setter Property="BorderThickness" Value="1" />
        <Setter Property="Padding" Value="0" />
        <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto" />
        <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto" />
        <Setter Property="ScrollViewer.PanningMode" Value="Both" />
        <Setter Property="hc:ScrollViewer.IsInertiaEnabled" Value="False" />
        <Setter Property="Stylus.IsFlicksEnabled" Value="False" />
        <Setter Property="VerticalContentAlignment" Value="Center" />
        <Setter Property="VirtualizingPanel.IsVirtualizing" Value="True" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="TreeView">
                    <Border x:Name="Bd" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" SnapsToDevicePixels="true">
                        <hc:ToggleBlock HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" IsChecked="{Binding HasItems, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}">
                            <hc:ToggleBlock.CheckedContent>
                                <hc:ScrollViewer
                                    x:Name="_tv_scrollviewer_"
                                    Padding="{TemplateBinding Padding}"
                                    Background="{TemplateBinding Background}"
                                    CanContentScroll="false"
                                    Focusable="false"
                                    HorizontalScrollBarVisibility="{TemplateBinding ScrollViewer.HorizontalScrollBarVisibility}"
                                    IsInertiaEnabled="{Binding Path=(hc:ScrollViewer.IsInertiaEnabled), RelativeSource={RelativeSource TemplatedParent}}"
                                    SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                                    Template="{StaticResource ScrollViewerBaseControlTemplate}"
                                    VerticalScrollBarVisibility="{TemplateBinding ScrollViewer.VerticalScrollBarVisibility}">
                                    <ItemsPresenter />
                                </hc:ScrollViewer>
                            </hc:ToggleBlock.CheckedContent>
                            <hc:ToggleBlock.UnCheckedContent>
                                <hc:Empty />
                            </hc:ToggleBlock.UnCheckedContent>
                        </hc:ToggleBlock>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsEnabled" Value="false">
                            <Setter TargetName="Bd" Property="Background" Value="{StaticResource {x:Static SystemColors.ControlBrushKey}}" />
                        </Trigger>
                        <Trigger Property="VirtualizingPanel.IsVirtualizing" Value="true">
                            <Setter TargetName="_tv_scrollviewer_" Property="CanContentScroll" Value="true" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
        <Style.Triggers>
            <Trigger Property="VirtualizingPanel.IsVirtualizing" Value="true">
                <Setter Property="ItemsPanel">
                    <Setter.Value>
                        <ItemsPanelTemplate>
                            <VirtualizingStackPanel />
                        </ItemsPanelTemplate>
                    </Setter.Value>
                </Setter>
            </Trigger>
        </Style.Triggers>
    </Style>

DataGrid控件

DataGrid是最完备的数据显示工具。他将数据分割到包含行列的网格中,就想ListView控件,但是DataGrid控件具有其他格式化特性(如:冻结列、设置单行样式),并且支持就地编辑数据。DataGrid控件从对象集合获取信息并在具有行和单元格的网络中显示信息。每行和单独的对象相对应,并且每列和对象的某个属性相对应。其选择模型允许选择一行、多行或者一些单元格的组合。

为创建暂时应急的DataGrid控件,可使用自动列生成功能:

AutoGenerateColumns=true

DataGrid的基本显示属性:

名称 说明
RowBackground
AlternatingRowBackground
用于绘制每行北京的画刷,并且决定是否使用不同的背景颜色绘制交替行,从而更容易区分行
ColumnHeaderHeight 位于DataGrid控件顶部的列标题行的高度
RowHeaderWidth 具有行题头的列的宽度。该列在网格的最左边,不显示任何数据。该列使用箭头指示当前选择的行,使用圈住的箭头指示正在编辑的行
ColumnWidth DataGridLength对象,用于设置每列默认宽度的尺寸改变模式
RowHeight 每行的高度。如果准备在DataGrid控件中显示多行文本或者不同的内容(图像等),该设置很有用。与列不同,用户不能改变行的尺寸
GridLinesVisibility 确定是否显示网格线的DataGridGridLines枚举值
VerticalGridLinesBrush 用于绘制列之间网格线的画刷
HorizontalGridLinesBrush 用于绘制行之间网格线的画刷
HeadersVisibity 确定显示哪个题头的DataGrisHeaders枚举值
HorizontalScrollBarVisibility
VerticalScrollBarVisibility
去顶是否显示滚动条的枚举值。默认是Auto(当需要时显示)

改变列的尺寸与重新安排列

当显示自动生成的列时,DataGrid控件尝试根据DataGrid.ColumnWidth属性智能地改变每列的宽度。

为设置ColumnWidth属性,需要提供DataGridLength对象。DataGridLength对象能够指定确切的尺寸或者指定特定的尺寸改变模式,从而让DataGrid控件自动完成。

grid.ColumnWidth=new DataGridLength(150);

使用足够的列宽来适应他们的题头文本:

grid.ColumnWidth=DataGridLength.SizeToHeader;

加宽每一列以适应当前视图中最宽的值:

grid.ColumnWidth=DataGridLength.SizeToCells;

加宽每一列以适应最大的显示值或者题头文本,使用其中的最大值:

grid.ColumnWidth=DataGridLength.Auto;

通常,用户能够通过将列边缘拖动到任意位置来改变列的尺寸。可通过将CanUserResizeColumns属性设置为false来阻止这一行为。也可以将列的CanUserResize属性设置为false,阻止用户改变特定列的尺寸。通过CanUserReorderColumns属性或者特定列的CanUserReorder属性设置为false来阻止用户改变列的位置。

定义列

将AutoGenerateColumns属性设置为false以关闭自动列生成功能。然后可以使用希望的设置和指定的顺序,明确地定义希望使用的列。使用合适的列对象来填充DataGrid.Columns集合。

  • DataGridTextColumn:这种列对于大部分数据类型时标准选择,值转换成文本
  • DataGridCheckBoxColumn:列显示复选框。通常是只读的,当编辑行时,会成为普通的复选框
  • DataGridHyperlinkColumn:显示单击的链接
  • DataGridComboBox:这种列最初和DataGridTextColumn类似,在编辑模式下,就编程可以下拉的ComboBox控件
  • DataGridTemplateColumn:这种列允许显示值定义数据模板。

设置列的格式和样式

可使用设置TextBlock格式相同的方式设置DataGridTextColumn格式,但是无法设置多行显示,需要使用ElementStyle属性了设置,使用具有多行显示的TextBlock样式即可。

属性 说明
ColumnHeaderStyle 位于网格顶部的列题头的TextBlock
RowHeaderStyle 行题头的TextBlock。一般用复选框做控件模板
DragIndicatorStyle 当用户正在将列题头拖动到新位置时用于列题头的TextBlock
RowStyle 用于普通行的TextBlock(没有通过列的ElementStyle属性明确定制过的行)

设置行的格式

DataGrid.LoadingRow事件:当每一行出现在屏幕上时,都会触发LoadingRow事件。当用户在网格中滚动是,会连续触发事件,所以不能在事件中进行耗时的处理。

显示行细节

DataGrid支持行细节(row details),一块可选的独立显示区域,在行的列值下面显示。

  • 能够跨越DataGrid控件的整个宽度,并且不会切入到独立的列中,从而提供了更过可供使用的空间
  • 可配置行细节区域,从而只为选择的行显示该区域,当不需要时,允许用户折叠额外的细节

可以通过设置属性DataGrid.RowDetailsTemplate属性,来定义行细节区域显示的内容。

可以通过设置DataGrid.0RowDetailsVisibilityMode属性来设置行细节区域的显示行为,默认是VisibleWhenSelected。

冻结列

冻结列位于DataGrid 控件的左边,甚至当向右滚动时,冻结列任然在左边。对于非常宽的网格,冻结列非常的有用,可以保持某些信息始终可见。通过属性FrozenColumnCount属性设置大于0的数。

冻结列必须总是位于网格的左侧,如果是1列,则就是最左边的那列,如果是2列,那就是最左边的两列。

选择

和普通的列表控件类似,DataGrid允许用户选择单个项,并且响应SelectionChanged事件。可以使用SelectedItem属性来找到当前选中的项。可以通过SelectionMode属性来设置单选还是多选。为了选择多行,用户必须按下Shift或者Ctrl键。通常我们可以在RowHeader中放置CheckBox来显示哪行被选中,也可以通过CheckBox直接选中某行或者多行。

排序

可以通过单击列题头来实现列的排序,可以通过设置SortMemberPath属性从绑定的数据对象中选择不同的属性来排序。可以通过CanUserSortColumns属性或者特定列的CanUserSort属性设置为false来禁止排序功能

编辑

一般情况下,DataGrid多数用于数据展示,编辑的话比较少用,可以通过属性DataGrid.IsReadOnly或者DataGridColumn.IsReadOnly属性设置为false来禁用编辑功能。

列举一个DataGrid的样式:

<Style x:Key="RowHeaderGripperStyle" TargetType="Thumb">
        <Setter Property="Height" Value="8"/>
        <Setter Property="Background" Value="Transparent"/>
        <Setter Property="Cursor" Value="SizeNS"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Thumb">
                    <Border Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}"/>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <Style x:Key="DataGridCellStyle" TargetType="DataGridCell">
        <Setter Property="FocusVisualStyle">
            <Setter.Value>
                <Style>
                    <Setter Property="Control.Template">
                        <Setter.Value>
                            <ControlTemplate>
                                <Rectangle Margin="2" Opacity=".6" SnapsToDevicePixels="true" Stroke="{DynamicResource SecondaryBorderBrush}" StrokeThickness="2" StrokeDashArray="1 1" RadiusX="4" RadiusY="4"/>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </Setter.Value>
        </Setter>
        <Setter Property="Background" Value="Transparent"/>
        <Setter Property="BorderBrush" Value="Transparent"/>
        <Setter Property="BorderThickness" Value="0"/>
        <Setter Property="VerticalContentAlignment" Value="Center"/>
        <Setter Property="HorizontalContentAlignment" Value="Left"/>
        <Setter Property="Padding" Value="{StaticResource DefaultControlPadding}"/>
        <Setter Property="hc:BorderElement.CornerRadius" Value="{StaticResource DefaultCornerRadius}"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="DataGridCell">
                    <Border Background="Transparent">
                        <Border Margin="0,0,4,0"  CornerRadius="{Binding Path=(hc:BorderElement.CornerRadius),RelativeSource={RelativeSource TemplatedParent}}" Padding="{TemplateBinding Padding}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
                            <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                        </Border>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
        <Style.Triggers>
            <MultiDataTrigger>
                <MultiDataTrigger.Conditions>
                    <Condition Binding="{Binding IsSelected,RelativeSource={RelativeSource Self}}" Value="true"/>
                    <Condition Binding="{Binding SelectionUnit,RelativeSource={RelativeSource FindAncestor,AncestorType=DataGrid}}" Value="Cell"/>
                </MultiDataTrigger.Conditions>
                <Setter Property="Foreground" Value="{DynamicResource TextIconBrush}"/>
                <Setter Property="Background" Value="{DynamicResource PrimaryBrush}"/>
            </MultiDataTrigger>
            <MultiDataTrigger>
                <MultiDataTrigger.Conditions>
                    <Condition Binding="{Binding IsSelected,RelativeSource={RelativeSource Self}}" Value="true"/>
                    <Condition Binding="{Binding IsSelected,RelativeSource={RelativeSource AncestorType=DataGridRow}}" Value="False"/>
                    <Condition Binding="{Binding SelectionUnit,RelativeSource={RelativeSource FindAncestor,AncestorType=DataGrid}}" Value="CellOrRowHeader"/>
                </MultiDataTrigger.Conditions>
                <Setter Property="Foreground" Value="{DynamicResource TextIconBrush}"/>
                <Setter Property="Background" Value="{DynamicResource PrimaryBrush}"/>
            </MultiDataTrigger>
            <MultiDataTrigger>
                <MultiDataTrigger.Conditions>
                    <Condition Binding="{Binding IsSelected,RelativeSource={RelativeSource Self}}" Value="true"/>
                    <Condition Binding="{Binding IsSelected,RelativeSource={RelativeSource AncestorType=DataGridRow}}" Value="True"/>
                    <Condition Binding="{Binding SelectionUnit,RelativeSource={RelativeSource FindAncestor,AncestorType=DataGrid}}" Value="CellOrRowHeader"/>
                </MultiDataTrigger.Conditions>
                <Setter Property="Foreground" Value="{DynamicResource TextIconBrush}"/>
            </MultiDataTrigger>
            <MultiDataTrigger>
                <MultiDataTrigger.Conditions>
                    <Condition Binding="{Binding IsSelected,RelativeSource={RelativeSource Self}}" Value="true"/>
                    <Condition Binding="{Binding SelectionUnit,RelativeSource={RelativeSource FindAncestor,AncestorType=DataGrid}}" Value="FullRow"/>
                </MultiDataTrigger.Conditions>
                <Setter Property="Foreground" Value="{DynamicResource TextIconBrush}"/>
            </MultiDataTrigger>
            <MultiTrigger>
                <MultiTrigger.Conditions>
                    <Condition Property="IsSelected" Value="true"/>
                    <Condition Property="Selector.IsSelectionActive" Value="false"/>
                </MultiTrigger.Conditions>
                <Setter Property="Background" Value="{DynamicResource DarkDefaultBrush}"/>
                <Setter Property="Foreground" Value="{DynamicResource PrimaryTextBrush}"/>
            </MultiTrigger>
        </Style.Triggers>
    </Style>
    <Style x:Key="DataGridRowStyle" TargetType="DataGridRow">
        <Setter Property="Background" Value="{DynamicResource RegionBrush}"/>
        <Setter Property="Foreground" Value="{DynamicResource PrimaryTextBrush}"/>
        <Setter Property="SnapsToDevicePixels" Value="true"/>
        <Setter Property="Margin" Value="0,0,0,4"/>
        <Setter Property="Padding" Value="0,6"/>
        <Setter Property="MinHeight" Value="44"/>
        <Setter Property="Validation.ErrorTemplate" Value="{x:Null}"/>
        <Setter Property="ValidationErrorTemplate">
            <Setter.Value>
                <ControlTemplate>
                    <TextBlock Foreground="Red" Margin="2,0,0,0" Text="!" VerticalAlignment="Center"/>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="DataGridRow">
                    <SelectiveScrollingGrid>
                        <SelectiveScrollingGrid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto"/>
                            <ColumnDefinition Width="*"/>
                        </SelectiveScrollingGrid.ColumnDefinitions>
                        <SelectiveScrollingGrid.RowDefinitions>
                            <RowDefinition Height="*"/>
                            <RowDefinition Height="Auto"/>
                        </SelectiveScrollingGrid.RowDefinitions>
                        <Border CornerRadius="4" Grid.ColumnSpan="2" x:Name="DGR_Border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True"/>
                        <DataGridCellsPresenter MinHeight="{TemplateBinding MinHeight}" VerticalContentAlignment="Center" Grid.Row="0" Grid.Column="1" ItemsPanel="{TemplateBinding ItemsPanel}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                        <DataGridDetailsPresenter Margin="0,6" Grid.Column="1" Grid.Row="1" SelectiveScrollingGrid.SelectiveScrollingOrientation="{Binding AreRowDetailsFrozen, ConverterParameter={x:Static SelectiveScrollingOrientation.Vertical}, Converter={x:Static DataGrid.RowDetailsScrollingConverter}, RelativeSource={RelativeSource AncestorType=DataGrid}}" Visibility="{TemplateBinding DetailsVisibility}"/>
                        <DataGridRowHeader Grid.Row="0" Grid.Column="0" SelectiveScrollingGrid.SelectiveScrollingOrientation="Vertical" Visibility="{Binding HeadersVisibility, ConverterParameter={x:Static DataGridHeadersVisibility.Row}, Converter={x:Static DataGrid.HeadersVisibilityConverter}, RelativeSource={RelativeSource AncestorType=DataGrid}}"/>
                    </SelectiveScrollingGrid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
        <Style.Triggers>
            <Trigger Property="IsMouseOver" Value="true">
                <Setter Property="Background" Value="{DynamicResource DarkDefaultBrush}"/>
            </Trigger>
            <Trigger Property="IsSelected" Value="True">
                <Setter Property="Background" Value="{DynamicResource PrimaryBrush}"/>
                <Setter Property="TextElement.Foreground" Value="{DynamicResource TextIconBrush}"/>
            </Trigger>
            <MultiTrigger>
                <MultiTrigger.Conditions>
                    <Condition Property="IsSelected" Value="true"/>
                    <Condition Property="Selector.IsSelectionActive" Value="false"/>
                </MultiTrigger.Conditions>
                <Setter Property="Background" Value="{DynamicResource DarkDefaultBrush}"/>
                <Setter Property="Foreground" Value="{DynamicResource PrimaryTextBrush}"/>
            </MultiTrigger>
        </Style.Triggers>
    </Style>
    <Style x:Key="ColumnHeaderGripperStyle" TargetType="Thumb">
        <Setter Property="Width" Value="8"/>
        <Setter Property="Background" Value="Transparent"/>
        <Setter Property="Cursor" Value="SizeWE"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Thumb">
                    <Border Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}"/>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <Style x:Key="DataGridColumnHeaderStyle" TargetType="DataGridColumnHeader">
        <Setter Property="VerticalContentAlignment" Value="Center"/>
        <Setter Property="Foreground" Value="{DynamicResource PrimaryTextBrush}"/>
        <Setter Property="Padding" Value="12,6,12,12"/>
        <Setter Property="MinHeight" Value="44"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="DataGridColumnHeader">
                    <hc:SimplePanel>
                        <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="Transparent" Padding="{TemplateBinding Padding}">
                            <Grid HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition/>
                                    <ColumnDefinition Width="Auto"/>
                                </Grid.ColumnDefinitions>
                                <ContentPresenter RecognizesAccessKey="True" VerticalAlignment="Center" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                                <ToggleButton Grid.Column="1" VerticalAlignment="Center" Height="{x:Static system:Double.NaN}" Padding="4,0" Width="20" IsEnabled="False" Opacity="1" Foreground="{DynamicResource PrimaryBrush}" x:Name="ToggleButtonSortDirection" Style="{StaticResource ToggleButtonIconTransparent}" hc:IconSwitchElement.Geometry="{StaticResource DownGeometry}" hc:IconSwitchElement.GeometrySelected="{StaticResource UpGeometry}"/>
                            </Grid>
                        </Border>
                        <Thumb x:Name="PART_LeftHeaderGripper" HorizontalAlignment="Left" Style="{StaticResource ColumnHeaderGripperStyle}"/>
                        <Thumb x:Name="PART_RightHeaderGripper" HorizontalAlignment="Right" Style="{StaticResource ColumnHeaderGripperStyle}"/>
                    </hc:SimplePanel>
                    <ControlTemplate.Triggers>
                        <Trigger Property="SortDirection" Value="{x:Null}">
                            <Setter Property="Visibility" Value="Collapsed" TargetName="ToggleButtonSortDirection"/>
                        </Trigger>
                        <Trigger Property="SortDirection" Value="Ascending">
                            <Setter Property="IsChecked" Value="True" TargetName="ToggleButtonSortDirection"/>
                        </Trigger>
                        <Trigger Property="SortDirection" Value="Descending">
                            <Setter Property="IsChecked" Value="False" TargetName="ToggleButtonSortDirection"/>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
        <Style.Triggers>
            <Trigger Property="SortDirection" Value="Ascending">
                <Setter Property="Foreground" Value="{DynamicResource PrimaryBrush}"/>
            </Trigger>
            <Trigger Property="SortDirection" Value="Descending">
                <Setter Property="Foreground" Value="{DynamicResource PrimaryBrush}"/>
                <Setter Property="Foreground" Value="{DynamicResource PrimaryBrush}"/>
            </Trigger>
        </Style.Triggers>
    </Style>
    <Style x:Key="DataGridRowHeaderStyle" TargetType="DataGridRowHeader">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="DataGridRowHeader">
                    <hc:SimplePanel HorizontalAlignment="Center">
                        <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="Transparent" Padding="{TemplateBinding Padding}" >
                            <StackPanel Orientation="Horizontal">
                                <ContentPresenter RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="Center"/>
                            </StackPanel>
                        </Border>
                        <Thumb x:Name="PART_TopHeaderGripper" Style="{StaticResource RowHeaderGripperStyle}" VerticalAlignment="Top"/>
                        <Thumb x:Name="PART_BottomHeaderGripper" Style="{StaticResource RowHeaderGripperStyle}" VerticalAlignment="Bottom"/>
                    </hc:SimplePanel>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <Style x:Key="TextBlockComboBoxStyle" TargetType="ComboBox">
        <Setter Property="Focusable" Value="True"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="ComboBox">
                    <TextBlock IsHitTestVisible="False" Text="{TemplateBinding Text}" TextTrimming="CharacterEllipsis"/>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <Style x:Key="DataGridTextColumnStyle" TargetType="TextBlock">
        <Setter Property="TextTrimming" Value="CharacterEllipsis"/>
    </Style>
    <Style TargetType="DataGrid">
        <Setter Property="Background" Value="{DynamicResource SecondaryRegionBrush}"/>
        <Setter Property="BorderBrush" Value="{DynamicResource BorderBrush}"/>
        <Setter Property="BorderThickness" Value="0"/>
        <Setter Property="GridLinesVisibility" Value="None"/>
        <Setter Property="RowDetailsVisibilityMode" Value="VisibleWhenSelected"/>
        <Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
        <Setter Property="ScrollViewer.PanningMode" Value="Both"/>
        <Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
        <Setter Property="EnableRowVirtualization" Value="True"/>
        <Setter Property="CanUserAddRows" Value="False"/>
        <Setter Property="CanUserDeleteRows" Value="False"/>
        <Setter Property="CanUserReorderColumns" Value="False"/>
        <Setter Property="CanUserResizeRows" Value="False"/>
        <Setter Property="ColumnHeaderStyle" Value="{StaticResource DataGridColumnHeaderStyle}"/>
        <Setter Property="RowHeaderStyle" Value="{StaticResource DataGridRowHeaderStyle}"/>
        <Setter Property="RowStyle" Value="{StaticResource DataGridRowStyle}"/>
        <Setter Property="CellStyle" Value="{StaticResource DataGridCellStyle}"/>
        <Setter Property="Padding" Value="6"/>
        <Setter Property="ColumnWidth" Value="*"/>
        <Setter Property="hc:DataGridAttach.TextColumnStyle" Value="{StaticResource DataGridTextColumnStyle}"/>
        <Setter Property="hc:DataGridAttach.EditingTextColumnStyle" Value="{StaticResource TextBoxBaseStyle}"/>
        <Setter Property="hc:DataGridAttach.ComboBoxColumnStyle" Value="{StaticResource TextBlockComboBoxStyle}"/>
        <Setter Property="hc:DataGridAttach.EditingComboBoxColumnStyle" Value="{StaticResource ComboBoxBaseStyle}"/>
        <Setter Property="hc:DataGridAttach.CheckBoxColumnStyle" Value="{StaticResource CheckBoxBaseStyle}"/>
        <Setter Property="hc:DataGridAttach.EditingCheckBoxColumnStyle" Value="{StaticResource CheckBoxBaseStyle}"/>
        <Setter Property="hc:DataGridAttach.ApplyDefaultStyle" Value="True"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="DataGrid">
                    <ControlTemplate.Resources>
                        <Storyboard x:Key="Storyboard1">
                            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PART_VerticalScrollBar">
                                <EasingDoubleKeyFrame KeyTime="0:0:.2" Value=".8"/>
                            </DoubleAnimationUsingKeyFrames>
                            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PART_HorizontalScrollBar">
                                <EasingDoubleKeyFrame KeyTime="0:0:.2" Value=".8"/>
                            </DoubleAnimationUsingKeyFrames>
                        </Storyboard>
                        <Storyboard x:Key="Storyboard2">
                            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PART_VerticalScrollBar">
                                <EasingDoubleKeyFrame KeyTime="0:0:.2" Value="0"/>
                            </DoubleAnimationUsingKeyFrames>
                            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PART_HorizontalScrollBar">
                                <EasingDoubleKeyFrame KeyTime="0:0:.2" Value="0"/>
                            </DoubleAnimationUsingKeyFrames>
                        </Storyboard>
                    </ControlTemplate.Resources>
                    <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="True">
                        <hc:ToggleBlock IsChecked="{Binding HasItems,RelativeSource={RelativeSource TemplatedParent},Mode=OneWay}" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch">
                            <hc:ToggleBlock.CheckedContent>
                                <ScrollViewer x:Name="DG_ScrollViewer" Focusable="false">
                                    <ScrollViewer.Template>
                                        <ControlTemplate TargetType="ScrollViewer">
                                            <Grid>
                                                <Grid.ColumnDefinitions>
                                                    <ColumnDefinition Width="Auto"/>
                                                    <ColumnDefinition Width="*"/>
                                                    <ColumnDefinition Width="Auto"/>
                                                </Grid.ColumnDefinitions>
                                                <Grid.RowDefinitions>
                                                    <RowDefinition Height="Auto"/>
                                                    <RowDefinition Height="*"/>
                                                </Grid.RowDefinitions>
                                                <Button Command="{x:Static DataGrid.SelectAllCommand}" Margin="0,0,0,6" Visibility="{Binding HeadersVisibility, ConverterParameter={x:Static DataGridHeadersVisibility.All}, Converter={x:Static DataGrid.HeadersVisibilityConverter}, RelativeSource={RelativeSource AncestorType=DataGrid}}" Width="{Binding CellsPanelHorizontalOffset, RelativeSource={RelativeSource AncestorType=DataGrid},Converter={StaticResource DoubleMinConverter}}" Style="{StaticResource ButtonIcon}" hc:IconElement.Geometry="{StaticResource AllGeometry}" Foreground="{DynamicResource PrimaryBrush}"/>
                                                <DataGridColumnHeadersPresenter x:Name="PART_ColumnHeadersPresenter" Grid.ColumnSpan="2" Grid.Row="0" Grid.Column="1" Visibility="{Binding HeadersVisibility, ConverterParameter={x:Static DataGridHeadersVisibility.Column}, Converter={x:Static DataGrid.HeadersVisibilityConverter}, RelativeSource={RelativeSource AncestorType=DataGrid}}"/>
                                                <ScrollContentPresenter x:Name="PART_ScrollContentPresenter" CanContentScroll="{TemplateBinding CanContentScroll}" Grid.ColumnSpan="3" Grid.Column="0" Grid.Row="1"/>
                                                <ScrollBar Style="{StaticResource ScrollBarBaseStyle}" Opacity="0" x:Name="PART_VerticalScrollBar" Grid.Column="2" Maximum="{TemplateBinding ScrollableHeight}" Orientation="Vertical" Grid.Row="1" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" Value="{Binding VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportHeight}"/>
                                                <ScrollBar Style="{StaticResource ScrollBarBaseStyle}" Opacity="0" x:Name="PART_HorizontalScrollBar" Grid.Column="1" Maximum="{TemplateBinding ScrollableWidth}" Orientation="Horizontal" VerticalAlignment="Bottom" Grid.Row="1" Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" Value="{Binding HorizontalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportWidth}"/>
                                            </Grid>
                                            <ControlTemplate.Triggers>
                                                <EventTrigger RoutedEvent="MouseEnter">
                                                    <BeginStoryboard Storyboard="{StaticResource Storyboard1}"/>
                                                </EventTrigger>
                                                <EventTrigger RoutedEvent="MouseLeave">
                                                    <BeginStoryboard Storyboard="{StaticResource Storyboard2}"/>
                                                </EventTrigger>
                                            </ControlTemplate.Triggers>
                                        </ControlTemplate>
                                    </ScrollViewer.Template>
                                    <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                                </ScrollViewer>
                            </hc:ToggleBlock.CheckedContent>
                            <hc:ToggleBlock.UnCheckedContent>
                                <hc:Empty />
                            </hc:ToggleBlock.UnCheckedContent>
                        </hc:ToggleBlock>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
        <Style.Triggers>
            <MultiTrigger>
                <MultiTrigger.Conditions>
                    <Condition Property="IsGrouping" Value="true"/>
                    <Condition Property="VirtualizingPanel.IsVirtualizingWhenGrouping" Value="false"/>
                </MultiTrigger.Conditions>
                <Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
            </MultiTrigger>
        </Style.Triggers>
    </Style>

WPF进阶技巧和实战03-控件(5-列表、树、网格04)的更多相关文章

  1. WPF进阶技巧和实战03-控件(3-文本控件及列表控件)

    系列文章链接 WPF进阶技巧和实战01-小技巧 WPF进阶技巧和实战02-布局 WPF进阶技巧和实战03-控件(1-控件及内容控件) WPF进阶技巧和实战03-控件(2-特殊容器) WPF进阶技巧和实 ...

  2. WPF进阶技巧和实战03-控件(4-基于范围的控件及日期控件)

    系列文章链接 WPF进阶技巧和实战01-小技巧 WPF进阶技巧和实战02-布局 WPF进阶技巧和实战03-控件(1-控件及内容控件) WPF进阶技巧和实战03-控件(2-特殊容器) WPF进阶技巧和实 ...

  3. WPF进阶技巧和实战06-控件模板

    逻辑树和可视化树 System.Windows.LogicalTreeHelper System.Windows.Media.VisualTreeHelper 逻辑树类(LogicalTreeHelp ...

  4. WPF进阶技巧和实战07--自定义元素02

    在01节中,研究了如何开发自定义控件,下节开始考虑更特殊的选择:派生自定义面板以及构建自定义绘图 创建自定义面板 创建自定义面板是一种比较常见的自定义控件开发子集,面板可以驻留一个或多个子元素,并且实 ...

  5. WPF进阶技巧和实战09-事件(2-多点触控)

    多点触控输入 多点触控输入和传统的基于比的输入的区别是多点触控识别手势,用户可以移动多根手指以执行常见的操作,放大,旋转,拖动等. 多点触控的输入层次 WPF允许使用键盘和鼠标的高层次输入(例如单击和 ...

  6. WPF进阶技巧和实战03-控件(1-控件及内容控件)

    所有控件都继承自System.Windows.Controls.Control类,这个类添加一些基本结构: 设置控件内容对齐方式 (HorizontalContentAlignment,Vertica ...

  7. WPF进阶技巧和实战03-控件(5-列表、树、网格03)

    数据视图 数据视图是在后台工作的,用于协调绑定数据的集合.使用数据视图可以添加导航逻辑.实现数据过滤.排序.分组. 当将集合或者DataTable绑定到ItemsControl控件时,会不加通告地在后 ...

  8. WPF进阶技巧和实战03-控件(5-列表、树、网格02)

    数据模板 样式提供了基本的格式化能力,但是不管如何修改ListBoxItem,他都不能够展示功能更强大的元素组合,因为了每个ListBoxItem只支持单个绑定字段(通过DisplayMemberPa ...

  9. WPF进阶技巧和实战03-控件(5-列表、树、网格01)

    列表控件 ItemsControl为列表项控件定义了基本功能,下图是ItemsControl的继承关系: 在继承自ItemsControl类的层次结构中,还显示了项封装器(MenuItem.TreeV ...

  10. WPF进阶技巧和实战08-依赖属性与绑定03

    数据提供者 在大多数的代码中,都是通过设置元素的DataContext属性或者列表控件的ItemsSource属性,从而提供顶级的数据源.当数据对象是通过另一个类构造时,可以有其他选择. 一种是作为窗 ...

随机推荐

  1. tcp为什么要三次握手,tcp为什么可靠

    转自 : https://www.cnblogs.com/LUO77/p/5771237.html大体看过,没有深入研究,有需要时继续看. 为什么不能两次握手:(防止已失效的连接请求又传送到服务器端, ...

  2. spring学习日志二

    一.spring依赖注入的方式 1.通过set方法来完成注入 <bean id="student" class="com.zhiyou100.xz.spring.S ...

  3. new和delete关键字

    new关键字创建出来的对象位于什么地方?很明显嘛,new关键字创建出来的对象一定位于堆空间,这种说法一定正确吗?本篇博客帮你揭开其神秘的面纱. 被忽略的事实new/delete的本质是C++预定义的操 ...

  4. Java Web基础 --- Servlet 综述(理论篇)

    摘要: Web 技术成为当今主流的互联网 Web 应用技术之一,而 Servlet 是 Java Web 技术的核心基础.本文首先从请求/响应架构应用的大背景谈起 Servlet 的由来,明确 Ser ...

  5. springboot使用redis(从配置到实战)

    概述 springboot通常整合redis,采用的是RedisTemplate的形式,除了这种形式以外,还有另外一种形式去整合,即采用spring支持的注解进行访问缓存. 准备工作 pom.xml ...

  6. JAVAWEB开发批量删除,SSM的几种情况

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  7. MMM双主-双从读写分离部署

    原文转自:https://www.cnblogs.com/itzgr/p/10233932.html作者:木二 目录 一 前期规划 1.1 主机规划 1.2 虚拟IP规划 1.3 用户列表 1.4 整 ...

  8. Qt之文件操作

    虽然文件操作是一项很常用的功能,但是总记不住,今天就干脆记了一下笔记,以后好查阅. 在Qt中,主要使用的是QFile类进行文件操作,因此要包括#include <QFile>头文件.下面就 ...

  9. pip 源的问题

    pip install -i https://pypi.doubanio.com/simple/ --trusted-host pypi.douban.com some-package

  10. 20210808 Hunter,Defence,Connect

    考场 乍一看都不可做 T1 算了半天样例,一直算出来 \(\frac{81}{400}\),直接丢了 T1 推了推发现是求最长连续 \(0\) 的数量,那就是线段树合并加上<玫瑰花精> T ...