Управление колонками таблиц в Silverlight: DataGrid (RadGridView, Columns, MVVM)

Просто о NET | создано: 22.09.2010 | опубликовано: 23.09.2010 | обновлено: 13.03.2024 | просмотров: 6377 | всего комментариев: 4

Совершенно недавно при разработки очередного проекта на Silverlight возникла некоторая проблема. В силу того, что проект пишется с использованием шаблона программирования под названием Model-View-ViewModel (MVVM), а компонент RadGridView не имеет DependencyProperty под названием ColumnCollection, пришлось искать простое и ,главное, быстрое решение данной проблемы.

Описание проблемы

Совершенно недавно при разработки очередного проекта на Silverlight возникла некоторая проблема. В силу того, что проект пишется с использованием шаблона программирования под названием Model-View-ViewModel (MVVM), а компонент RadGridView не имеет DependencyProperty под названием ColumnCollection, пришлось искать простое и ,главное, быстрое решение данной проблемы.

Входные данные

Есть компонент для Silverlight от компании Telerik, которые носит название RadGridView. Существует потребность при использовании MVVM генерировать колонки для таблицы программным способом. Ибо только при программной генерации колонок можно обработать метаданные с RIA-сервиса и наделить колонки необходимыми данными.

Описание способа решения

Самое простое и быстрое решение – это сделать AttachedProperty, которое и будет управлять колонками. Итак, создадим класс RadGridViewHelper, который будет содержать DependencyProperty под названием ColumnsCollectionProperty. А при изменении значения этого свойства ColumnsCollectionsChanged мы будем обновлять список колонок у объекта, к которому это свойство “приаттачено”:

private static void ColumnsCollectionsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    GridViewDataControl grid = d as GridViewDataControl;
    if (grid != null)
    {
        GridViewColumnCollection collection = (GridViewColumnCollection)e.NewValue;
        foreach (GridViewColumn item in collection)
        {
            grid.Columns.Add(item);
        }
    }
}

Отмечу только что GridViewDataControl – это как раз и есть RadGridView. Весь класс выглядит следующим образом:

/// <summary>
/// класс-помощник для RadGridView контрола.
/// </summary>
public class RadGridViewHelper
{
    /// <summary>
    /// Коллекция колонок для MVVM
    /// </summary>
    public static readonly DependencyProperty ColumnsCollectionProperty =
        DependencyProperty.RegisterAttached("ColumnsCollection",
        typeof(GridViewColumnCollection),
        typeof(RadGridViewHelper),
        new PropertyMetadata(ColumnsCollectionsChanged));


    private static void ColumnsCollectionsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        GridViewDataControl grid = d as GridViewDataControl;
        if (grid != null)
        {
            GridViewColumnCollection collection = (GridViewColumnCollection)e.NewValue;
            foreach (GridViewColumn item in collection)
            {
                grid.Columns.Add(item);
            }
        }
    }

    /// <summary>
    /// Установка свойства
    /// </summary>
    /// <param name="d">объект</param>
    /// <param name="columns">колонки</param>
    public static void SetColumnsCollection(DependencyObject d, GridViewColumnCollection columns)
    {
        d.SetValue(ColumnsCollectionProperty, columns);
    }

    /// <summary>
    /// Чтение свойтсва
    /// </summary>
    /// <param name="d">объект</param>
    /// <returns></returns>
    public static GridViewColumnCollection GetColumnsCollection(DependencyObject d)
    {
        return (GridViewColumnCollection)d.GetValue(ColumnsCollectionProperty);
    }
}

Теперь только и остается что использовать наш класс-помощник в XAML подключив нужное пространство имён:

<telerikGrid:RadGridView Grid.Row="1"
                                     SelectedItem="{Binding Path=SelectedItem, Mode=TwoWay}"
                                     ItemsSource="{Binding ElementName=Source, Path=Data}"
                                     grid:RadGridViewHelper.ColumnsCollection="{Binding Path=ColumnsCollection}"
                                     AutoGenerateColumns="False">

В нашем случаи пространство имён называется “grid”. Также необходимо отключить автоматическую генерацию колонок у таблицы, установив свойство AutoGenerateColumns в значение “False”. А свойство из MVVM, которое привязывается (биндится) Binding Path=ColumnsCollection вы глядит вот так:

#region свойство Columns
        /// <summary>
        /// скрытое поле для хранения коллекции полей для контрола.
        /// </summary>
        private GridViewColumnCollection gridViewColumnCollection;

        /// <summary>
        /// скрытая коллекция
        /// </summary>
        private ObservableCollection<Staff> stafflist;

        /// <summary>
        /// Колонки для таблицы
        /// </summary>
        public GridViewColumnCollection ColumnsCollection
        {
            get
            {
                if (gridViewColumnCollection == null)
                {
                    gridViewColumnCollection = new GridViewColumnCollection();
                    gridViewColumnCollection = new ColumnsGenerator(this.BridgeContext, typeof(Person)).ColumnsCollection;
                }
                return gridViewColumnCollection;
            }
        }

        #endregion

Примечание:
ColumnsGenerator  – это класс, который, собственно говоря, и делает обработку метаданных с RIA-сервиса и генерирует колонки для таблицы.
BridgeContext – это экземпляр класса DomainContext.

Поблагодарить

Хотите тоже получать донаты? Тогда заходите на boosty.to и регистрируйтесь!

Кстати, я использую хостинг reg.ru. Подключайся с промокодом 9A17-953A-8591-CF98.