简体   繁体   English

触发自动生成的DataGrid列

[英]Trigger for auto-generated DataGrid column

I currently work on a WPF project which handels data within an auto-generated data grid. 我目前在WPF项目中工作,该项目在自动生成的数据网格内处理数据。 How can I set up a trigger, for changing the background color of a column depending on an empty textbox? 如何设置触发器,以根据空的文本框更改列的背景颜色?

My current usercontrol XAML creates a grid which keeps and data grid inside. 我当前的usercontrol XAML创建了一个网格,其中保留了数据网格。 For each DataGridColumnHeader I set a new ContentTemplate, which keeps a TextBlock (for the actual header) and a TextBox for filtering. 我为每个DataGridColumnHeader设置了一个新的ContentTemplate,该模板保留一个TextBlock(用于实际的标题)和一个TextBox用于过滤。

I tried to set up a trigger for DataGridCell, which worked, but only changes the color of the cell. 我试图为DataGridCell设置一个触发器,该触发器可以工作,但只能更改单元格的颜色。 I can't find a specific target type for a data grid column. 我找不到数据网格列的特定目标类型。

<UserControl x:Class="...">
<Grid>
    <DataGrid AutoGenerateColums="True" IsReadOnly="True" x:Name="MyDataGrid">
        <DataGrid.Resources>
            <Style TargetType="x:Type DataGridColumnHeader=">
                <Setter Property="ContentTemplate">
                    <Setter.Value>
                        <DataTemplate>
                            <StackPanel>
                                <TextBlock x:Name="myBlock" Text="{Binding}" TextWrapping="Wrap" />
                                <TextBox x:Name="myBox" KeyUp="KeyUpEvent" />
                            </StackPanel>
                        </DataTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </DataGrid.Resources>
    </DataGrid>
</Grid>

I expect to change the color of a data grid column, if the TextBox is filled with content. 如果TextBox充满内容,我希望更改数据网格列的颜色。 Currently I do not know how to set a specific trigger for a data grid column, if the column are auto-generated. 当前,如果该列是自动生成的,我不知道如何为数据网格列设置特定的触发器。 EDIT #1: Something like that: 编辑#1:类似的东西:

在列名称下具有列,行和过滤器单元的DataGrid

This is when the data grid doesn't have any filters set. 这是当数据网格未设置任何过滤器时。 But the appearance changes, as soon as you enter a filter text inside one of the filters, like that: 但是外观会发生变化,只要您在其中一个过滤器中输入过滤器文本,如下所示:

在第二列中设置了一个过滤器的DataGrid

EDIT #2: 编辑#2:

I was able to build a solution for coloring the rows programmatically, without coloring the header. 我能够建立一种解决方案,以编程方式为行着色,而无需给标题着色。 That's missing. 没了 Do you have any suggestions? 你有什么建议吗?

See the following code: 请参见以下代码:

private void StyleRows(string text, string name)
{
    if(text != "" && column != "")
    {
        foreach(DataGridColumn column in DataGrid.Columns)
        {
            if(column.Header == column)
            {
                Style style = new Style(typeof(DataGridCell));
                style.Settes.Add(new Setter(DataGridCell.BackgroundProperty, System.Windows.Media.Brushes.Red));
                column.cellStyle = style
            }
        }
    }
}

Question: Is there a way to do that inside the XAML? 问题:是否可以在XAML中执行此操作?

Thank you for your help! 谢谢您的帮助!

There is no way to do it in XAML only . 仅在XAML中无法做到这一点

You could try to adjust a ViewModel to provide for each column whether the content of TextBox is empty or not(bind the TextBox.Text to the properties and provide bool properties to check string is null or empty). 您可以尝试调整ViewModel以为每一列提供TextBox的内容是否为空(将TextBox.Text绑定到属性,并提供bool属性以检查字符串为null还是为空)。 But it's also not a "XAML only" solution. 但这也不是“仅XAML”解决方案。

If yoy set the CellStyle you will need to observe the control from template and use trigger, but you have no access to it. 如果您设置了CellStyle ,则需要从模板观察控件并使用触发器,但是您无权访问它。

I would do it with a Behavior . 我会用Behavior来做。 Once you have written a Behavior you can easily use/reuse it in XAML only without need to touch/adjust a code behind. 编写Behavior ,只需在XAML中轻松使用/重用它,而无需触摸/调整后面的代码。

public class ObserveEmpty : Behavior<TextBox>
{
    public Control TargetControl
    {
        get { return (Control)GetValue(TargetControlProperty); }
        set { SetValue(TargetControlProperty, value); }
    }
    public static readonly DependencyProperty TargetControlProperty =
        DependencyProperty.Register(nameof(TargetControl), typeof(object), typeof(ObserveEmpty), new PropertyMetadata(null, TargetCtlChanged));

    private static void TargetCtlChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        (d as ObserveEmpty)?.SetTargetBackground();
    }
    public Brush TargetBgrndBrushOnEmpty { get; set; }
    public Brush TargetBgrndBrush { get; set; }


    protected override void OnAttached()
    {
        base.OnAttached();
        SetTargetBackground();
        AssociatedObject.TextChanged += AssociatedObject_TextChanged;
    }
    protected override void OnDetaching()
    {
        base.OnDetaching();
        AssociatedObject.TextChanged -= AssociatedObject_TextChanged;
    }
    private void AssociatedObject_TextChanged(object sender, TextChangedEventArgs e)
    {
        SetTargetBackground();
    }
    private void SetTargetBackground()
    {
        if (TargetControl != null)
        {
            var brush = string.IsNullOrEmpty(AssociatedObject?.Text) ? TargetBgrndBrushOnEmpty : TargetBgrndBrush;

            TargetControl.Background = brush;

            var dgrClmnHdr = TargetControl as DataGridColumnHeader;
            if (dgrClmnHdr?.Column != null)
            {
                Style style = new Style(typeof(DataGridCell));
                style.Setters.Add(new Setter(DataGridCell.BackgroundProperty, brush));
                dgrClmnHdr.Column.CellStyle = style;
            }
        }
    }
}

xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
    <DataGrid.Resources>
        <Style TargetType="{x:Type DataGridColumnHeader}">
            <Setter Property="ContentTemplate">
                <Setter.Value>
                    <DataTemplate>
                        <StackPanel>
                            <TextBlock x:Name="myBlock" Text="{Binding}" TextWrapping="Wrap" />
                            <TextBox x:Name="myBox">
                                <i:Interaction.Behaviors>
                                    <local:ObserveEmpty TargetBgrndBrush="Aqua" TargetBgrndBrushOnEmpty="Red" 
                                                        TargetControl="{Binding RelativeSource={RelativeSource AncestorType=DataGridColumnHeader}, Mode=OneWay}"/>
                                </i:Interaction.Behaviors>
                            </TextBox>
                        </StackPanel>
                    </DataTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </DataGrid.Resources>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM