Как добавить дополнительную строку (содержащую кнопку и соответствующий обработчик события) в GridView - PullRequest
1 голос
/ 03 марта 2012

Это должно быть то, что сделали многие люди. По сути, это пользовательский GridView (то есть унаследованный элемент управления) с возможностью обновления всех строк одновременно. Я пытался поместить кнопку «обновить все» в разных местах (нижний колонтитул, пейджер, за пределами сетки), но она выглядит лучше всего (для меня), когда кнопка находится в дополнительном ряду в качестве последней строки GridView.

Примечание: строка пейджера не подходит для этой кнопки, поскольку этот пользовательский элемент управления может использоваться в ситуации, когда подкачка имеет значение false. Точно так же нормальный нижний колонтитул может потребоваться для некоторых других целей (например, итогов).

Вот мой код для размещения кнопки в правильном месте (с извинениями за краткие переменные и т. Д.):

    protected override void OnPreRender(EventArgs e)
    {
        base.OnPreRender(e);
        //Add an extra row to the table...
        if (_updateAllEnabled)
        {
          GridViewRow r = base.CreateRow(-1, -1, DataControlRowType.Footer, DataControlRowState.Normal);
          Button btn = new Button();
          TableCell c = new TableCell();
          btn.ID = "UpdateAllButton";    // tried with and without this line
          btn.Text = "Update All";
          btn.Click += new EventHandler(UpdateAll);
          r.Cells.Add(c);
          c.Controls.Add(btn);
          Table t = this.Controls[0] as Table;
          c.ColumnSpan = this.Columns.Count;
          t.Rows.Add(r);           
      }
    }

Это создает видимость, которую я хочу, но событие щелчка (UpdateAll) не запускается.

Я предполагаю, что материал добавляется слишком поздно в жизненном цикле (PreRender), но где еще я могу сделать это, чтобы убедиться, что строка находится в конце GridView? Я также подумал, что могут быть проблемы с идентификацией кнопки, поэтому я попытался установить идентификатор. В любом случае, идентификатор в сгенерированном HTML выглядит хорошо (в соответствии с «рабочими» кнопками в строке пейджера.

Есть ли способ для меня достичь этого или я пытаюсь сделать невозможное?

Ответы [ 2 ]

2 голосов
/ 03 марта 2012

Лучшее место для создания элементов управления нижнего колонтитула - RowCreated , так как это достаточно рано в жизненном цикле, а также гарантирует, что они воссоздаются при каждой обратной передаче:

Подход нижнего колонтитула :

protected void Grid_RowCreated(Object sender, GridViewRowEventArgs e) {
    if(e.Row.RowType == DataControlRowType.Footer) {
        Button btn = new Button();
        TableCell c = new TableCell();
        btn.ID = "UpdateAllButton";   
        btn.Text = "Update All";
        btn.Click += new EventHandler(UpdateAll);
        var firstCell=e.Row.Cells[0];
        firstCell.ColumnSpan =e.Row.Cells.Count;
        firstCell.Controls.Add(btn);
        while(e.Row.Cells.Count > 1)e.Row.Cells.RemoveAt(e.Row.Cells.Count-1);
    }
}

Конечно, вы должны установить ShowFooter на true:

<asp:GridView ID="GridView1" 
     ShowFooter="true" 
     OnRowCreated="Grid_RowCreated" 
     runat="server"
</asp:GridView>

Пейджинговый подход:

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

Здесь я использую пейджер для управления вашими костомами, добавляя еще TableRow к PagerTable, который наследуется от Table.

protected void Grid_RowCreated(Object sender, GridViewRowEventArgs e) {
    switch(e.Row.RowType){
        case DataControlRowType.Pager:
            Button btnUpdate = new Button();
            btnUpdate.ID = "UpdateButton";   
            btnUpdate.Text = "Update";
            btnUpdate.Click += new EventHandler(UpdateAll);
            var tblPager = (Table)e.Row.Cells[ 0 ].Controls[ 0 ];
            var row = new TableRow();
            var cell = new TableCell();
            cell.ColumnSpan = tblPager.Rows[ 0 ].Cells.Count;
            cell.Controls.Add(btnUpdate);
            row.Cells.Add(cell);
            tblPager.Rows.Add(row);
            break;
    }
}

Чтобы гарантировать, что пейджер виден, даже если отображается только одна страница (обратите внимание, что настоящий пейджер невидим, если PageSize==1):

protected void Grid_PreRender(object sender, EventArgs e){
    GridView gv = (GridView)sender;
    GridViewRow gvr = (GridViewRow)gv.BottomPagerRow;
    if(gvr != null) {
        gvr.Visible = true;
        var tblPager = (Table)gvr.Cells[ 0 ].Controls[ 0 ];
        //hide real pager if unnecessary
        tblPager.Rows[ 0 ].Visible = GridView1.PageCount > 1;
    }
}

Конечно, теперь вы должны установить AllowPaging=true:

<asp:GridView ID="GridView1" 
   AllowPaging="true" 
   PagerSettings-Mode="NumericFirstLast" 
   OnRowCreated="Grid_RowCreated"  
   OnPreRender="Grid_PreRender"
   OnPageIndexChanging="Grid_PageChanging"
   runat="server">
</asp:GridView>

Окончательный подход (работает для пользовательского GridView и всех PagerPositions):

public PagerPosition OriginalPagerPosition{
    get { return (PagerPosition)ViewState[ "OriginalPagerPosition" ]; }
    set { ViewState[ "OriginalPagerPosition" ] = value; }
}

protected void Page_Load(object sender, EventArgs e){
    if(!IsPostBack) OriginalPagerPosition = GridView1.PagerSettings.Position;
    GridView1.PagerSettings.Position = PagerPosition.TopAndBottom;
    GridView1.AllowPaging = true;

    // databinding stuff ...
}

Оставьте RowCreated таким же, как указано выше в Пейджер .

Видимость верхнего / нижнего пейджеров будет контролироваться в PreRender в соответствии со свойством OriginalPagerPosition. Оба пейджера созданы даже с PagerPosition=TOP, нижний пейджер необходим для вашего дополнительного контроля (ов):

protected void Grid_PreRender(object sender, EventArgs e)
{
    GridView gv = (GridView)sender;
    GridViewRow tpr = (GridViewRow)gv.TopPagerRow;
    GridViewRow bpr = (GridViewRow)gv.BottomPagerRow;
    tpr.Visible = gv.PageCount > 1 && (OriginalPagerPosition == PagerPosition.Top || OriginalPagerPosition == PagerPosition.TopAndBottom);
    bpr.Visible = true;
    var tblBottomPager = (Table)bpr.Cells[ 0 ].Controls[ 0 ];
    tblBottomPager.Rows[ 0 ].Visible = gv.PageCount > 1 && (OriginalPagerPosition == PagerPosition.Bottom || OriginalPagerPosition == PagerPosition.TopAndBottom);
    var tblTopPager = (Table)tpr.Cells[ 0 ].Controls[ 0 ];
    tblTopPager.Rows[1].Visible = false;
}

Примечание : если вы расширяете элемент управления GridView, вы должны заменить все вхождения GridView1 (моя тестовая сетка) на this.

1 голос
/ 05 марта 2012

Было бы легко добавить дополнительный ряд в сетку.Но сложность в вашем требовании состоит в том, что RowCollection GridView не должен содержать эту строку, так как она будет подвержена ошибкам.Это также должна быть самая последняя строка, даже если подкачка включена.Это (афаик) невозможно.

Поэтому я решил расширить пейджер этой функцией.

Я добавлю это как отдельный ответ, так как мой другой уже слишком подробен и описывает два разных способа (нижний колонтитул, пейджер)добавить элементы управления к GridView, не расширяя его.

Этот подход расширяет GridView, как в ваших собственных требованиях, и похож на мой другой пейджинговый подход.Но он чище и только добавляет дополнительный ряд к BottomPager.Он также работает для каждого параметра (AllowPaging = false, Pager-Position: Top, Bottom, BottomTop):

[DefaultProperty("EnableUpdateAll")]
[ToolboxData("<{0}:UpdateGridView runat=server></{0}:UpdateGridView>")]
public class UpdateGridView : GridView
{
    [Bindable(true)]
    [Category("Appearance")]
    [DefaultValue("true")]
    [Localizable(true)]
    public bool EnableUpdateAll
    {
        get
        {
            Object val = ViewState["EnableUpdateAll"];
            return ((val == null) ? true : (bool)val);
        }

        set
        {
            ViewState["EnableUpdateAll"] = value;
        }
    }

    private bool OriginalAllowPaging
    {
        get
        {
            Object val = ViewState["OriginalAllowPaging"];
            return (bool)val;
        }

        set
        {
            ViewState["OriginalAllowPaging"] = value;
        }
    }

    private PagerPosition OriginalPagerPosition
    {
        get
        {
            Object val = ViewState["OriginalPagerPosition"];
            return (PagerPosition)val;
        }

        set
        {
            ViewState["OriginalPagerPosition"] = value;
        }
    }

    protected override void OnInit(System.EventArgs e)
    {
        if (ViewState["OriginalPagerPosition"] == null)
            OriginalPagerPosition = base.PagerSettings.Position;
        if(OriginalPagerPosition != PagerPosition.Bottom)
            PagerSettings.Position=PagerPosition.TopAndBottom;
        if (ViewState["OriginalAllowPaging"] == null)
            OriginalAllowPaging = base.AllowPaging;
        base.AllowPaging = true;
    }

    protected override void OnRowCreated(GridViewRowEventArgs e)
    {
        switch (e.Row.RowType)
        {
            case DataControlRowType.Pager:
                //check if we are in BottomPager
                if (this.Rows.Count != 0 && this.EnableUpdateAll)
                {
                    Button btnUpdate = new Button();
                    btnUpdate.ID = "BtnUpdate";
                    btnUpdate.Text = "Update";
                    btnUpdate.Click += new EventHandler(UpdateAll);
                    var tblPager = (Table)e.Row.Cells[0].Controls[0];
                    var row = new TableRow();
                    var cell = new TableCell();
                    cell.ColumnSpan = tblPager.Rows[0].Cells.Count;
                    cell.Controls.Add(btnUpdate);
                    row.Cells.Add(cell);
                    tblPager.Rows.Add(row);
                }
                break;
        }
    }

    protected override void OnPreRender(EventArgs e)
    {
        bool bottomPagerVisible = 
            OriginalAllowPaging && 
            PageCount > 1 && 
            (OriginalPagerPosition == PagerPosition.Bottom || OriginalPagerPosition == PagerPosition.TopAndBottom);
        BottomPagerRow.Visible = bottomPagerVisible || EnableUpdateAll;
        var tblBottomPager = (Table)BottomPagerRow.Cells[0].Controls[0];
        tblBottomPager.Rows[0].Visible = bottomPagerVisible;
    }

    private void UpdateAll(Object sender, EventArgs e)
    {
        // do something...
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...