WPF DataGrid DataTrigger Binding on DataContext pr

2019-09-11 14:15发布

问题:

What's the correct DataTrigger binding for DataContext properties? I have a DataGrid which is bound like this:

XAML:

<DataGrid x:Name="dataGrid" Grid.Row="4" Grid.ColumnSpan="2"
    ItemsSource="{Binding}"
    CellStyle="{StaticResource RowStateStyle}"
>
</DataGrid>

In .cs the grid is bound to a DataTable, hence the DataContext for a cell is DataRowView, containing Row as a property:

// DataTable containing lots of rows/columns
dataGrid.DataContext = dataTable; 

Edit:

Refering to ASh's solution I edited the style and put in Triggers for Unchanged and Modified:

    <Style x:Key="RowStateStyle" TargetType="{x:Type DataGridCell}">
        <Style.Triggers>
            <DataTrigger Binding="{Binding Path=DataContext.Row.RowState,
                RelativeSource={RelativeSource Self}}" Value="Unchanged">
                <Setter Property="Foreground" Value="Green" />
            </DataTrigger>
            <DataTrigger Binding="{Binding Path=DataContext.Row.RowState,
                RelativeSource={RelativeSource Self}}" Value="Modified">
                <Setter Property="Foreground" Value="Yellow" />
            </DataTrigger>
            <DataTrigger Binding="{Binding Path=Content.Text,
                RelativeSource={RelativeSource Self}}" Value="test">
                <Setter Property="Foreground" Value="Red" />
            </DataTrigger>
        </Style.Triggers>
    </Style>

Triggering on Content.Text works perfectly fine, so does Unchanged. However when I modify a cell (thus DataRowState = Modified), nothing happens and the color stays green. Any solution?

回答1:

DataTrigger works for me, if I

  1. use DataContext.Row.RowState path

  2. don't use Mode=TwoWay

  3. and remove enum name DataRowState when set Value

<DataTrigger Binding="{Binding Path=DataContext.Row.RowState,
             RelativeSource={RelativeSource Self}}" 
             Value="Unchanged">
    <Setter Property="Foreground" Value="Red" />
</DataTrigger>

I have found another post related to this issue

WpfToolkit DataGrid: Highlight modified rows

There is no default mechanism which notifies about RowState changes. But it is possible to create one in a derived dataTable class:

public class DataTableExt: DataTable
{
    protected override DataRow NewRowFromBuilder(DataRowBuilder builder)
    {
        return new DataRowExt(builder);
    }

    protected override void OnRowChanged(DataRowChangeEventArgs e)
    {
        base.OnRowChanged(e);
        // row has changed, notifying about changes
        var r = e.Row as DataRowExt;
        if (r!= null)
            r.OnRowStateChanged();
    }
}

with a derived dataRow class:

public class DataRowExt: DataRow, INotifyPropertyChanged
{
    protected internal DataRowExt(DataRowBuilder builder) : base(builder)
    {
    }

    internal void OnRowStateChanged()
    {
        OnPropertyChanged("RowState");
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
        var handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
}