WPF Datagrid基于值的行颜色

时间:2017-01-30 22:25:49

标签: c# wpf datagrid

我有以下代码在运行时填充数据网格的资源。

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);
}

最后,我将我的数据网格引用到此数据表

dgv_Transations.DataContext = dt;

在第一个函数中,我可以从x.TransactionType中找出需要突出显示哪些行。所有等于值“A”的类型将使其对应的行以黄色突出显示,因为在背景中将为黄色。

有没有办法以编程方式在运行时(从c#代码)设置整行的背景颜色为我想要的。我可以使用dt.rows.count作为我的索引,但我无法想出一种设置datagrid行背景颜色的方法(总是得到空引用异常)。

在winforms我会去datagridview.rows并继续,但在WPF我没有选项。我尝试了以下但它一直返回null。

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

3 个答案:

答案 0 :(得分:2)

我从一个稍微不同的解决方案中修改了这个答案。

您可以为拥有DataGrid的窗口创建XAML样式。

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

&#34;代码&#34;是类型为string的类变量的名称,它包含颜色名称(&#34;红色&#34;,&#34;蓝色&#34;等)。所以在你的情况下&#34; Code&#34;将是你的dt中的一个专栏。

然后,你需要设置&#34; Code&#34;的值。只要你想要突出显示这条线就黄色。

如果您不是很清楚,请参阅我在此处使用的原始代码示例:

Original Code Sample

答案 1 :(得分:0)

您可以创建一个将事务类型转换为画笔的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)
        {        
}               

然后你可以尝试两件事:

  1. 您可以将DataGrid的RowBackground绑定到Type并将Converter绑定到TransactionTypeConverter:

    &lt; DataGrid RowBackground =&#34; {Binding transactionType}&#34; Converter =&#34; {StaticResource TransactionTypeConverter}&#34;&gt;

  2. 在细胞模板中做同样的事情。

答案 2 :(得分:0)

执行此操作的常见和推荐方法是使用@Sach建议的XAML中的数据触发器,但如果您仍希望以编程方式执行此操作,则实际上可以使用{{1}获取对可视容器的引用}。

您必须等到创建容器。您可以通过调用ItemContainerGenerator事件处理程序中的ContainerFromIndex方法来执行此操作:

Loaded

第二个问题是DataGrid使用UI虚拟化。这意味着只生成您在屏幕上实际看到的数据行的容器。因此,如果最后一行被滚动,它就不再有任何DataGridRow容器。

您可以通过禁用虚拟化来解决此问题:

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;
        }
    };
}

当然这可能会对性能产生负面影响。

另一个选项是滚动到该项目,然后以编程方式生成容器:

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