正确设置DataGridCell样式 [英] Styling DataGridCell correctly

查看:181
本文介绍了正确设置DataGridCell样式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我之前遇到的问题,你可以在那里找到它

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 TextBlocks 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆