7

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

现在通常在 MVVM 中,您只需通过 XamDataGrid 中所需的列通过尽可能多的属性填充数据,后者只会自动生成它们。

显然,我不能只在运行时在我的 ViewModel 中创建属性,除非我对反射做了一些疯狂的事情。

我还能如何实现这一目标?

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

这种方法可以在不违反 MVVM 模式的情况下使用吗?谢谢

4

2 回答 2

5

您可以使用索引器:

在您的视图模型中:

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

MyVariableCollection:受保护的 SomeRowViewModel 视图模型;

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

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

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

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

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

希望能提供一些思考——关于这条路线的任何问题,请发表评论。


编辑一个额外的想法:我已经使用内容ComponentModel命名空间来生成一个自定义的TypeDescriptor. 它相当深入,但您可以使对象“看起来”具有附加或自定义属性。它比我在上面发布的索引器方法复杂得多,但如果你遇到困难,值得一看。

于 2010-08-06T17:48:36.187 回答
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 以类似的方式实现。

于 2010-08-17T20:10:21.230 回答