MVVM - 如何在运行时为xamdatagrid创建列?

时间:2010-08-06 16:57:40

标签: .net wpf mvvm xamdatagrid

我必须创建一个XamDataGrid,它显示时间范围x到y的动态数量的列。因此,我不知道用户会选择多少年来预先创建这些列。

现在通常在MVVM中,您只需通过XamDataGrid中需要Columns的多个Properties填充数据,后者只需自动生成它们。

显然我不能在运行时在我的ViewModel中创建属性,除非我用Reflection做了一些疯狂的事。

我还能做到这一点吗?

我应该只为数据网格创建未绑定的字段并通过代码填充它们吗?我同意在这个阶段我不需要双向绑定,因为网格只是只读...只是在大声思考。

这种方法是否可以在不违反MVVM模式的情况下进行? 感谢

2 个答案:

答案 0 :(得分:4)

您可以使用索引器:

在ViewModel中:

public MyVariableCollection RowData
{
    get { return new MyVariableCollection(this); }
}

MyVariableCollection中:     protected SomeRowViewModel viewModel;

public MyVariableCollection(SomeRowViewModel viewmodel)
{
    this.viewModel = viewmodel;
}

public object this[string name]
{
    get { return viewModel.GetRowColumnValue(name); }
}

我试图保持简短:但是想法是,你有一个定义了索引器的新类,那么你可以像这样绑定:

{Binding Path=SomeRowViewModelInstance.RowData["ColumnName"]}

数据网格控件上的列集合将被绑定 - 您可以为每个列设置一个列模板以绑定到相关列;你不需要在索引器中使用像这样的文字字符串。

希望提供一些思考的东西 - 有关此路线的任何问题请发表评论。


编辑以获得额外的想法:我使用了内容ComponentModel命名空间来生成自定义TypeDescriptor。它相当深入,但您可以使对象“显示”以具有其他或自定义属性。它比我上面发布的索引器方法复杂得多,但是如果你卡住它就值得一看。

答案 1 :(得分:1)

我遇到了类似的问题,因为用户可以在运行时定义网格的列。

我编写了一个包含xam数据网格的控件,并公开了一个DataSource依赖项属性来绑定网格的模型(即数据表)。

每次源更改(您可以为PropertyChanged添加事件侦听器和网格FieldLayoutInitializing事件)时,通过清除其数据源并重置它来动态重新呈现网格:

private void ReRenderGrid()
{
    XamDataGrid.FieldLayouts.Clear();
    XamDataGrid.ClearValue(DataPresenterBase.DataSourceProperty);
    XamDataGrid.DataSource = DataSource.Data.DefaultView;
}

在重置网格数据源之后,由xamdatagrid引发的以下事件的事件处理程序重新配置列:

XamDataGrid.FieldLayoutInitializing += LayoutInitializing;

处理程序:

private void LayoutInitializing(object sender, FieldLayoutInitializingEventArgs e)
{
    const string deletebuttonstyle = "DeleteButtonStyle";
    const string requiredinputvalue = "RequiredInputValue";
    const string optionalinputvalue = "OptionalInputValue";
    const string outputvalue = "OutputValue";

    var fieldLayout = e.FieldLayout;
    fieldLayout.Fields.Clear();

    AddFields(DataSource.InColumns, requiredinputvalue, fieldLayout);
    AddSplitter(fieldLayout);
    AddFields(DataSource.OptionalInColumns, optionalinputvalue, fieldLayout);
    AddSplitter(fieldLayout);
    AddFields(DataSource.OutColumns, outputvalue, fieldLayout);

    AddUnboundField(fieldLayout, string.Empty, GetStyle(deletebuttonstyle));
}

在我的例子中,数据源包含用户配置的所有列。 AddFields为每个列表条目调用此方法:

private void AddField(string name, Style style, FieldLayout fieldLayout)
{
    var field = new Field {Name = name};
    field.Settings.LabelPresenterStyle = style;
    field.Settings.CellValuePresenterStyle = GetStyle("StandardCellValueStyle");
    fieldLayout.Fields.Add(field);
}

AddSplitter和AddUnboundField以类似的方式实现。