更改DataGrid WPF中单元格的背景颜色 [英] Changing background color of cells in DataGrid WPF

查看:125
本文介绍了更改DataGrid WPF中单元格的背景颜色的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用以下链接在表格中显示了二维数据:





我本来希望得到福特广场是绿色,本田是黄色,通用汽车是红色,丰田是蓝色的东西。像下面这样(请原谅我可怕的标记技巧)。



解决方案

这是使用 DataView 作为ItemsSource的不幸副作用之一。在这种情况下, DataGridRow 的DataContext是 DataRowView ,它具有属性 Row 。此属性包含一个值数组,这些值是单个单元格。 DataGridCell 继承了 DataContext 。然后,您要查找的是第一列 Row [0] ,第二列是 Row [1] 列等。将下面的XAML用于 DataGridTextColumn ,产生了您在测试中想要的结果,其中使用了 Row [0] 而不是绑定中的 Make 。并感谢您提供如此出色的工作代码,节省了时间!

 < DataGridTextColumn Binding = {Binding Row [0 ]}> 
< DataGridTextColumn.ElementStyle>
< Style TargetType = {x:Type TextBlock}>
< Setter Property = Background Value = {Binding Row [0],Converter = {StaticResource NameToBrushConverter}} />
< / Style>
< /DataGridTextColumn.ElementStyle>
< / DataGridTextColumn>

我最近需要做一些类似的事情,其中​​我的输入必须是不确定维度的二维数组。我最终做了一个可重用的自定义控件,扩展了 DataGrid 。该控件管理自己的DataContext(一个 DataTable ),这使UI变得干净整洁,无需使用索引或任何代码隐藏。



也许有更好的方法可以做到这一点,但我无法弄清楚。另外,这实际上取决于您要实现的目标。如果您的列在设计时是已知的,我将考虑创建一个包含对象的ObservableCollection。如果不是这样,也许有人有更好的技巧,但这至少应该可以使您的代码正常工作。


I used the following links to display my 2 dimensional data in a table:

How to bind an 2D array bool[][] to a WPF DataGrid (one-way)?

Change DataGrid cell colour based on values

All is working except that the background color is not changing (and the converter method is not even being hit). Can someone tell me what's going on?

Below I post a complete, minimal example. I'm not wedded to any of these ideas (using a DataView to bind my IEnumerable> for example) so feel free to suggest alternative methods. My only hard requirement is that in my real project, the data is given as IEnumerable>

Here's the code:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        ViewModel vm = new ViewModel();

        List<Column> row1 = new List<Column>()
        {
            new Column(){Make = Make.Ford,OperatingStatus =  OperatingStatus.Broken},
            new Column(){Make = Make.Honda, OperatingStatus = OperatingStatus.Unknown}
        };
        List<Column> row2 = new List<Column>()
        {
            new Column() {Make = Make.GM, OperatingStatus = OperatingStatus.Working},
            new Column() {Make = Make.Toyota, OperatingStatus = OperatingStatus.Broken}
        };

        List<List<Column>> data = new List<List<Column>>();
        data.Add(row1);
        data.Add(row2);
        vm.Data = data;
        DataContext = vm;

    }
}

public enum OperatingStatus
{
    Working = 0,
    Broken = 1,
    Unknown = 2
}

public enum Make
{
    Ford,
    Honda,
    GM,
    Toyota
}

public class Column
{
    public Make Make { get; set; }
    public OperatingStatus OperatingStatus { get; set; }
}
public class ViewModel
{
    public IEnumerable<IEnumerable<Column>>  Data { get; set; }

    public DataView MyDataTable
    {
        get
        {
            var rows = Data.Count();
            var cols = Data.First().Count();
            var t = new DataTable();
            for (var c = 0; c < cols; c++)
            {
                t.Columns.Add(new DataColumn(c.ToString()));
            }

            foreach (var row in Data)
            {
                var newRow = t.NewRow();
                int c = 0;
                foreach (var col in row)                 
                {
                    newRow[c] = col.Make;
                    c++;
                }
                t.Rows.Add(newRow);
            }
            return t.DefaultView;
        }
    }
}

public class NameToBrushConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        string input = value as string;
        switch (input)
        {
            case "Ford":
                return Brushes.LightGreen;
            case "GM":
                return Brushes.Red;
            case "Toyota":
                return Brushes.Blue;
            case "Honda":
                return Brushes.Yellow;
            default:
                return DependencyProperty.UnsetValue;
        }
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}

And here's the XAML

<Window x:Class="StackOverFlowDataGridQuestion.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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:StackOverFlowDataGridQuestion"
    mc:Ignorable="d"
    Title="MainWindow" Height="450" Width="800">
<Window.Resources>
    <local:NameToBrushConverter x:Key="NameToBrushConverter"/>
</Window.Resources>
<Grid>
    <ScrollViewer>
        <DataGrid Width="1000"
                  Margin="0"
                  HorizontalAlignment="Left"                   
                  DataContext="{Binding}"                      
                  ItemsSource="{Binding MyDataTable}"      >

            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding Make}">
                    <DataGridTextColumn.ElementStyle>
                        <Style TargetType="{x:Type TextBlock}">
                            <Setter Property="Background" Value="{Binding Make, Converter={StaticResource NameToBrushConverter}}"/>
                        </Style>
                    </DataGridTextColumn.ElementStyle>
                </DataGridTextColumn>
            </DataGrid.Columns>
        </DataGrid>
    </ScrollViewer>
</Grid>

After trying Nik's suggestion and replacing 'Make' with 'Row[0]' in two places, I got the following, which is progress because there is some colour! If there is more changes, I'll report back here.

I would have expected to get something where the Ford square is green, Honda is yellow, GM is red, and Toyota is blue. Something more like below (please excuse my horrible markup skills).

解决方案

That is one of the unfortunate side effect of using a DataView as your ItemsSource. The DataContext of a DataGridRow in this case is a DataRowView which has a property Row. This property contains an array of values which are the individual cells. DataGridCell inherits that DataContext. Then what you're looking for is Row[0] for the first column, Row[1] for your second column and so on. Using the XAML below for the DataGridTextColumn, produced the result you're looking for in my testing, where I used Row[0] instead of Make in the bindings. And thank you for providing such good working code, such a time saver!

<DataGridTextColumn Binding="{Binding Row[0]}">
  <DataGridTextColumn.ElementStyle>
    <Style TargetType="{x:Type TextBlock}">
      <Setter Property="Background" Value="{Binding Row[0], Converter={StaticResource NameToBrushConverter}}"/>
    </Style>
  </DataGridTextColumn.ElementStyle>
</DataGridTextColumn>

I recently needed to do something similar where my input had to be a 2-D array of indeterminate dimensions. I ended up making a reusable Custom Control extending a DataGrid. This control managed its own DataContext (a DataTable), which made the UI nice a clean without the need to use indices or any code-behind.

There may be a nicer way to do this, but I could not figure it out. Plus it really depends on what you're trying to achieve. If your columns are known at design time, I would consider creating an ObservableCollection containing objects. If not, maybe someone has a better trick, but at least this should get your code working.

这篇关于更改DataGrid WPF中单元格的背景颜色的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆