正确设置DataGridCell样式 [英] Styling DataGridCell correctly
问题描述
这是我之前遇到的问题,你可以在那里找到它
This is a question following my previous problem, you can find it right there
所以。现在我为每个列定义了一个 DataGrid
,其中包含一个特定的 ElementStyle
(只需定义 TextBlock
So. Now I defined a DataGrid
with a specific ElementStyle
for each column (which just defines the TextBlock
s inside in bold & white -- will come over this problem later)
所以现在我有两个问题
第一个问题(已解决)
当我碰巧为我的单元格设置背景时,它会覆盖
When I happen to set a background to my cell, it overrides the default style, and the background stays the same when the cell is highlighted.
风格的一个例子:
<!-- Green template for market-related -->
<ControlTemplate x:Key="Green" TargetType="{x:Type tk:DataGridCell}">
<Grid Background="Green">
<ContentPresenter
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Grid>
</ControlTemplate>
我自然会说这是正常,因为我设置网格
的背景为绿色。因此,我以这种方式尝试:
I'd naturally say that this is "normal" because I set the Grid
's background to Green. I therefore tried it this way:
<!-- Light green template for sophis-related -->
<ControlTemplate x:Key="LightGreen" TargetType="{x:Type tk:DataGridCell}">
<Grid Background="LightGreen">
<Grid.Resources>
<Style TargetType="{x:Type Grid}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type tk:DataGridCell}},
Converter={StaticResource DebugConverter}}" Value="True">
<Setter Property="Grid.Background" Value="#FF3774FF" />
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Resources>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
</ControlTemplate>
这也不行。正如你可以看到的,我放了一个DebugConverter,所以我可以检查触发器是否被实际调用,情况就是这样,但是...背景不会改变(Snoop确认这个...)
This won't work either. As you can see I put a DebugConverter so I can check that the trigger is actually called, which is the case, but... Background does not change (and Snoop confirms this...)
第三次尝试:
<!-- Light green template for sophis-related -->
<ControlTemplate x:Key="LightGreen" TargetType="{x:Type tk:DataGridCell}">
<ControlTemplate.Resources>
<Style TargetType="{x:Type tk:DataGridCell}">
<Setter Property="Background" Value="LightGreen" />
</Style>
</ControlTemplate.Resources>
<Grid>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
</ControlTemplate>
而且不会显示背景(保持透明)
And... No background will be displayed (stays transparent)
所以我想我在这里工作的错误,我想知道我该怎么做,以定义未选择的模板。
我会说,我可能需要定义一个风格基于经典风格,但是我该怎么做?我试图添加TemplateBindings没有成功
So I think I am working in the wrong way here and I was wondering what should I do to JUST define the "not selected" template. I would say that I may need to define a style BasedOn the "classic" style but, how would I do that? I tried to add TemplateBindings with no success
**编辑:解决方案**
** Solution**
正如HB在他的答案是问题来自DependencyProperty优先级,这里是解决方案:
As H B suggested in his answer, problem was coming from DependencyProperty Precedence, here's the solution:
<!-- Light green template for sophis-related -->
<ControlTemplate x:Key="LightGreen" TargetType="{x:Type tk:DataGridCell}">
<Grid>
<Grid.Resources>
<Style TargetType="{x:Type Grid}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type tk:DataGridCell}},
Converter={StaticResource DebugConverter}}" Value="True">
<Setter Property="Grid.Background" Value="#FF316AC5" />
</DataTrigger>
<DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type tk:DataGridCell}},
Converter={StaticResource DebugConverter}}" Value="False">
<Setter Property="Grid.Background" Value="LightGreen" />
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Resources>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
</ControlTemplate>
第二个问题
现在,我们来说触发器
。
基本上,我想做的是定义具体的触发器
到我的 ElementStyle
,所以如果单元格的背景是红色或绿色,字体颜色是白色的(这是唯一的目的是有一个更好的可读性,因为红色和绿色是黑暗的黑色背景下的黑色字体导致一个很好的失败:p)
Basically, what I want to do is to define specific Triggers
to my ElementStyle
so the font color is white if the cell's background is Red or Green (the only aim of this is to have a better readability as Red and Green are kinda dark, black font on dark background results in a nice fail :p )
编辑似乎我不够清楚:以下风格是通过属性 DataGridTextColumn.ElementStyle
应用于datagrid的每个项目的样式。以下是代码处理:
Edit Seems like I'm not clear enough: the following style is the style applied to each item of the datagrid, through the property DataGridTextColumn.ElementStyle
. Here is the code handling that:
void VolatilityDataGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
DataGridTextColumn column = e.Column as DataGridTextColumn;
column.ElementStyle = s_boldCellStyle;
// Other stuff here...
}
这是我的do:
<!-- Cell style for colored matrix-->
<Style x:Key="BoldCellStyle" TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding Background, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type tk:DataGridCell}}}"
Value="Red">
<Setter Property="Foreground" Value="White" />
</DataTrigger>
<DataTrigger Binding="{Binding Background, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type tk:DataGridCell}},
Converter={StaticResource DebugConverter}}"
Value="Green">
<Setter Property="Foreground" Value="White" />
</DataTrigger>
</Style.Triggers>
<Setter Property="FontWeight" Value="Bold"/>
</Style>
而...它不工作。奇怪的是,通过转换器只有透明的背景颜色。我绝对错过了这里!
BTW,我也尝试过经典的触发器,也没有成功,我使用 DataTriggers
在这里,所以我可以调试绑定值!
And... It doesn't work. Strangely, what goes through converter is ONLY transparent background colors. I am definitely missing something here!
BTW, I also tried with classic triggers, no success either, I use DataTriggers
here so I can debug the binding values!
现在我已经停了三天以上,我开始出事了...希望Stackoverflow社区会救我:)
Now I've been stuck for more than three days on this and I'm starting to freak out... Hopefully the Stackoverflow community will save me :)
谢谢!
修改
我明白为什么我的触发器
不起作用。背景实际设置在 Grid
而不是 DataGridCell
上。因此,我没有任何颜色设置是正常的。
Okay, update.
I understood why my Trigger
does not work. The Background actually set is on the Grid
and NOT on the DataGridCell
. It is therefore normal that I don't get any color set there.
但是,我运行了一些测试,发现当绑定设置时, TextBlock
没有任何父项( Parent
= null)。绑定到 RelativeSource
类型 Grid
将绑定到...整个 DataGrid
项目主持人。
我不知道该怎么做,因为它似乎是从实际的 TextBlock
样式我无法达到父网格
,因此无法根据背景来解析我应该显示的颜色。
此外,我不能更改我的 ControlTemplate
中的字体颜色,因为 DataGrid
需要$每个列的c $ c> Style 默认情况下覆盖模板的样式(见我以前的问题及其答案)
所以...再次被卡住我是!
However, I ran some tests and found out that when the binding is set, the TextBlock
does not have any parent yet (Parent
= null). Binding to a RelativeSource
of type Grid
will bind me to... The whole DataGrid
items presenter.
I'm not sure what to do now, since it seems like that from the actual TextBlock
style I can't reach the parent Grid
and therefore cannot resolve what color should I display according to the background.
Also, I can't change the Font color in my ControlTemplate
because the DataGrid
wants a Style
for each column, which overrides the template's style by default (see my previous question and its answer)
So... Stuck again I am!
推荐答案
这是:
<Grid Background="LightGreen">
<Grid.Resources>
<Style TargetType="{x:Type Grid}">
<!-- Trigger Stuff -->
</Style>
</Grid.Resources>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
需要:
<Grid>
<Grid.Resources>
<Style TargetType="{x:Type Grid}">
<Setter Property="Background" Value="LightGreen"/>
<!-- Trigger Stuff -->
</Style>
</Grid.Resources>
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
不知道现在的第二个问题,可能是一个相关的问题,我建议为初学者设置 TextElement.Foreground
而不是 Foreground
。获取透明度
,因为值不是很有帮助,您在 DataGridCell
中使用什么控件模板?如果是自定义的,背景
是否通过 TemplateBinding
正确连接?
Not sure about your second question as of now, possibly a related problem, i would suggest setting TextElement.Foreground
instead of Foreground
for starters. Getting Transparent
as value is not very helpful, what control template do you use for the DataGridCell
? If it is custom, is the Background
hooked up properly via a TemplateBinding
?
只要使用 Background
属性,这样就可以使用,所以如果你有一个 ControlTemplate
设置内部需要外部化的东西。一般的 DataGrid
示例:
This works as long as the Background
property is used, so if you have a ControlTemplate
which sets things internally you need to externalize that. A normal DataGrid
example:
<DataGrid.CellStyle>
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="Background" Value="LightGreen"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Content}" Value="Apple">
<Setter Property="Background" Value="Red"/>
</DataTrigger>
<DataTrigger Binding="{Binding Content}" Value="Tomato">
<Setter Property="Background" Value="Green"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.CellStyle>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding Background, RelativeSource={RelativeSource AncestorType={x:Type DataGridCell}}}" Value="Red">
<Setter Property="Foreground" Value="White"/>
</DataTrigger>
<DataTrigger Binding="{Binding Background, RelativeSource={RelativeSource AncestorType={x:Type DataGridCell}}}" Value="Green">
<Setter Property="Foreground" Value="White"/>
</DataTrigger>
</Style.Triggers>
<Setter Property="FontWeight" Value="Bold"/>
</Style>
所以如果 CellStyle
设置 ControlTemplate
属性需要通过TemplateBinding挂接。例如
So if the CellStyle
sets the ControlTemplate
the properties need to be hooked up via TemplateBinding. e.g.
<DataGrid.CellStyle>
<Style TargetType="{x:Type DataGridCell}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridCell}">
<Grid Background="{TemplateBinding Background}">
<ContentPresenter />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Background" Value="LightGreen"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Content}" Value="Apple">
<Setter Property="Background" Value="Red"/>
</DataTrigger>
<DataTrigger Binding="{Binding Content}" Value="Tomato">
<Setter Property="Background" Value="Green"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.CellStyle>
不要在模板中进行触发,否则会变得混乱。
Do not do the triggering inside the template or it will get messy.
这篇关于正确设置DataGridCell样式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!