我有一个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>
我发现有关硬背景的帖子,但我希望更顺畅。它应该适合鼠标悬停和选择动作以及相应的颜色,但颜色不同。
我想为“默认”列,重要列和“只读”列提供视觉效果。
像上面这样的东西。不同颜色的列,但如果选择行,仍会稍微改变颜色。 但是如何?
答案 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
,由于DataGridTemplateColumn
和DataGridBoundColumn
(例如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>
此屏幕截图显示样式完成后列的外观。
答案 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>