简体   繁体   English

当绑定属性的值更改时,更改DataGrid单元格的文本颜色

[英]Change Text Color of DataGrid Cell when value of bound property changes

I have a DataGrid in WPF, filled with elements of an ObservableCollection ( ElementGroup items that have an ID and a Text property and are read from an XML file). 我在WPF中有一个DataGrid ,其中填充了ObservableCollection元素(具有ID和Text属性并从XML文件读取的ElementGroup项)。 What I want to achieve is that the text color of the cell content changes when a user has edited the value of the cell. 我要实现的是,当用户编辑单元格的值时,单元格内容的文本颜色会更改。 The color of the cell should remain for example green as soon as the user leaves the cell and the value is different than the original value. 用户离开单元格后,单元格的颜色应保持例如绿色,并且该值与原始值不同。

What I have so far: 到目前为止,我有:

A user control with the following datagrid: 具有以下数据网格的用户控件:

<DataGrid Grid.Row="7" Grid.Column="3" ItemsSource="{Binding Config.ElementGroups, Mode=TwoWay}" AutoGenerateColumns="False" >            
    <DataGrid.Columns>  
        <DataGridTextColumn Header="ID" Binding="{Binding Id, Mode=TwoWay}" Width="Auto"/>
        <DataGridTextColumn Header="Group Name" Binding="{Binding Text, Mode=TwoWay}" Width="*" />
    </DataGrid.Columns>
</DataGrid>

Nothing in the code behind of the User Control. 用户控件后面的代码中没有任何内容。

The ElementGroup class with the 2 Properties, that also implements INotifyPropertyChanged (extra class in order to re-use it) 具有2个属性的ElementGroup类,该类还实现了INotifyPropertyChanged (额外的类,以便重新使用它)

public class ElementGroup : NotifyPropertyChangedBase, ITag
{
    private int myId;
    private string myText;

    public ElementGroup()
    {
        Elements = new List<Element>();
    }

    public List<Element> Elements { get; private set; }

    public int Id 
    { 
        get { return myId; }
        set
        {
            if (myId == value)
            {
                return;
            }
            myId = value;
            OnPropertyChanged();
        }
    }

    public string Text
    {
        get { return myText; }
        set
        {
            if (myText == value)
            {
                return;
            }
            myText = value;
            OnPropertyChanged();
        }
    }
}

The datagrid rows are correctly filled: datagrid行已正确填充:

datagrid example 数据网格示例

I listen to the property changed event in my viewmodel. 我在视图模型中监听属性更改事件。 The event is fired and the breakpoint is hit when I set it to the handler and then change a cell of the datagrid. 当我将其设置为处理程序,然后更改数据网格的单元格时,将触发该事件并触发断点。 The HasTextChanged and HasIdChanged functions return true if the change is a real change or false if the value was changed to the previous value. 如果更改是真实更改,则HasTextChangedHasIdChanged函数返回true;如果将值更改为先前值,则返回false。

private void GroupPropertyChanged(object sender, PropertyChangedEventArgs propertyChangedEventArgs)
{
    ElementGroup changedGroup = sender as ElementGroup;

    switch (propertyChangedEventArgs.PropertyName)
    {
        case "Text":
            GroupChanged = HasTextChanged(changedGroup);
            OnPropertyChanged("GroupChanged");
            break;
        case "Id":
            GroupChanged = HasIdChanged(changedGroup);
            OnPropertyChanged("GroupChanged");
            break;
    }           
}

What I have tried: 我尝试过的

At first I thought I just return a color and bind the foreground color to the datagrid, just as it is working for a simple TextBox : 起初,我以为我只是返回一种颜色并将前景色绑定到数据网格,就像它在一个简单的TextBox

<TextBox Grid.Row="5" Grid.Column="3" Text="{Binding Config.Description}" Foreground="{Binding DescriptionColor}"/>

But putting the same Foreground binding to the DataGridTextColumns did not work. 但是,将相同的前台绑定放置到DataGridTextColumns无效。 I tried to adapt the answer found here ( Change Color of DatagridCell ) but could not get it to work ( DescriptionColor in below example is SolidColorBrush DescriptionColor = Brushes.Green : 我试着去适应这里找到(答案DatagridCell改色 ),但无法得到它的工作( DescriptionColor在下面的例子是SolidColorBrush DescriptionColor = Brushes.Green

<DataGridTextColumn Header="Group Name" Binding="{Binding Text, Mode=TwoWay}" Width="*" >
    <DataGridTextColumn.CellStyle>
        <Style>
            <Setter Property="Border.Background" Value="{Binding DescriptionColor}"/>
        </Style>
    </DataGridTextColumn.CellStyle>
</DataGridTextColumn>

All other cell color change answers I found were about setting a trigger and if the value changes to a specified value, then the color can be changed. 我发现的所有其他单元格颜色更改答案均与设置触发器有关,如果该值更改为指定值,则可以更改颜色。

So I decided to go for the "real change yes/no" approach and added a style trigger my datagrid: 因此,我决定采用“真正的改变是/否”的方法,并添加了一个触发数据网格的样式:

<DataGrid Grid.Row="7" Grid.Column="3" ItemsSource="{Binding Config.ElementGroups, Mode=TwoWay}" AutoGenerateColumns="False" >
    <DataGrid.CellStyle>
        <Style TargetType="{x:Type DataGridCell}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding GroupChanged}" Value="True">
                    <Setter Property="Background" Value="Green"/>
                </DataTrigger>
                <DataTrigger Binding="{Binding GroupChanged}" Value="False">
                    <Setter Property="Background" Value="Black"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </DataGrid.CellStyle>
    <DataGrid.Columns>  
        <DataGridTextColumn Header="ID" Binding="{Binding Id, Mode=TwoWay}" Width="Auto"/>
        <DataGridTextColumn Header="Group Name" Binding="{Binding Text, Mode=TwoWay}" Width="*" />
    </DataGrid.Columns>
</DataGrid>

This also didn't work and I begin to wonder if I miss something elementary. 这也行不通,我开始怀疑我是否想念一些基本的东西。

Has anybody an idea what I do wrong, or what I have to do to get this to work? 有谁知道我做错了什么,或者我必须做些什么才能使它起作用? I must admit that I am not 100% understanding how the trigger works and if it really knows what to do... 我必须承认我不是100%理解触发器如何工作以及它是否真的知道该怎么做...

Thanks 谢谢

If I clearly understand you want to mark cell what is currently edited by user. 如果我清楚理解您要标记单元格,则用户当前正在编辑什么。 So if you are using DataGridTextBoxColumns you can add EditingElementStyle for them. 因此,如果您使用的是DataGridTextBoxColumns ,则可以EditingElementStyle添加EditingElementStyle

<DataGrid.Resources>
    <Style x:Key="EditingStyle" TargetType="TextBox">
        <Setter Property="Background" Value="Green" />
        <Setter Property="Foreground" Value="White" />
    </Style>
</DataGrid.Resources>

And the columns should look like this. 列应如下所示。

<DataGridTextColumn Header="ID" Binding="{Binding Id, Mode=TwoWay}" Width="Auto"
                    EditingElementStyle="{StaticResource EditingStyle}" />

Update 更新

To remaing color of edited cells you can 1 add some bool props into ElementGroup that indicating edited cells. 要保持已编辑单元格的颜色,您可以1将一些bool道具添加到ElementGroup ,以指示已编辑单元格。 Something like this. 这样的事情。

private bool _isIdChanged;
public bool IsIdChanged
{
    get { return _isIdChanged; }
    set { _isIdChanged = value; NotifyPropertyChanged( "IsIdChanged" ); }
}

2 You should add into the id setter IsIdChanged = true . 2您应该在id设置器中添加IsIdChanged = true

...
myId = value;
OnPropertyChanged();
IsIdChanged = true;

3 Change the binding for ID column. 3更改“ ID绑定”列。

Binding="{Binding Id, Mode=TwoWay, NotifyOnTargetUpdated=True}"

4 Add style for this column. 4为该列添加样式。

<Style x:Key="IdStyle" TargetType="DataGridCell">
    <Style.Triggers>
        <DataTrigger Binding="{Binding IsIdChanged}" Value="True">
            <Setter Property="Background" Value="Green" />
        </DataTrigger>
    </Style.Triggers>
</Style>

<DataGridTextColumn Name="ID" ... CellStyle="{StaticResource IdStyle}" />

5 After binding to the DataGrid should change all values of the IsIdChanged of the collection elements to false. 5绑定到DataGrid之后,应将集合元素的IsIdChanged的所有值更改为false。 And it needed to set it to false after changing values from code behind. 并且需要从后面的代码更改值后将其设置为false。

6 Should add same code for other columns. 6应该为其他列添加相同的代码。 Hope this helps. 希望这可以帮助。

Update 更新

I've looked at your code, you should change DataTrigger binding to this. 我看过您的代码,您应该更改DataTrigger绑定。

<DataTrigger Binding="{Binding IdChanged}" Value="True">
    <Setter Property="Background" Value="Green" />
</DataTrigger>

And you should add these strings in the constructor of ChangeConfigSettingViewModel . 并且应该将这些字符串添加到ChangeConfigSettingViewModel的构造函数中。 It should be last strings of constructor for initializing IdChanged values to false. 它应该是用于将IdChanged值初始化为false的构造函数的最后一个字符串。

foreach ( PersonModel pers in myPersons )
{
    pers.IdChanged = false;
}

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

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