Silverlight, DataPager, RIA Services и интеллектуальный пейджинг - PullRequest
13 голосов
/ 18 февраля 2010

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

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

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

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

Мы приветствуем идеи, предложения, рекомендации и полезные советы.

Ответы [ 3 ]

11 голосов
/ 21 февраля 2010

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

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

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

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

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

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

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

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

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

Теперь для кода 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

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

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

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

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

Просто переместите DomainDataSource в вашу ViewModel! Готово! * * 1006

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

Внутри вашей 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, пока не увижу ваш комментарий!

0 голосов
/ 14 августа 2010

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

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

...