正确地样式化DataGridCell



这是我上一个问题之后的问题,你可以在这里找到它

。现在我定义了一个DataGrid,每一列都有一个特定的ElementStyle(它只是定义了里面的TextBlock s,用粗体&白色——稍后会解决这个问题)

现在我有两个问题

第一个问题(解决)

当我碰巧为单元格设置背景时,它会覆盖默认样式,并且当单元格高亮显示时背景保持不变。

样式的一个例子:

<!-- 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,但没有成功

** EDIT: Solution**

正如H B在他的回答中所建议的,问题来自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>

第二个问题

现在,让我们来谈谈Triggers

基本上,我想做的是定义特定的Triggers到我的ElementStyle,所以字体颜色是白色的,如果单元格的背景是红色或绿色(这样做的唯一目的是有一个更好的可读性,红色和绿色有点暗,黑色字体在黑暗的背景导致一个很好的失败:p)

Edit似乎我不够清楚:以下样式是通过属性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社区能拯救我:)

谢谢!

编辑

好的,更新。我明白为什么我的Trigger不工作。背景实际上是在Grid上而不是在DataGridCell上设置的。因此,我没有在那里设置任何颜色是正常的。

然而,我运行了一些测试,发现当绑定设置时,TextBlock还没有任何父(Parent = null)。绑定到Grid类型的RelativeSource将绑定到…整个DataGrid项目展示。我不知道现在该怎么办,因为从实际的TextBlock样式来看,我无法到达父Grid,因此无法解决我应该根据背景显示什么颜色。此外,我不能改变我的ControlTemplate的字体颜色,因为DataGrid想要一个Style的每一列,这覆盖了模板的默认样式(参见我之前的问题和它的答案)所以…我又卡住了!

依赖属性值优先级

:

<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。获得Transparent作为值不是很有帮助,您为DataGridCell使用什么控制模板?如果是自定义的,Background是否通过TemplateBinding正确连接?

只要使用Background属性就可以工作,所以如果你有一个ControlTemplate在内部设置东西,你需要外部化它。正常DataGrid示例:

<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连接。例如

<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>

不要在模板内触发,否则会很乱。

最新更新