正确设置DataGridCell的样式

时间:2011-08-18 11:58:24

标签: wpf datagrid styles controltemplate

这是我之前的问题you can find it right there

之后的问题

因此。现在我为每列定义了一个DataGrid,其中包含一个特定的ElementStyle(其中只用粗体和白色定义了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但没有成功

**编辑:解决方案**

正如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)

编辑似乎我不够清楚:以下样式是通过属性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)。绑定到RelativeSource类型Grid会将我绑定到...整个DataGrid项目主持人。 我不知道现在该做什么,因为从实际的TextBlock样式来看,我似乎无法到达父Grid因此无法根据背景显示我应该显示的颜色。 另外,我无法更改ControlTemplate中的字体颜色,因为DataGrid想要每列Style,默认情况下会覆盖模板的样式(see my previous question and its answer) 所以...我再次被困!

1 个答案:

答案 0 :(得分:4)

Dependency Property Value Precedence

此:

<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连接属性。 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>

不要在模板内进行触发,否则会变得混乱。