简体   繁体   English

WPF Datagrid基于值的行颜色

[英]WPF Datagrid row color based on a value

I have the following code filling the resources of a data grid on run time. 我有以下代码在运行时填充数据网格的资源。

DataTable dt = new DataTable();
dt.Columns.Add("Date");
dt.Columns.Add("User");
dt.Columns.Add("Type");
foreach (var x in query)
{
    var row = dt.NewRow();
    decimal total_REC = 0;
    decimal total_RET = 0;

    row["Date"] = x.CurrentDate.ToString();
    row["User"] = x.User;
    row["Type"] = x.TranscationType;
    dt.Rows.Add(row);
}

And in the end i refer my data grid to this datatable 最后,我将数据网格引用到此数据表

dgv_Transations.DataContext = dt;

During the first function, i can figure out which rows need to be highlighted, from x.TransactionType. 在第一个函数中,我可以从x.TransactionType中找出需要突出显示的行。 All the types which are equal to the value "A" will have their corresponding rows highlighted in yellow, as in the background would be yellow. 等于值“ A”的所有类型的对应行将以黄色突出显示,因为背景将为黄色。

Is there any way to programatically set the background color of the whole row on runtime (from the c# code) to be as i want. 有没有办法以编程方式在运行时(从C#代码)将整行的背景色设置为我想要的。 I can use dt.rows.count as my index, but i can't figure out a way to set the datagrid row background color (always getting null reference exceptions). 我可以将dt.rows.count用作索引,但是我不知道一种设置datagrid行背景色的方法(总是获取null引用异常)。

In winforms i would go datagridview.rows and proceed, but in WPF i do not have the option. 在Winforms中,我将转到datagridview.rows并继续,但是在WPF中,我没有选择。 I tried the following but it keeps returning null. 我尝试了以下操作,但始终返回null。

if (dt.Rows.Count > 0)
{
    DataGridRow r = dgv_Transations.ItemContainerGenerator.ContainerFromIndex(dt.Rows.Count - 1) as DataGridRow;
    r.Background = Brushes.Red;
}

I'm modifying this answer from a solution I used slightly differently. 我正在从使用稍有不同的解决方案中修改此答案。

You could create an XAML style for the window where you have your DataGrid. 您可以为拥有DataGrid的窗口创建XAML样式。

<Window.Resources>
   <Style TargetType="{x:Type DataGridRow}">
      <Style.Setters>
            <Setter Property="Background" Value="{Binding Path=Code}"></Setter>
      </Style.Setters>
   </Style>
</Window.Resources>

"Code" is the name of a class variable of type string which holds the color names ("Red", "Blue" etc). “代码”是字符串类型的类变量的名称,其中包含颜色名称(“红色”,“蓝色”等)。 So in your case "Code" would be a column in your dt. 因此,在您的情况下,“代码”将是dt中的一列。

Then, you need to set the value of "Code" to yellow whenever you want the line to be highlighted. 然后,每当要突出显示该行时,都需要将“代码”的值设置为黄色。

If you're not very clear please refer to the original code sample I've used here: 如果您不太清楚,请参考我在这里使用的原始代码示例:

Original Code Sample 原始代码样本

You could create an IValueConverter that converts transaction type to a brush and put an entry in Window.Resources to register it. 您可以创建一个IValueConverter,将事务类型转换为画笔,然后在Window.Resources中放置一个条目以进行注册。

public class TransactionTypeConverter: IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            var trxnType = value as int;
            if (value == null || trxnType==null) return Brushes.Transparent;

            if(trxnType==1) return Brushes.Red;            

            return Brushes.Transparent;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {        
}               

Then there are two things you can try: 然后可以尝试两种方法:

  1. You could bind the RowBackground of the DataGrid to the Type and bind Converter to TransactionTypeConverter: 您可以将DataGrid的RowBackground绑定到Type,然后将Converter绑定到TransactionTypeConverter:

    <DataGrid RowBackground="{Binding transactionType}" Converter="{StaticResource TransactionTypeConverter}"> <Da​​taGrid RowBackground =“ {Binding transactionType}” Converter =“ {StaticResource TransactionTypeConverter}”>

  2. Do the same thing but in the cell template. 在单元格模板中执行相同的操作。

The common and recommended way to do this would be to use a data trigger in XAML as suggested by @Sach but if you still want to do this programmatically you can actually get a reference to the visual container using the ItemContainerGenerator . 推荐的常用方法是按照@Sach的建议在XAML中使用数据触发器,但是如果您仍然想以编程方式执行此操作,则实际上可以使用ItemContainerGenerator获取对可视容器的引用。

You must wait until the containers have been created though. 但是,您必须等待,直到创建了容器。 You could do this by calling the ContainerFromIndex method in a Loaded event handler: 您可以通过在Loaded事件处理程序中调用ContainerFromIndex方法来做到这一点:

public MainWindow()
{
    InitializeComponent();
    DataTable dt = new DataTable();
    dt.Columns.Add("Date");
    dt.Columns.Add("User");
    dt.Columns.Add("Type");
    for (int i = 1; i < 10; ++i)
    {
        var row = dt.NewRow();
        row["Date"] = 1;
        row["User"] = 2;
        row["Type"] = 3;
        dt.Rows.Add(row);
    }

    dgv_Transations.ItemsSource = dt.DefaultView;

    dgv_Transations.Loaded += (s, e) =>
    {
        if (dt.Rows.Count > 0)
        {
            DataGridRow r = dgv_Transations.ItemContainerGenerator.ContainerFromIndex(dt.Rows.Count - 1) as DataGridRow;
            r.Background = Brushes.Red;
        }
    };
}

The second issue is that the DataGrid uses UI virtualization. 第二个问题是DataGrid使用UI虚拟化。 This means that only the containers for the data rows you actually see on the screen are generated. 这意味着仅生成您实际在屏幕上看到的数据行的容器。 So if the last row is scrolled away it no longer has any DataGridRow container. 因此,如果将最后一行滚动开,则它将不再具有任何DataGridRow容器。

You could solve this by disabling the virtualization: 您可以通过禁用虚拟化来解决此问题:

<DataGrid x:Name="dgv_Transations" VirtualizingPanel.IsVirtualizing="False" />

Of course this may affect the performance negatively. 当然,这可能会对性能产生负面影响。

The other option would be to scroll to the item and then generate the container programmatically: 另一个选择是滚动到该项目,然后以编程方式生成容器:

dgv_Transations.Loaded += (s, e) => 
{
    if (dt.Rows.Count > 0)
    {
        var lastItem = dt.DefaultView[dt.Rows.Count - 1];
        DataGridRow r = dgv_Transations.ItemContainerGenerator.ContainerFromItem(lastItem) as DataGridRow;
        if (r == null)
        {
            dgv_Transations.ScrollIntoView(lastItem);
            r = dgv_Transations.ItemContainerGenerator.ContainerFromItem(lastItem) as DataGridRow;
        }
        r.Background = Brushes.Red;
    }
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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