为DataGrid列提供不同的色调

时间:2015-08-01 19:15:55

标签: c# wpf mvvm datagrid

我有一个WPF DataGrid,我想要一些列有不同的颜色。

<DataGrid>
   <DataGrid.Columns>
      <DataGridTextColumn Header="Name" Binding="{Binding Name}" />

      <DataGridTemplateColumn Header="Weight">
         <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
               <TextBlock Text="{Binding Path=Weight}" />
            </DataTemplate>
         </DataGridTemplateColumn.CellTemplate>
         <DataGridTemplateColumn.CellEditingTemplate>
            <DataTemplate>
               <TextBox Text="{Binding Path=Weight}" />
            </DataTemplate>
         </DataGridTemplateColumn.CellEditingTemplate>
      </DataGridTemplateColumn>

      <DataGridTextColumn Header="Created At" Binding="{Binding CreatedAt}" />
   </DataGrid.Columns>
</DataGrid>

我发现有关硬背景的帖子,但我希望更顺畅。它应该适合鼠标悬停和选择动作以及相应的颜色,但颜色不同。

我想为“默认”列,重要列和“只读”列提供视觉效果。

datagrid example

像上面这样的东西。不同颜色的列,但如果选择行,仍会稍微改变颜色。 但是如何?

3 个答案:

答案 0 :(得分:6)

一种解决方案是在自动生成列时设置正确的CellStyle。 在下面的Xaml中,我提供了一种默认状态DataGridCell的样式,它响应鼠标悬停,焦点,选择等。其他状态(例如只读,扩展, ...)可以通过颜色的一些微小变化来设计相同的样式。

<Window.Resources>
    <Style x:Key='CellDefaultStyle' TargetType="{x:Type DataGridCell}" >
        <Setter Property="Foreground" Value="Black" />
        <Setter Property="Background" Value="Transparent" />
        <Setter Property="HorizontalContentAlignment" Value="Stretch" />
        <Setter Property="VerticalContentAlignment" Value="Stretch" />
        <Setter Property="Cursor" Value="Arrow" />
        <Setter Property="IsTabStop" Value="False" />
        <Setter Property="Padding" Value="2 5 2 5" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type DataGridCell}">
                    <Grid x:Name="Root" Background="{TemplateBinding Background}">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*" />
                            <ColumnDefinition Width="Auto" />
                        </Grid.ColumnDefinitions>
                        <Rectangle x:Name="RightGridLine" VerticalAlignment="Stretch" 
                                   Width="1" Grid.Column="1" />
                        <Rectangle HorizontalAlignment="Stretch" x:Name="FocusVisual" 
                                   VerticalAlignment="Stretch" IsHitTestVisible="false" 
                                   Opacity="0" Fill="Green" Stroke="DarkGreen" 
                                   StrokeThickness="1" Grid.Column="0" />
                        <Rectangle x:Name="BackgroundRectangle" Grid.Column="0" 
                                   Fill="LightSteelBlue" Opacity="0.25" />
                        <Rectangle x:Name="SelectedRectangle" Opacity="0" 
                                   Fill="Blue" Grid.Column="0"  />
                        <Rectangle x:Name="HoverRectangle" 
                                   Fill="LightBlue" Opacity="0" Grid.Column="0"  />
                        <ContentPresenter Grid.Column="0" Margin="{TemplateBinding Padding}" 
                                          HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
                                          VerticalAlignment="{TemplateBinding VerticalContentAlignment}" 
                                          Content="{TemplateBinding Content}" 
                                          ContentTemplate="{TemplateBinding ContentTemplate}" 
                                          Cursor="{TemplateBinding Cursor}"/>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsSelected" Value="True">
                            <Setter Property='Opacity' TargetName='FocusVisual' Value='0.8' />
                        </Trigger>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Trigger.EnterActions>
                                <BeginStoryboard>
                                    <Storyboard>
                                        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" 
                                                                       Storyboard.TargetName="HoverRectangle" 
                                                                       Storyboard.TargetProperty="(UIElement.Opacity)">
                                            <SplineDoubleKeyFrame KeyTime="00:00:00" Value="1" />
                                        </DoubleAnimationUsingKeyFrames>
                                    </Storyboard>
                                </BeginStoryboard>
                            </Trigger.EnterActions>
                            <Trigger.ExitActions>
                                <BeginStoryboard>
                                    <Storyboard>
                                        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" 
                                                                       Storyboard.TargetName="HoverRectangle" 
                                                                       Storyboard.TargetProperty="(UIElement.Opacity)">
                                            <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0" />
                                        </DoubleAnimationUsingKeyFrames>
                                    </Storyboard>
                                </BeginStoryboard>
                            </Trigger.ExitActions>
                        </Trigger>
                        <Trigger Property="IsSelected" Value="True">
                            <Trigger.EnterActions>
                                <BeginStoryboard>
                                    <Storyboard>
                                        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="SelectedRectangle" Storyboard.TargetProperty="(UIElement.Opacity)">
                                            <SplineDoubleKeyFrame KeyTime="00:00:00" Value="1" />
                                        </DoubleAnimationUsingKeyFrames>
                                    </Storyboard>
                                </BeginStoryboard>
                            </Trigger.EnterActions>
                            <Trigger.ExitActions>
                                <BeginStoryboard>
                                    <Storyboard>
                                        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="SelectedRectangle" Storyboard.TargetProperty="(UIElement.Opacity)">
                                            <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0" />
                                        </DoubleAnimationUsingKeyFrames>
                                    </Storyboard>
                                </BeginStoryboard>
                            </Trigger.ExitActions>
                        </Trigger>
                        <MultiTrigger >
                            <MultiTrigger.Conditions>
                                <Condition Property="IsMouseOver" Value="True" />
                                <Condition Property="IsSelected" Value="True" />
                            </MultiTrigger.Conditions>
                            <MultiTrigger.EnterActions>
                                <BeginStoryboard>
                                    <Storyboard>
                                        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="HoverRectangle" Storyboard.TargetProperty="(UIElement.Opacity)">
                                            <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0.5" />
                                        </DoubleAnimationUsingKeyFrames>
                                        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="SelectedRectangle" Storyboard.TargetProperty="(UIElement.Opacity)">
                                            <SplineDoubleKeyFrame KeyTime="00:00:00" Value="1" />
                                        </DoubleAnimationUsingKeyFrames>
                                    </Storyboard>
                                </BeginStoryboard>
                            </MultiTrigger.EnterActions>
                            <MultiTrigger.ExitActions>
                                <BeginStoryboard>
                                    <Storyboard>
                                        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="HoverRectangle" Storyboard.TargetProperty="(UIElement.Opacity)">
                                            <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0" />
                                        </DoubleAnimationUsingKeyFrames>
                                        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="SelectedRectangle" Storyboard.TargetProperty="(UIElement.Opacity)">
                                            <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0" />
                                        </DoubleAnimationUsingKeyFrames>
                                    </Storyboard>
                                </BeginStoryboard>
                            </MultiTrigger.ExitActions>
                        </MultiTrigger>
                        <MultiTrigger >
                            <MultiTrigger.Conditions>
                                <Condition Property="IsMouseOver" Value="True" />
                                <Condition Property="IsSelected" Value="False" />
                            </MultiTrigger.Conditions>
                            <MultiTrigger.EnterActions>
                                <BeginStoryboard>
                                    <Storyboard>
                                        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="HoverRectangle" Storyboard.TargetProperty="(UIElement.Opacity)">
                                            <SplineDoubleKeyFrame KeyTime="00:00:00" Value="1" />
                                        </DoubleAnimationUsingKeyFrames>
                                        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="SelectedRectangle" Storyboard.TargetProperty="(UIElement.Opacity)">
                                            <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0" />
                                        </DoubleAnimationUsingKeyFrames>
                                    </Storyboard>
                                </BeginStoryboard>
                            </MultiTrigger.EnterActions>
                            <MultiTrigger.ExitActions>
                                <BeginStoryboard>
                                    <Storyboard>
                                        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="HoverRectangle" Storyboard.TargetProperty="(UIElement.Opacity)">
                                            <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0" />
                                        </DoubleAnimationUsingKeyFrames>
                                        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="SelectedRectangle" Storyboard.TargetProperty="(UIElement.Opacity)">
                                            <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0" />
                                        </DoubleAnimationUsingKeyFrames>
                                    </Storyboard>
                                </BeginStoryboard>
                            </MultiTrigger.ExitActions>
                        </MultiTrigger>
                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="IsSelected" Value="True" />
                                <Condition Property="IsFocused" Value="False" />
                            </MultiTrigger.Conditions>
                            <MultiTrigger.EnterActions>
                                <BeginStoryboard>
                                    <Storyboard>
                                        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="SelectedRectangle" Storyboard.TargetProperty="(UIElement.Opacity)">
                                            <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0.6" />
                                        </DoubleAnimationUsingKeyFrames>
                                    </Storyboard>
                                </BeginStoryboard>
                            </MultiTrigger.EnterActions>
                            <MultiTrigger.ExitActions>
                                <BeginStoryboard>
                                    <Storyboard>
                                        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="SelectedRectangle" Storyboard.TargetProperty="(UIElement.Opacity)">
                                            <SplineDoubleKeyFrame KeyTime="00:00:00" Value="0" />
                                        </DoubleAnimationUsingKeyFrames>
                                    </Storyboard>
                                </BeginStoryboard>
                            </MultiTrigger.ExitActions>
                        </MultiTrigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
        <Setter Property="IsSelected" Value="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGridRow}, 
            Path=IsSelected, Mode=OneWayToSource, UpdateSourceTrigger=PropertyChanged}" />
    </Style>
    <Style x:Key='CellReadOnlyStyle' TargetType="{x:Type DataGridCell}" >
         <based on CellDefaultStyle with some minor change in colors ...>
    </Style>
</Window.Resources>

这是具有自动列生成功能的DataGrid的示例。

<Window>
    <Grid>
        <DataGrid ItemsSource="{Binding MyItems}" 
                  AutoGeneratingColumn="DataGrid_AutoGeneratingColumn"/>
    </Grid>
</Window>

这就是在生成列时为不同状态选择样式的方式:

    private void DataGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
    {
        if (e.Column.IsReadOnly)
        {
            e.Column.CellStyle = (Style)Resources["CellReadOnlyStyle"];
        }
        else if (other states)
        {
            e.Column.CellStyle = (Style)Resources["CellOtherStyle"];
        }
        else
        {
            e.Column.CellStyle = (Style)Resources["CellDefaultStyle"];
        }
    }

<强>更新

如果AutoGeneratingColumns设置为False,由于DataGridTemplateColumnDataGridBoundColumn(例如DataGridTextColumn)都具有CellStyle属性,您可以手动为每列设置适当的样式:

    <DataGrid ItemsSource="{Binding ViewModel.MyList}" 
              AutoGenerateColumns="False">
        <DataGrid.Columns>
            <DataGridTextColumn Header="Name" Binding="{Binding Name}" CellStyle="{StaticResource CellDefaultStyle}" />
            <DataGridTemplateColumn Header="Weight" 
                                    CellStyle="{StaticResource CellDefaultStyle}">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Path=Weight}" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
                <DataGridTemplateColumn.CellEditingTemplate>
                    <DataTemplate>
                        <TextBox Text="{Binding Path=Weight}" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellEditingTemplate>
            </DataGridTemplateColumn>
            <DataGridTextColumn Header="Created At" Binding="{Binding CreatedAt}" CellStyle="{StaticResource CellReadOnlyStyle}"/>
        </DataGrid.Columns>
    </DataGrid>

此屏幕截图显示样式完成后列的外观。

enter image description here

答案 1 :(得分:4)

对于Selected,ReadOnly和MouseOver,它看起来像这样

<Style x:Key='CustomCellStyle' TargetType="{x:Type DataGridCell}" >
        <Style.Triggers>
            <MultiTrigger >
                <MultiTrigger.Conditions>
                    <Condition Property="IsMouseOver" Value="True" />
                    <Condition Property="IsSelected" Value="False" />
                    <Condition Property="IsReadOnly" Value="False" />
                </MultiTrigger.Conditions>
                <Setter Property="Background" Value="Blue" />
            </MultiTrigger>
            <MultiTrigger >
                <MultiTrigger.Conditions>
                    <Condition Property="IsMouseOver" Value="True" />
                    <Condition Property="IsSelected" Value="False" />
                    <Condition Property="IsReadOnly" Value="True" />
                </MultiTrigger.Conditions>
                <Setter Property="Background" Value="LightBlue" />
            </MultiTrigger>
            <MultiTrigger >
                <MultiTrigger.Conditions>
                    <Condition Property="IsMouseOver" Value="True" />
                    <Condition Property="IsSelected" Value="True" />
                    <Condition Property="IsReadOnly" Value="True" />
                </MultiTrigger.Conditions>
                <Setter Property="Background" Value="LightGray" />
            </MultiTrigger>
            <MultiTrigger >
                <MultiTrigger.Conditions>
                    <Condition Property="IsMouseOver" Value="False" />
                    <Condition Property="IsSelected" Value="False" />
                    <Condition Property="IsReadOnly" Value="True" />
                </MultiTrigger.Conditions>
                <Setter Property="Background" Value="Gray" />
            </MultiTrigger>
            <MultiTrigger >
                <MultiTrigger.Conditions>
                    <Condition Property="IsMouseOver" Value="False" />
                    <Condition Property="IsSelected" Value="True" />
                    <Condition Property="IsReadOnly" Value="True" />
                </MultiTrigger.Conditions>
                <Setter Property="Background" Value="Red" />
            </MultiTrigger>
        </Style.Triggers>
    </Style>

我无法在Bahman_Aries的帖子上发表评论,所以我在这里发布: 我不明白为什么他的解决方案不适合你。如果您有AutoGenerateColumns =“False”,它会使解决方案更容易,因为您可以手动为每列设置样式。

<DataGridTextColumn Header="Data 1" Binding="{Binding Data1}" IsReadOnly="True" CellStyle="{StaticResource CellReadOnlyStyle}"/>

答案 2 :(得分:4)

您的示例简短而简单

    <Window x:Class="WpfApplication1.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525" Loaded="Window1_Load">
        <Window.Resources>
            <SolidColorBrush x:Key="clBl" Color="Blue" />
            <SolidColorBrush x:Key="clred" Color="Red" />
            <SolidColorBrush x:Key="clgreen" Color="Green" />
        </Window.Resources>
        <Grid>
            <DataGrid Name="grd" AutoGenerateColumns="False" ItemsSource="{Binding}">
                <DataGrid.Columns>
                    <DataGridTextColumn Header="Name" Binding="{Binding Name}" >
                        <DataGridTextColumn.CellStyle>
                            <Style TargetType="DataGridCell">
                                <Setter Property="Background" 
                                    Value="{StaticResource clred}" />
                            </Style>
                        </DataGridTextColumn.CellStyle>
                    </DataGridTextColumn>
                    <DataGridTemplateColumn Header="Weight">
                        <DataGridTemplateColumn.CellTemplate>
                            <DataTemplate>
                                <TextBlock Text="{Binding Path=Weight}" />
                            </DataTemplate>

                        </DataGridTemplateColumn.CellTemplate>

                        <DataGridTemplateColumn.CellEditingTemplate>
                            <DataTemplate>
                                <TextBox Text="{Binding Path=Weight}" />
                            </DataTemplate>
                        </DataGridTemplateColumn.CellEditingTemplate>
                        <DataGridTemplateColumn.CellStyle>
                            <Style TargetType="DataGridCell">
                                <Setter Property="Background" 
                                    Value="{StaticResource clBl}" />
                            </Style>
                        </DataGridTemplateColumn.CellStyle>
                    </DataGridTemplateColumn>

                    <DataGridTextColumn Header="Created At" Binding="{Binding CreatedAt}" >
                        <DataGridTextColumn.CellStyle>
                            <Style TargetType="DataGridCell">
                                <Setter Property="Background" 
                                    Value="{StaticResource clgreen}" />
                            </Style>
                        </DataGridTextColumn.CellStyle>
                        </DataGridTextColumn>
                </DataGrid.Columns>
            </DataGrid>
        </Grid>
    </Window>

你也可以用同样的方式使用HeaderStyle和FooterStyle

鼠标悬停和鼠标离开

适当使用

<DataGrid.RowStyle>
    <Style TargetType="DataGridRow">
         <Style.Triggers>
              <Trigger Property="IsMouseOver"
                       Value="True">
                   <Setter Property="Background"
                           Value="Green" />
              </Trigger>
         </Style.Triggers>
    </Style>
</DataGrid.RowStyle>

 <DataGrid.CellStyle>
    <Style TargetType="DataGridCell">
        <Style.Triggers>
            <Trigger Property="IsMouseOver"
                     Value="True">
                <Setter Property="Background"
                        Value="Pink" />
            </Trigger>
         </Style.Triggers>
    </Style>
</DataGrid.CellStyle>