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

时间:2016-01-12 06:43:22

标签: c# wpf xaml mvvm datagrid

我在WPF中有一个DataGrid,其中包含ObservableCollectionElementGroup项的元素,这些项具有ID和Text属性,并从XML文件中读取。 我想要实现的是当用户编辑单元格的值时,单元格内容的文本颜色会发生变化。一旦用户离开单元格并且该值与原始值不同,单元格的颜色应保持为绿色。

到目前为止我所拥有的:

具有以下数据网格的用户控件:

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

用户控件后面的代码中没有任何内容。

带有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();
        }
    }
}

正确填充数据网格行:

datagrid example

我在viewmodel中收听属性更改事件。当我将其设置为处理程序然后更改数据网格的单元格时,会触发该事件并触发断点。 如果更改是实际更改,则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;
    }           
}

我尝试过:

起初我以为我只是返回一种颜色并将前景颜色绑定到数据网格,就像它适用于简单的TextBox一样:

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

但是将相同的Foreground绑定放到DataGridTextColumns上并不起作用。我尝试调整此处的答案(Change Color of DatagridCell),但无法使其正常工作(以下示例中的DescriptionColorSolidColorBrush 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>

我发现的所有其他单元格颜色更改答案都是关于设置触发器,如果​​值更改为指定值,则可以更改颜色。

所以我决定选择&#34;真正改变是/否&#34;方法并添加了一个样式触发我的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>

这也没有用,我开始怀疑自己是否会错过一些基本的东西。

有人知道我做错了什么,或者我需要做些什么才能让它发挥作用? 我必须承认,我并非100%了解触发器的工作原理,以及它是否真的知道该怎么做......

由于

1 个答案:

答案 0 :(得分:0)

如果我清楚地了解您想要标记用户当前编辑的单元格。因此,如果您使用的是DataGridTextBoxColumns,则可以为其添加EditingElementStyle

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

列应该是这样的。

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

<强>更新

要重新编辑已编辑单元格的颜色,您可以在ElementGroup中添加一些指示已编辑单元格的bool道具。这样的事情。

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

2您应该添加到ID设置器IsIdChanged = true

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

3更改ID列的绑定。

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

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绑定到DataGrid后,应将集合元素的IsIdChanged的所有值更改为false。并且在从后面的代码更改值之后需要将其设置为false。

6应为其他列添加相同的代码。希望这会有所帮助。

<强>更新

我查看了您的代码,您应该将DataTrigger绑定更改为此。

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

您应该在ChangeConfigSettingViewModel的构造函数中添加这些字符串。它应该是构造函数的最后一串,用于将IdChanged值初始化为false。

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