Avalonia UI C# XAML WPF - настройка цвета строки сетки данных на основе значения столбца

public class EventLogView : UserControl
{
    private DataGrid dataGrid;
    public EventLogView()
    {
        this.InitializeComponent();
        dataGrid = this.FindControl<DataGrid>("EventLogsDataGrid");
        this.dataGrid.LoadingRow += new EventHandler<DataGridRowEventArgs>(dataGrid_LoadingRows);
    } 

    private void InitializeComponent()
    {
        AvaloniaXamlLoader.Load(this);
    }

    void dataGrid_LoadingRows(object sender, DataGridRowEventArgs e)
    {

    }
}

Я хотел бы изменить цвет каждой строки на красный, если значение 4-го столбца "ВЫСОКОЕ".

3 ответа

Решение

Чтобы сделать это в "чистом" WPF, нужно определить ItemContainerStyle с DataTrigger:

<DataGrid x:Name="EventLogsDataGrid"
                  AutoGenerateColumns="False"
                  Items="{Binding LogsData}"
                  CanUserReorderColumns="True"
                  CanUserResizeColumns="True"
                  IsReadOnly="True">
    <DataGrid.ItemContainerStyle>
        <Style TargetType="DataGridRow">
            <Style.Triggers>
                <DataTrigger Binding="{Binding Importance}" Value="HIGH">
                    <Setter Property="Background" Value="Red" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </DataGrid.ItemContainerStyle>
    <DataGrid.Columns>
        <DataGridTextColumn Binding="{Binding Id}"
                                Header="ID"
                                Width="Auto"/>
        <DataGridTextColumn Binding="{Binding Content}"
                                Header="Content"
                                Width="Auto"/>
        <DataGridTextColumn Binding="{Binding CreationDate}"
                                Header="Date Time"
                                Width="Auto"/>
        <DataGridTextColumn Binding="{Binding Source}"
                                Header="Source"
                                Width="Auto"/>
        <DataGridTextColumn Binding="{Binding Importance}"
                                Header="Priority"
                                Width="Auto"/>
    </DataGrid.Columns>
</DataGrid>

Но поскольку Avalonia не поддерживает триггеры, вам, возможно, придется справиться с LoadingRow событие примерно так, чтобы установить Background свойство программно:

void dataGrid_LoadingRows(object sender, DataGridRowEventArgs e)
{
    var dataObject = e.Row.DataContext as YourDataObject;
    if (dataObject != null && dataObject.Importance == "HIGH")
        e.Row.Background = Brushes.Red;
}

Может быть и другой способ сделать то же самое, но в XAML. Честно говоря, я не участвую в квесте, но это было очень близко. Автор Avalonia.Xaml.Behaviors Wiesław Šoltés опубликовал пример очень интересного подхода . Я попытался применить его для использования со строкой DataGrid, и это почти сработало:

      <Window xmlns="https://github.com/avaloniaui"
        xmlns:int="clr-namespace:Avalonia.Xaml.Interactivity;assembly=Avalonia.Xaml.Interactivity"
        xmlns:ia="clr-namespace:Avalonia.Xaml.Interactions.Core;assembly=Avalonia.Xaml.Interactions"        
        x:Class="BvsDesktopLinux.Views.MainWindow" ...>
...
<Window.Styles>
    <Style Selector="DataGridCell.statusColumn">
        <Setter Property="FontSize" Value="24"/>
        <Setter Property="(int:Interaction.Behaviors)">
            <int:BehaviorCollectionTemplate>
                <int:BehaviorCollection>
                    <ia:DataTriggerBehavior Binding="{Binding Status}" ComparisonCondition="Equal" Value="Rejected">
                        <ia:ChangePropertyAction TargetObject="DataGridCell" PropertyName="Background" Value="Red" />
                    </ia:DataTriggerBehavior>
                </int:BehaviorCollection>
            </int:BehaviorCollectionTemplate>
        </Setter>
    </Style>
</Window.Styles>
...
<DataGrid AutoGenerateColumns="False" Margin="10"
          Items="{Binding Banknotes}" SelectedItem="{Binding SelectedBanknote}">
    <DataGrid.Columns>
        <DataGridTextColumn Header="{x:Static p:Resources.NoteId}" Binding="{Binding Id}" />
        <DataGridTextColumn Header="{x:Static p:Resources.NoteCurrency}" Binding="{Binding Currency}" />
        <DataGridTextColumn Header="{x:Static p:Resources.NoteDenomination}" Binding="{Binding Denomination}" />
        <DataGridTextColumn Header="{x:Static p:Resources.Status}" Binding="{Binding Status}" CellStyleClasses="statusColumn" />
    </DataGrid.Columns>
</DataGrid>

У меня была только одна проблема с кодом — привязка не использует DataContext DataGridCell (элемент ObservableCollection из ViewModel), а использует DataContext всего представления/окна (ViewModel).

@mm8: Спасибо за полезную подсказку! Я искал тот же ответ и начал с вашего совета. Я столкнулся с проблемой после сортировки строк или перезагрузки содержимого с некоторыми изменениями. К нескольким строкам, не соответствующим критериям, было прикреплено свойство фона. Поэтому я использовал стили для присоединения/отсоединения стиля:

      <Window.Styles>
    <Style Selector="DataGridRow.rejectedStatus">
        <Setter Property="Background" Value="Red"/>
        <Setter Property="Foreground" Value="White"/>
    </Style>
</Window.Styles>
      private void DataGrid_OnLoadingRow(object? sender, DataGridRowEventArgs e)
{
    var dataObject = e.Row.DataContext as Models.Banknote;
    if (dataObject != null && dataObject.Status == "Rejected")
    {
        e.Row.Classes.Add("rejectedStatus");
    }
    else
    {
        e.Row.Classes.Remove("rejectedStatus");
    }
}
Другие вопросы по тегам