简体   繁体   中英

How to customize WinUI 3.0 DataGrid Cell color?

I'm building a WinUI 3.0 Application and I need to change DataGrid cell's color depend on it's value, like this:

1个

But nothing worked so far... The Microsoft's document doesn't make it clear enough: [ styling_formatting_options ]

Is there any way to do this Programatically in WinUi 3.0?

I have query many data, but they are related to WPF, not for WinUI 3.0.

You can create a derived class from DataGridTextColumn and override GenerateElement() :

using CommunityToolkit.WinUI.UI.Controls;
using Microsoft.UI.Xaml.Media;
using Microsoft.UI.Xaml;
using System.Collections.Generic;
using Windows.UI;

namespace DataGridTests;

public class DataGridTextColumnEx : DataGridTextColumn
{
    public Dictionary<string, Color> ValueToColorDictionary
    {
        get => (Dictionary<string, Color>)GetValue(ValueToColorDictionaryProperty);
        set => SetValue(ValueToColorDictionaryProperty, value);
    }

    public static readonly DependencyProperty ValueToColorDictionaryProperty = DependencyProperty.Register(
        nameof(ValueToColorDictionary),
        typeof(Dictionary<string, Color>),
        typeof(DataGridTextColumnEx),
        new PropertyMetadata(new Dictionary<string, Color>()));

    protected override FrameworkElement GenerateElement(DataGridCell cell, object dataItem)
    {
        if (dataItem is Item item &&
            ValueToColorDictionary.TryGetValue(item.Value, out Color color) is true)
        {
            cell.Background = new SolidColorBrush(color);
        }

        return base.GenerateElement(cell, dataItem); ;
    }
}

We can pass he colors using the DependencyProperty ValueToColorDictionary.

Now wen can use it like this:

MainWindowViewModel.cs

using CommunityToolkit.Mvvm.ComponentModel;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;

namespace DataGridTests;

public class Item
{
    public string Name { get; set; } = string.Empty;
    public string Value { get; set; } = string.Empty;
}

public partial class MainWindowViewModel : ObservableObject
{
    [ObservableProperty]
    private ObservableCollection<Item> items = new()
    {
        { new Item() { Name="Person1", Value="A" } },
        { new Item() { Name="Person2", Value="Z" } },
        { new Item() { Name="Person3", Value="B" } },
        { new Item() { Name="Person4", Value="Z" } },
        { new Item() { Name="Person5", Value="C" } },
    };

    [ObservableProperty]
    private Dictionary<string, Color>valueToDictionary = new()
    {
        { "A", Colors.HotPink },
        { "B", Colors.LightGreen },
        { "C", Colors.SkyBlue },
    };
}

MainWindow.xaml

<Window
    x:Class="DataGridTests.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="using:DataGridTests"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:toolkit="using:CommunityToolkit.WinUI.UI.Controls"
    mc:Ignorable="d">

    <Grid>
        <toolkit:DataGrid
            AutoGenerateColumns="False"
            ItemsSource="{x:Bind ViewModel.Items, Mode=OneWay}">
            <toolkit:DataGrid.Columns>
                <toolkit:DataGridTextColumn
                    Width="250"
                    Binding="{Binding Name}"
                    FontSize="14"
                    Header="Name" />
                <local:DataGridTextColumnEx
                    Width="250"
                    Binding="{Binding Value}"
                    FontSize="14"
                    Header="Value"
                    ValueToColorDictionary="{x:Bind ViewModel.ValueToDictionary, Mode=OneWay}" />
            </toolkit:DataGrid.Columns>
        </toolkit:DataGrid>
    </Grid>

</Window>

What I can suggest is a solution to apply a background color to whole rows of the DataGrid using events and the code behind file. Unfortunately I do not know any way to access DataGridCell instances using code.

XAML

In my app, I set an event handler for the LoadingRow event:

    <controls:DataGrid AutoGenerateColumns="False" 
                       ItemsSource="{x:Bind ViewModel.Items}" 
                       SelectedItem="{x:Bind ViewModel.SelectedItem, Mode=TwoWay}"
                       LoadingRow="OnLoadingRow">

CodeBehind

In the code behind file the event handling code sets the background color of the rows depending on some value of the viewmodel that is related to the row:

    private void OnLoadingRow(object sender, DataGridRowEventArgs e)
    {
        DataGrid dataGrid = (DataGrid) sender;
        ViewModelOfRow viewModelOfRow = (ViewModelOfRow)e.Row.DataContext;

        if (dataGrid is null)
        {
            return;
        }

        switch (viewModelOfRow.SomeProperty)
        {
            case A:
                e.Row.Background = new SolidColorBrush(Colors.Green);
                break;
            case B:
                e.Row.Background = new SolidColorBrush(Colors.Yellow);
                break;
            default:
                break;
        }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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