MVVM - Как создать столбцы во время выполнения для xamdatagrid? - PullRequest
6 голосов
/ 06 августа 2010

Мне нужно создать XamDataGrid, который показывает динамическое количество столбцов для периода времени от x до y. Поэтому я не знаю, сколько лет пользователь выбрал бы, чтобы эти столбцы создавались заранее.

Теперь обычно в MVVM вы просто заполняете данные через столько свойств, сколько вам нужно, чтобы столбцы в вашей XamDataGrid, а последний просто генерирует их.

Очевидно, что я не мог просто создать Свойства в моей ViewModel во время выполнения, если я не сошел с ума с Reflection.

Как еще мне этого добиться?

Должен ли я просто создать несвязанные поля для сетки данных и заполнить их с помощью кода? Я согласен, что на этом этапе мне не нужно двухстороннее связывание, поскольку сетка только для чтения ... просто мысли вслух.

Является ли этот подход нормальным, не нарушая шаблон MVVM? Спасибо

Ответы [ 2 ]

4 голосов
/ 06 августа 2010

Вы можете использовать индексаторы:

В вашей ViewModel:

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

В MyVariableCollection: защищенный 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 голос
/ 18 августа 2010

У меня была похожая проблема, потому что пользователь мог определять столбцы сетки во время выполнения.

Я написал элемент управления, содержащий сетку данных xam и выставив свойство зависимостей DataSource для привязки модели к сетке (то есть к таблице данных).

Каждый раз, когда источник менялся (вы можете добавить прослушиватели событий для PropertyChanged и события FieldLayoutInitializing сетки), сетка динамически перерисовывалась путем очистки источника данных и сброса:

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

Столбцы переконфигурируются обработчиком события для следующего события, которое вызывается xamdatagrid после сброса источника данных grid:

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 реализованы аналогичным образом.

...