正确设置 DataGridCell 样式
这是继我之前的问题之后的一个问题,你可以在那里找到它
那么。现在,我为每列定义了一个具有特定 ElementStyle
的 DataGrid
(它只是以粗体和白色定义了内部的 TextBlock
- 将会出现)稍后解决这个问题)
所以现在我有两个问题
第一个问题(已解决)
当我碰巧为单元格设置背景时,它会覆盖默认样式,并且当单元格被设置时背景保持不变突出显示。
一种样式的示例:
<!-- Green template for market-related -->
<ControlTemplate x:Key="Green" TargetType="{x:Type tk:DataGridCell}">
<Grid Background="Green">
<ContentPresenter
HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Grid>
</ControlTemplate>
我自然会说这是“正常”,因为我将Grid
的背景设置为绿色。因此我尝试了这样的方法:
<!-- 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 确认了这一点......)
第三次尝试:
<!-- 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>
并且......没有背景将显示(保持透明)
所以我认为我在这里以错误的方式工作,我想知道我应该做什么来定义“未选择”模板。 我想说我可能需要定义一个基于“经典”样式的样式,但是,我该怎么做呢?我尝试添加 TemplateBindings 但没有成功
** 编辑:解决方案**
正如 HB 在他的回答中建议的那样,问题来自 DependencyProperty Precedence,这是解决方案:
<!-- 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
定义特定的 Triggers
,因此如果单元格的背景是红色或绿色,则字体颜色为白色(这样做的唯一目的是为了具有更好的可读性,因为红色和绿色有点暗,深色背景上的黑色字体会导致很好的失败:p)
编辑似乎我还不够清楚:以下样式是应用的样式通过属性到数据网格的每个项目DataGridTextColumn.ElementStyle
。这是处理该问题的代码:
void VolatilityDataGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
DataGridTextColumn column = e.Column as DataGridTextColumn;
column.ElementStyle = s_boldCellStyle;
// Other stuff here...
}
这是我所做的:
<!-- 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>
而且...它不起作用。奇怪的是,通过转换器的只是透明的背景颜色。我肯定在这里遗漏了一些东西! 顺便说一句,我也尝试过经典触发器,但也没有成功,我在这里使用 DataTriggers 这样我就可以调试绑定值!
现在我已经在这个问题上被困了三天多了,我开始害怕了......希望 Stackoverflow 社区能够拯救我:)
谢谢!
编辑
好的,更新。 我明白为什么我的触发器
不起作用。实际设置的背景位于 Grid
上,而不是位于 DataGridCell
上。因此,我在那里没有设置任何颜色是正常的。
但是,我运行了一些测试,发现设置绑定后,TextBlock
还没有任何父级 (Parent
= null)。绑定到 Grid
类型的 RelativeSource
会将我绑定到...整个 DataGrid
项目呈现器。 我不知道现在该怎么办,因为从实际的 TextBlock
样式来看,我无法到达父 Grid
,因此无法解析我应该使用什么颜色根据背景显示。 另外,我无法更改 ControlTemplate
中的字体颜色,因为 DataGrid
需要每个列都有一个 Style
,这会通过以下方式覆盖模板的样式默认(请参阅我之前的问题及其答案) 所以...我又被困住了!
This is a question following my previous problem, you can find it right there
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)
So now I have two questions
First question (solved)
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.
One example of a style:
<!-- 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>
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...)
Third try:
<!-- 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)
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
** EDIT: Solution**
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>
Second question
Now, let's speak Triggers
.
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 )
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...
}
Here is what I 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>
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!
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 :)
Thanks!
Edit
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.
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!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
依赖属性值优先级
:
需要是:
目前不确定你的第二个问题,可能是一个相关的问题,我建议初学者设置
TextElement.Foreground
而不是Foreground
。将Transparent
作为值并不是很有帮助,您为DataGridCell
使用什么控件模板?如果是自定义的,Background
是否通过TemplateBinding
正确连接?只要使用
Background
属性,此功能就有效,因此,如果您有一个在内部设置内容的ControlTemplate
,则需要将其外部化。一个普通的 DataGrid 示例:因此,如果
CellStyle
设置ControlTemplate
,则需要通过 TemplateBinding 连接属性。例如,不要在模板内进行触发,否则会变得混乱。
Dependency Property Value Precedence
This:
Needs to be:
Not sure about your second question as of now, possibly a related problem, i would suggest setting
TextElement.Foreground
instead ofForeground
for starters. GettingTransparent
as value is not very helpful, what control template do you use for theDataGridCell
? If it is custom, is theBackground
hooked up properly via aTemplateBinding
?This works as long as the
Background
property is used, so if you have aControlTemplate
which sets things internally you need to externalize that. A normalDataGrid
example:So if the
CellStyle
sets theControlTemplate
the properties need to be hooked up via TemplateBinding. e.g.Do not do the triggering inside the template or it will get messy.