Реализация Telerik VirtualQueryableCollectionView с шаблоном MVVM - PullRequest
2 голосов
/ 22 июля 2011

У меня есть приложение, которое было реализовано с использованием элемента управления Telerik RadGridView и инфраструктуры Caliburn.Micro MVVM.Из-за некоторых проблем с производительностью мне пришлось реализовать Telerik VirtualQueryableCollectionView вместо используемой прямой привязки control-to-ObservableCollection.В исходном коде свойство ItemsSouce объекта RadGridView было связано со свойством «Цены» модели представления.Мне пришлось устранить эту привязку и это в выделенном коде:

public PricingView(PricingViewModel vm)
{
    InitializeComponent();

    var dataView = new VirtualQueryableCollectionView()
                         { LoadSize=20, VirtualItemCount = vm.Prices.Count };
    dataView.ItemsLoading += (sender, e) =>
        {
            var view = sender as VirtualQueryableCollectionView;
            if (dataView != null)
            {
                view.Load(e.StartIndex, vm.Prices.Skip(e.StartIndex).Take(e.ItemCount));
            }
        };
    this.PricesGridView.ItemsSource = dataView;
}

Поскольку этот код имеет дело только с конкретными функциями пользовательского интерфейса, а именно с реализацией представления, я рад, что этот код принадлежит квыделение кода, а не ViewModel, поскольку было бы отступлением от шаблона MVVM, чтобы поместить ссылку на VirtualQueryableCollectionView в ViewModel.Часть, которой я не доволен, передает ссылку на ViewModel в конструктор View.Есть ли хороший способ получить ссылку в коде без необходимости передавать ссылку в конструкторе?

Или есть лучший способ сделать все это?

Ответы [ 2 ]

3 голосов
/ 21 марта 2012

Мое приложение реализовано с помощью MVVM Light, в моем случае я использовал класс VirtualQueryableCollectionView во ViewModel вместо View.

Я так и сделал, потому что я думаю, что этот класс очень похож на ObservableCollection, хотя он не является частью базовых классов. На самом деле, VirtualQueryableCollectionView не ограничивается элементами управления Telerik, но многими другими стандартными элементами управления, такими как ListView.

Выборка в моем случае реализована в модели.

void MainViewModel()
{
    this.Traces = new VirtualQueryableCollectionView<MyEntityClass>()
    {
        // ViewModel also manages the LoadSize
        LoadSize = this.PageSize,
        VirtualItemCount = myModel.TotalCount
    };
    this.Traces.ItemsLoading += (s, args) =>
    {
        this.Traces.Load(args.StartIndex, 
                         myModel.FetchRange(args.StartIndex, args.ItemCount));
    };
}
0 голосов
/ 23 июля 2011

Не уверен, что означают «проблемы с производительностью», но я собираюсь предположить, что это означает, что когда вы заполняете коллекцию из потока пользовательского интерфейса, она блокирует приложение достаточно долго, и кажется, что он не отвечает.

Существует дваобщие решения для этого.Во-первых, просто заполните свою коллекцию из фонового потока.

Наивная реализация состоит в том, чтобы просто перенести загрузку в поток ThreadPool, а затем с помощью диспетчера распределить вызовы для добавления элементов в ObservableCollection в поток пользовательского интерфейса.

Более хороший подход (одинкоторый вообще не включает ViewModel) должен использовать асинхронные привязки. Вы настраиваете запасной вариант к некоторому значению, которое указывает загружаемому пользователю.Иногда (в зависимости от ситуации) вы можете использовать PriorityBinding для постепенного заполнения вашего пользовательского интерфейса.

Другими альтернативами являются предварительная загрузка и кэширование данных при отображении заставки .Они немного отличаются в WPF, это не похоже на старое «покажи эту форму, пока я работаю, а затем покажу основную форму» в режиме winforms.И, конечно же, всегда есть классическая нумерация данных.Его сложно кодировать, но эффективно.На самом деле, я должен сказать, что это сложно в пользовательском интерфейсе.Теперь легко в коде (database.Skip(pageNumber * pageSize).Take(pageSize)).

...