以编程方式向wpf dgv中的行中添加多个具有样式的DataGridCell [英] Add more than 1 DataGridCell with style to a row in wpf dgv programatically

查看:87
本文介绍了以编程方式向wpf dgv中的行中添加多个具有样式的DataGridCell的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个类 Ro ,其中有4个字段(2个名称和2种颜色)

I have a class Ro that has 4 fields (2 names and 2 colors)

public class Ro
    {
        public string c1 { get; set; }
        public SolidColorBrush c1Color { get; set; }
        public string c2 { get; set; }
        public SolidColorBrush c2Color { get; set; }
    }

我创建了 Ro对象列表

List<Ro> data = new List<Ro>();
            data.Add(new Ro()
            {
                c1 = "7B",
                c1Color = Brushes.Green,
                c2 = "",
                c2Color = Brushes.White
            });
            data.Add(new Ro()
            {
                c1 = "Jot",
                c1Color = Brushes.Green,
                c2 = "",
                c2Color = Brushes.Black
            });
            data.Add(new Ro()
            {
                c1 = "Nav",
                c1Color = Brushes.White,
                c2 = "",
                c2Color = Brushes.Orange
            });

现在我要使用此列表来填充 wpf DataGridView 在循环列表时根据对象的当前字段为每个单元格分配颜色

Now I want to use this List to populate a wpf DataGridView assigning the color to each cell depending on current field of object when looping the list

为此,我创建了一个为每个单元格创建ControlTemplate的方法:

To do so I created a method that will create ControlTemplate for each cell:

        public ControlTemplate CellTemplate(string text, SolidColorBrush color)
        {
            ControlTemplate template = new ControlTemplate();
            template.VisualTree = new FrameworkElementFactory(typeof(TextBlock));
            template.VisualTree.SetValue(TextBlock.TextProperty, text);
            template.VisualTree.SetValue(TextBlock.BackgroundProperty, color);
            template.VisualTree.SetValue(TextBlock.TextAlignmentProperty, TextAlignment.Center);
            template.VisualTree.SetValue(TextBlock.FontWeightProperty, FontWeights.Bold);
            if (color == Brushes.White)
                template.VisualTree.SetValue(TextBlock.ForegroundProperty, Brushes.Black);
            else
                template.VisualTree.SetValue(TextBlock.ForegroundProperty, Brushes.White);
            return template;
        }

我还创建了一个dataColumn c1

and also I created a dataColumn c1

dataGrid1.Columns.Add(
    new DataGridTextColumn
    { Header = "c1" });

最后在foreach循环中,我创建具有样式的单元格

finally in a foreach loop I create the cells with styles

foreach (Ro me in data)
{
    DataGridCell cell0 = new DataGridCell { Template = CellTemplate(me.c1,me.c1Color) };
    dataGrid1.Items.Add(cell0);
  }

到目前为止还不错,但是当我添加第二列并尝试应用相同的想法时,例如

so far so good, however when I add the second column and try to apply the same idea like

 dataGrid1.Columns.Add(
    new DataGridTextColumn
    { Header = "c2" });

foreach (Ro me in data)
{
    DataGridCell cell0 = new DataGridCell { Template =    CellTemplate(me.c1,me.c1Color) };
    dataGrid1.Items.Add(cell0);

   DataGridCell cell1 = new DataGridCell { Template = CellTemplate(me.c2, me.c2Color) };
    dataGrid1.Items.Add(cell1);
}

我受到鼓舞:


System.ArgumentOutOfRangeException在
上未处理System.Windows.Media.VisualCollection.get_Item(Int32索引)在System.Windows.Controls.UIElementCollection.get_Item(Int32索引上) )
在System.Windows.Controls.UIElementCollection.System.Collections.IList.get_Item(Int32
索引)
在System.Windows.Controls.DataGridCellsPanel.ArrangeOverride(大小
rangitSize )...

System.ArgumentOutOfRangeException was unhandled on System.Windows.Media.VisualCollection.get_Item(Int32 index) on System.Windows.Controls.UIElementCollection.get_Item(Int32 index) on System.Windows.Controls.UIElementCollection.System.Collections.IList.get_Item(Int32 index) on System.Windows.Controls.DataGridCellsPanel.ArrangeOverride(Size arrangeSize) ...

如果dgv中只有一列,我会得到:

if I have only one column in dgv I get:

我尝试执行以下操作,但出现错误,我不知道如何在dgv中的特定列中插入特定的单元格...

I tried doing following, but got error, I do not know how to insert a particular cell in a particular column in dgv...

 foreach (Ro me in data)
            {
                DataGridCell cell0 = new DataGridCell { Template = CellTemplate(me.c1, me.c1Color) };
                DataGridCell cell1 = new DataGridCell { Template = CellTemplate(me.c2, me.c2Color) };
                dataGrid1.Columns.Insert(0, cell0);
                dataGrid1.Columns.Insert(1, cell0);
                //dataGrid1.Items.Add(cell0);
                //dataGrid1.Items.Add(cell1);
            }

如何以编程方式在一行中添加单元格?

How can I add cells in a row programatically?

推荐答案

如果不做一些体操,这是不可能的。像这样添加您的列:

This is not possible without doing some gymnastics. Add your columns like this:

this.dataGrid.Columns.Add(
    new DataGridTextColumn
    { Header = "c1", Binding = new Binding("c1") } );

this.dataGrid.Columns.Add(
    new DataGridTextColumn
    { Header = "c2", Binding = new Binding("c2") });
this.dataGrid.LoadingRow += DataGrid_LoadingRow;

foreach (Ro me in data)
{
    dataGrid.Items.Add(me);
}

查看代码如何限制 C1 列到 Ro c1 属性中。查看代码还如何订阅 LoadingRow 事件。这是异步调用 AlterRow 方法的行的处理程序:

See how the code bounds the C1 column to c1 property of your Ro. See how the code also subscribes to the LoadingRow event. Here is the handler for the row which calls the AlterRow method asynchronously:

private void DataGrid_LoadingRow(object sender, DataGridRowEventArgs e)
{
    Dispatcher.BeginInvoke(DispatcherPriority.Render, new Action(() => AlterRow(e)));
}

这是其余的代码,基本上可以找到列0中的单元格并为每一行设置第1列,然后找出背景属性并进行设置。

And here is the rest of the code which basically finds the cells in columns 0 and columns 1 for each row and then figures out the background property and sets it.

private void AlterRow(DataGridRowEventArgs e)
{
    var cell = GetCell(dataGrid, e.Row, 0);
    if (cell == null) return;

    var item = e.Row.Item as Ro;
    if (item == null) return;

    cell.Background = item.c1Color;

    cell = GetCell(dataGrid, e.Row, 1);
    if (cell == null) return;

    cell.Background = item.c2Color;
}

public static T GetVisualChild<T>(Visual parent) where T : Visual
{
    T child = default(T);
    int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
    for (int i = 0; i < numVisuals; i++)
    {
        var v = (Visual)VisualTreeHelper.GetChild(parent, i);
        child = v as T ?? GetVisualChild<T>(v);
        if (child != null)
        {
            break;
        }
    }
    return child;
}


public static DataGridCell GetCell(DataGrid host, DataGridRow row, int columnIndex)
{
    if (row == null) return null;

    var presenter = GetVisualChild<DataGridCellsPresenter>(row);
    if (presenter == null) return null;

    // try to get the cell but it may possibly be virtualized
    var cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(columnIndex);
    if (cell == null)
    {
        // now try to bring into view and retreive the cell
        host.ScrollIntoView(row, host.Columns[columnIndex]);
        cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(columnIndex);
    }
    return cell;
}

某些代码是从此处

这篇关于以编程方式向wpf dgv中的行中添加多个具有样式的DataGridCell的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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