Сообщений 0    Оценка 0        Оценить  
Система Orphus

Элемент управления для выбора количества записей на странице

Автор: Черняев Константин
Опубликовано: 16.04.2013
Исправлено: 10.12.2016
Версия текста: 1.0
Серверный элемент управления CountChooser
Known bugs или что можно улучшить?
Исходный текст на GitHub

В сердце каждой трудности кроется возможность.
Альберт Эйнштейн

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

Причины делать такой выбор могут быть, например, такими:

При использовании платформы ASP.NET возможность выбора числа из набора легко реализовать с помощью элемента управления DropDownList, и это может выглядеть так:


Получается очень просто и проблем или недостатков в такой реализации на первый взгляд нет. Но при следующих дополнительных возможностях страница будет более user-friendly:

1. Если всего строк в таблице (на примере 756) не больше, чем максимально возможного количества элементов на странице (на примере 200), то скрыть лишние варианты, и вместо них показать «вывести все»:


Тут всего элементов – 23, поэтому варианты «50 на странице» и тем более «100 (200) на странице» лишние.

2. Если всего строк в таблице не больше, чем минимальный возможный выбор количества строк на странице (на примере 10), то выбор размера окна и не нужен – лучше скрыть этот выбор:


Тут всего элементов 7, а минимальный выбор на странице – 10, поэтому все выборы лишние.

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

Серверный элемент управления CountChooser

Реализовать описанное поведение удобно и несложно в новом серверном элементе управления (server control). Я назову его CountChooser. Нацелимся на то, чтобы в разметке страницы объявлять его так:

<ucc:CountChooser runat="server" ID="cc" Counts="10,20,200,500"Title="Количество пользователей на странице:" DefaultValue="20"
    AutoPostBack="True" OnSelectedIndexChanged="FilterChanged" />

Наследовать будем от DropDownList. Свойства AutoPostBack и OnSelectedIndexChanged – унаследованные, а остальные новые:

Заслуживает внимания код основного свойства:

      int[] _counts;
public string Counts
{
    set
    {
        _counts = value.Split(new[] {';'','}, StringSplitOptions
.RemoveEmptyEntries)
            .Select(s => s.Trim())
            .Where(s => !string.IsNullOrEmpty(s))
            .Select(int.Parse).ToArray();
    }
}

Свойство Title – тривиальное автосвойство, а DefaultValue – сохраняется во ViewState, чтобы была возможность его устанавливать программно с сохранением между postback’ами:

      public int DefaultValue
{
    get
    {
        object obj = ViewState["df"];
        return (obj == null) ? _counts.Min() : (int) obj;
    }
    set
    {
        ViewState["df"] = value;
        SelectedValue = value;
    }
}

Свойство SelectedValue переопределено как int с использованием DefaultValue:

      public new int SelectedValue
{
    get { return string.IsNullOrEmpty(base.SelectedValue) 
        ? DefaultValue : int.Parse(base.SelectedValue); }
    set { base.SelectedValue = value.ToString(); }
}

Обозначенные свойства на самом деле никак не расширяют функциональность исходного DropDownList. Чтобы достичь обозначенного расширения, нужно дополнительное поведение, дополнительный метод. Назовем его SetAsCount – он устанавливает видимость control-а или изменяет элементы выбора в зависимости от общего количества строк в таблице.

      public void SetAsCount(int cnt)
{
    this.Visible = cnt >= _counts.Min();
    if (!this.Visible) 
        return;
 
    int prevSelectedValue = SelectedValue;
 
    if (cnt <= _counts.Max())
    {
        int beginCut = _counts.Where(s => s >= cnt).Min();
        this.Items.Clear();
        this.Items.AddRange(_counts.Where(s => s < cnt)
            .Select(s => new ListItem(s.ToString(), s.ToString()))
            .Concat(new[] 
                {
                    new ListItem("вывести все", 
                        (prevSelectedValue < beginCut 
                            ? beginCut : prevSelectedValue).ToString())
                })
            .ToArray());
    }
    else
    {
        this.DataSource = _counts;
        this.DataBind();
    }
    SelectedValue = prevSelectedValue;
}

Функциональность CountChooser’а раскрывается в использовании метода SetAsCount, вызывать его удобно в методе веб-страницы, отвечающем за выборку количества элементов таблицы, например, так:

      public int SelectCount()
{
    int count = <get total count of elements>;
    labelFoundCount.Text = count.ToString();
    countChooser.SetAsCount(count);
    return count;
}

Этот метод в таком явном виде появляется при использовании ObjectDataSource, который удобно использовать для привязки данных к таблице, вот пример его объявления для постраничного вывода:

<asp:ObjectDataSource runat="server" ID="ods" TypeName="pagetypename" 
  OnObjectCreating="ods_ObjectCreating" OnObjectDisposing="ods_ObjectDisposing" 
  EnablePaging="True" 
    SelectMethod="Select" 
      MaximumRowsParameterName="count" SortParameterName="orderBy" 
      StartRowIndexParameterName="startIndex" 
    SelectCountMethod="SelectCount" />

Known bugs или что можно улучшить?

Исходный текст на GitHub

Исходник самого control-а лежит в github тут. Небольшой показательный пример проекта можно посмотреть здесь, а пример страницы, использующей CountChooserздесь aspx и здесь aspx.cs.


Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав.
    Сообщений 0    Оценка 0        Оценить