Silverlight, DataPager, RIA Services и умная подкачка страниц

Я все еще пытаюсь получить ноги на земле с Silverlight and RIA Services и конечно запускаюсь с части более "забавного" материала как сетки и интеллектуальная подкачка страниц. Я могу соединиться с RIA Services (использующий ORM собственной разработки, не L2S или EF), получить данные по сетке и соединиться с DataPager. Доменный сервис работает хорошо с ORM собственной разработки, по крайней мере, для запросов. (Все еще работающий над полным CRUD.) Однако существуют все еще проблемы:

  1. Для поддержки пользовательского приложения мне нужны управляемая пользователями сортировка и фильтрация, в дополнение к умной подкачке страниц (только работает, запрос для строк должен был отобразиться), и группировка.

  2. До сих пор я ничего не видел в DataGrid или DataPager для воплощения этих возможностей так, чтобы фильтрация, сортируя, и параметры подкачки страниц могла быть передана серверу для создания соответствующего запроса.

  3. Наборы данных являются потенциально довольно большими; моя таблица, которую я выбрал для разработки прототипа работы, может иметь до 35 000 записей в некоторых клиентах, и я уверен, что существуют другие таблицы, намного больше, с которым я должен буду иметь дело в какой-то момент. Таким образом, "умная подкачка страниц" аспект важна.

Идеи, предложения, руководство и nerf кирпичи являются всем приветствием.

13
задан Cylon Cat 18 February 2010 в 12:59
поделиться

3 ответа

Хорошо, я провел несколько дней в сорняках с этим, и я думаю, что я справился с этим.

Во-первых, важное волшебство. Чтобы разбиение на страницы работало правильно, пейджер должен знать общее количество элементов, независимо от того, сколько элементов было возвращено текущим запросом. Если запрос возвращает все, количество элементов, очевидно, равно количеству возвращенных элементов. Для интеллектуального разбиения по страницам количество элементов по-прежнему является общим количеством доступных элементов, хотя запрос возвращает только то, что отображается. При фильтрации даже общее количество доступных элементов изменяется каждый раз при смене фильтра.

У элемента управления Silverlight Datapager есть свойство ItemCount. Он доступен только для чтения и не может быть привязан к данным в XAML или установлен непосредственно в коде. Однако, если пользовательский элемент управления, содержащий пейджер, имеет DataContext, который реализует IPagedCollectionView, тогда объект контекста данных должен реализовывать свойство ItemCount с уведомлением PropertyChanged, и DataPager, похоже, подбирает это автоматически.

Во-вторых, я настоятельно рекомендую Брэда Абрамса серию блогов о службах RIA , особенно эту, о ViewModel . Он содержит большую часть того, что вам нужно для работы с разбивкой по страницам и фильтрации, хотя в нем отсутствует важная часть по управлению количеством элементов. Его загружаемый образец также содержит очень хорошую базовую структуру для реализации ModelViewViewModel (MVVM). Спасибо, Брэд!

Итак, вот как заставить работать счетчик предметов. (Этот код относится к настраиваемому ORM, в то время как код Брэда использует Entity Framework; между ними вы можете понять, что вам нужно в вашей среде.)

Во-первых, ваша ORM должна поддерживать получение количества записей с фильтром и без него. Вот мой код службы домена, который делает счетчики доступными для служб RIA:

[Invoke]
public int GetExamCount()
{
    return Context.Exams.Count();
}

[Invoke]
public int GetFilteredExamCount(string descriptionFilter)
{
    return Context.Exams.GetFilteredCount(descriptionFilter);
}

Обратите внимание на атрибут [Invoke]. Это необходимо для любого метода DomainService, который не возвращает Entity или коллекцию Entity.

Теперь о коде ViewModel. Конечно, вам понадобится ItemCount. (Это из примера Брэда.)

    int itemCount;
    public int ItemCount
    {
        get { return itemCount; }
        set
        {
            if (itemCount != value)
            {
                itemCount = value;
                RaisePropertyChanged(ItemCountChangedEventArgs);
            }
        }
    }

Ваш метод LoadData выполнит запрос, чтобы получить текущий набор строк для отображения в DataGrid. (Здесь еще не реализована пользовательская сортировка, но это простое дополнение.)

    EntityQuery<ExamEntity> query = 
        DomainContext.GetPagedExamsQuery(PageSize * PageIndex, PageSize, DescriptionFilterText);
    DomainContext.Load(query, OnExamsLoaded, null);

Затем метод обратного вызова выполняет запрос для получения счетчиков. Если фильтр не используется, мы получаем счетчик для всех строк; если есть фильтр, мы получаем количество отфильтрованных строк.

private void OnExamsLoaded(LoadOperation<ExamEntity> loadOperation)
{
    if (loadOperation.Error != null)
    {
        //raise an event... 
        ErrorRaising(this, new ErrorEventArgs(loadOperation.Error));
    }
    else
    {
        Exams.MoveCurrentToFirst();
        if (string.IsNullOrEmpty(DescriptionFilterText))
        {
            DomainContext.GetExamCount(OnCountCompleted, null);
        }
        else
        {
            DomainContext.GetFilteredExamCount(DescriptionFilterText, OnCountCompleted, null);
        }
        IsLoading = false;
    }
}

Также существует метод обратного вызова для счетчиков:

void OnCountCompleted(InvokeOperation<int> op)
{
    ItemCount = op.Value;
    TotalItemCount = op.Value;
}

С установленным ItemCount элемент управления Datapager выбирает его, и у нас есть разбиение по страницам с фильтрацией и интеллектуальный запрос, который возвращает только отображаемые записи!

LINQ упрощает запрос с помощью .Skip () и .Take (). Сделать это с сырым ADO.NET сложнее. Я узнал, как это сделать, разобрав запрос, сгенерированный LINQ.

SELECT * FROM 
    (select ROW_NUMBER() OVER (ORDER BY Description) as rownum, * 
     FROM Exams as T0  WHERE T0.Description LIKE @description ) as T1 
WHERE T1.rownum between @first AND @last ORDER BY rownum

Предложение «выбрать ROW_NUMBER () OVER (ORDER BY Description) as rownum» является интересной частью, потому что еще не многие люди используют «OVER». Это предложение сортирует таблицу по описанию перед назначением номеров строк, и фильтр также применяется перед назначением номеров строк. Это позволяет внешнему оператору SELECT фильтровать номера строк после сортировки и фильтрации.

Итак, умная подкачка с фильтрацией в службах RIA и Silverlight!

11
ответ дан 2 December 2019 в 00:17
поделиться

Вот быстрое и грязное решение (которое я выбрал):

Просто переместите свой DomainDataSource в свою ViewModel! Сделанный!

Может быть, не совсем хорошо для тестируемости и, возможно, некоторых других ограничений, которые я еще не обнаружил, но лично меня это не волнует , пока не появится что-то получше .

Внутри модели ViewModel просто создайте экземпляр источника данных:

// Feedback DataSource
_dsFeedback = new DomainDataSource();
_dsFeedback.DomainContext = _razorSiteDomainContext;
_dsFeedback.QueryName = "GetOrderedFeedbacks";
_dsFeedback.PageSize = 10;
_dsFeedback.Load();

и укажите свойство, которое можно привязывать:

private DomainDataSource _dsFeedback { get; set; }
public DomainDataSource Feedback 
{
    get 
    {
        return _dsFeedback;
    }
}

И добавьте свой DataPager в свой XAML:

  <data:DataPager Grid.Row="1"
                  HorizontalAlignment="Stretch" 
                  Source="{Binding Feedback.Data}" 
                  Margin="0,0,0,5" />

  <data:DataGrid ItemsSource="{Binding Feedback.Data}">


PS. Спасибо «Франсуа» с указанной выше страницы. Я даже не догадывался, что могу извлечь DomainDataSource из XAML, пока не увидел ваш комментарий!

4
ответ дан 2 December 2019 в 00:17
поделиться

Это интересная статья от мая 2010 года о возможной будущей поддержке этого типа функций во фреймворке.

http://www.riaservicesblog.net/Blog/post/WCF-RIA-Services-Speculation-EntityCollectionView.aspx

0
ответ дан 2 December 2019 в 00:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: