使用动态列将行绑定到DataGrid

时间:2016-02-15 17:28:00

标签: c# wpf xaml

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

如:

  

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

我还没有找到一种方法来允许Binding的PropertyPath合作。

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

1 个答案:

答案 0 :(得分:0)

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

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