使用动态列将行绑定到数据网格

本文关键字:数据 数据网 网格 绑定 动态 | 更新日期: 2023-09-27 18:34:51

我正在创建一个零售服装POS系统,并希望在特殊格式的DataGrid中显示与样式关联的项目。

如:

┌───────┬───┬───┬───┬───┬───┐│ 颜色 │ S │ M │ L │ X │ 2 │├───────┼───┼───┼───┼───┼───┤│ 红色 │ 2 │ 2 │ 2 │ 0 │ 1 ││ 蓝色 │ 0 │ 1 │ 2 │ 0 │ 0 ││ 粉色 │ 0 │ 2 │ 1 │ 1 │ 1 │└───────┴───┴───┴───┴───┴───┘

我根据样式中的大小在运行时添加了网格上的列。我遇到的唯一问题是当我尝试将 Sizes 属性绑定到列时。

private void SetColumns()
{
    ObservableCollection<DataGridColumn> columns =
        new ObservableCollection<DataGridColumn>();
    var color_col = new DataGridTextColumn()
    {
        Header = "Color",
        Binding = new Binding("Color")
    };
    columns.Add(color_col);
    if (AttributeVisible == Visibility.Visible)
    {
        columns.Add(new DataGridTextColumn()
        {
            Header = AttributeType,
            Binding = new Binding("Attribute")
        });
    }
    foreach (string s in Items.Select(i => i.Size).Distinct())
    {
        columns.Add(new DataGridTextColumn()
        {
            Header = s,
            Binding = new Binding("Sizes[0].Item2")
            //This works, for binding one Size's Quantity to all of the Columns
            //But I need something that does it for each column like a Hashmap
            //Sizes[s].Item2,
            //or a list Sizes.Where(i => i.Item1 == s).Select(i => i.Item2)
        });
    }
    ColumnCollection = new ObservableCollection<DataGridColumn>(columns);
}

该行的模型为:

class StyleGridRow
{
    public string Color
    {
        get;
        set;
    }
    public string Attribute
    {
        get;
        set;
    }
    //The Sizes Property also contains the quantity for the size.
    /*public Hashtable Sizes
    {
        get;
        set;
    }*/
    public List<Tuple<string, int>> Sizes
    {
        get;
        set;
    }

    public StyleGridRow()
    {
        this.Color = "";
        this.Attribute = "";
        this.Sizes = new Hashtable();
    }
    public StyleGridRow(ref string Color, ref string Attribute, ref Hashtable Sizes)
    {
        this.Color = Color;
        this.Attribute = Attribute;
        this.Sizes = Sizes;
    }        
}

我还没有找到一种方法来允许绑定的属性路径合作。

是否有任何类型的数据类型可以用于此目的,或者我是否需要更改我的 StyleGridRow 以更好地适应设计?

使用动态列将行绑定到数据网格

您是否尝试过手动更改数组索引:

// Add an index to specify the array offset
int index = 0;
// The Distinct() will cause issues finding the correct array offset.
// You may need to use GroupBy() or another mechanism to group the
// column with the size.
foreach (string s in Items.Select(i => i.Size).Distinct())
{
    columns.Add(new DataGridTextColumn()
    {
        Header = s,
        // The array index must exist already. You can put a check for it above if needed.
        Binding = new Binding(string.Format("Sizes[{0}].Item2", index)),
    });
    index++;
}

编辑:最好使用ObservableCollection作为大小。您可以使用两个数组或创建另一个类。理想情况下,您将使用另一个类并将 Distinct(( 重构到更高的级别,以便所有StyleGridRow元素具有相同的顺序和长度:

// implement INPC for notifications, but I won't show it for brevity
public class SizeColumn : INotifyPropertyChanged
{
    public string Header { get; set; }
    public int Count { get; set; }
    public int Index { get; set; }
}
class StyleGridRow
{
    // ...
    public ObservableCollection<SizeColumn> SizeColumns { get; set; }
    // ...
}
// ...
int index = 0;
var sizeColumns = new List<SizeColumn>();
// TODO: Refactor `Select().Distinct()` this so all rows will have same order and length
var sizes = Items.Select(i => i.Size).Distinct().ToList();
foreach (string s in sizeColumns)
{
    // Assuming you are summing the values, and the property name is `Value`
    var count = Items.Where(x => x.Size == s).Sum(i => i.Value);
    sizeColumns.Add(new SizeColumn()
    {
        Header = s,
        Count = count,
        Index = index,
    });
    columns.Add(new DataGridTextColumn()
    {
        Header = s,
        Binding = new Binding(string.Format("SizeColumns[{0}].Count", index)),
    });
    ++index;
}
SizeColumns = new ObservableCollection<SizeColumn>(sizeColumns);
ColumnCollection = new ObservableCollection<DataGridColumn>(columns);