Расширенный GridView с функцией вставки - Косметические улучшения

ОГЛАВЛЕНИЕ

Косметические улучшения

Сводка результатов

GridView часто применяется для отображения результатов поиска, а значит, в текстовые управляющие элементы всегда вставляются фразы типа "Результаты 1-10 из 50", которые надо всегда не забывать показывать и прятать, что скучно. Вот почему была добавлена "строка сводки", отображающая эту информацию автоматически. Сводка вставляет прямо над заголовком, но ее можно переместить в любое нужное вам место.

/// <span class="code-SummaryComment"><summary></span>
/// Отображает содержимое управляющего элемента.
/// <span class="code-SummaryComment"></summary></span>
/// <span class="code-SummaryComment"><param name="writer"> <see cref="HtmlTextWriter"/> Для записи куда-либо.</param></span>
protected override void RenderContents(HtmlTextWriter writer)
{
    if (this.ShowResultSummary && this.PageCount != 0)
    {
        // Создать управляющие элементы сводки
        int firstResultIndex = this.PageIndex * this.PageSize;
        HtmlGenericControl topSummaryControl = new HtmlGenericControl("div");
        topSummaryControl.Style.Add("float", "left");
        topSummaryControl.InnerHtml = string.Format("<b>Records:</b> {0} to {1} of {2}",
            firstResultIndex + 1, firstResultIndex +
            this.Rows.Count, this.DataSourceCount);
        HtmlGenericControl bottomSummaryControl = new HtmlGenericControl("div");
        bottomSummaryControl.Style.Add("float", "left");
        bottomSummaryControl.InnerHtml = topSummaryControl.InnerHtml;

        if (this.PageCount == 1)
        {
            // Добавить сводку к таблице сверху
            this.Controls[0].Controls.AddAt(0, this.CreateSummaryRow(topSummaryControl));
            // Добавить сводку к таблице снизу
            this.Controls[0].Controls.Add(this.CreateSummaryRow(bottomSummaryControl));
        }
        else
        {
            // Добавить управляющий элемент сводки к верхнему блоку листания
            if (this.TopPagerRow != null)
                this.TopPagerRow.Cells[0].Controls.Add(topSummaryControl);
            // Добавить управляющий элемент сводки к нижнему блоку листания
            if (this.BottomPagerRow!= null)
                this.BottomPagerRow.Cells[0].Controls.Add(bottomSummaryControl);
        }
    }

    base.RenderContents(writer);
}

private TableRow CreateSummaryRow(Control summaryControl)
{
    TableRow summaryRow = new TableRow();
    TableCell summaryCell = new TableCell();
    summaryCell.ColumnSpan = this.HeaderRow.Cells.Count;
    summaryRow.Cells.Add(summaryCell);
    summaryCell.Controls.Add(summaryControl);
    return summaryRow;
}

private int _dataSourceCount;

/// <span class="code-SummaryComment"><summary></span>
/// Должна ли показываться сводка результатов.
/// <span class="code-SummaryComment"></summary></span>
[DefaultValue(false)]
[Category("Appearance")]
[Description("Whether the results summary should be shown.")]
public bool ShowResultSummary
{
    get
    {
        if (this.ViewState["ShowResultSummary"] == null)
            return false;
        else
            return (bool)this.ViewState["ShowResultSummary"];
    }
    set { this.ViewState["ShowResultSummary"] = value; }
}

/// <span class="code-SummaryComment"><summary></span>
/// Общее число строк в источнике данных.
/// <span class="code-SummaryComment"></summary></span>
public int DataSourceCount
{
    get
    {
        if (this.Rows.Count == 0)
            return 0;
        else if (this.AllowPaging)
            return this._dataSourceCount;
        else
            return this.Rows.Count;
    }
}

Пара свойств позволяет включать и выключать строку сводки по желанию и дает возможность добыть общее число записей в источнике данных, связанном с GridView, отсутствие которого всегда злило в прошлом. Значение берется из метода InitializePager (опущенного здесь, но имеющегося в демонстрационном проекте), являющегося крайне полезным методом, достойным отдельной статьи.

Индикаторы сортировки

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

/// <span class="code-SummaryComment"><summary></span>
/// Инициализирует строку в сетке.
/// <span class="code-SummaryComment"></summary></span>
/// <span class="code-SummaryComment"><param name="row">Строка для инициализации.</param></span>
/// <span class="code-SummaryComment"><param name="fields">Поля, с которыми инициализируется строка.</param></span>
protected override void InitializeRow(GridViewRow row, DataControlField[] fields)
{
    base.InitializeRow(row, fields);

    if (row.RowType == DataControlRowType.Header && this.AscendingImageUrl != null)
    {
        for (int i = 0; i < fields.Length; i++)
        {
            if (this.SortExpression.Length > 0 && fields[i].SortExpression ==
                    this.SortExpression)
            {
                // Добавить индикатор сортировки
                Image sortIndicator = new Image();
                sortIndicator.ImageUrl =
                    this.SortDirection == SortDirection.Ascending ?
                    this.AscendingImageUrl : this.DescendingImageUrl;
                sortIndicator.Style.Add(HtmlTextWriterStyle.VerticalAlign, "TextTop");
                row.Cells[i].Controls.Add(sortIndicator);
                break;
            }
        }
    }
}

/// <span class="code-SummaryComment"><summary></span>
/// Изображение, отображаемое, если <span class="code-SummaryComment"><see cref="SortDirection"/> является возрастающий.</span>
/// <span class="code-SummaryComment"></summary></span>
[Editor(typeof(ImageUrlEditor), typeof(UITypeEditor))]
[Description("Image that is displayed when SortDirection is ascending.")]
[Category("Appearance")]
public string AscendingImageUrl
{
    get { return this.ViewState["AscendingImageUrl"] as string; }
    set { this.ViewState["AscendingImageUrl"] = value; }
}

/// <span class="code-SummaryComment"><summary></span>
/// Изображение, отображаемое, если <span class="code-SummaryComment"><see cref="SortDirection"/> является убывающий.</span>
/// <span class="code-SummaryComment"></summary></span>
[Editor(typeof(ImageUrlEditor), typeof(UITypeEditor))]
[Description("Image that is displayed when SortDirection is descending.")]
[Category("Appearance")]
public string DescendingImageUrl
{
    get { return this.ViewState["DescendingImageUrl"] as string; }
    set { this.ViewState["DescendingImageUrl"] = value; }
}

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