skip to Main Content

I have a Gridview with different items, ordered by the integer column "Order". I am saving the DataTable that feeds the Gridview as "Session Parameter".

Item        Order      LinkButtons
----------------------------------
Item1         1         up   down
Item2         2         up   down
Item3         3         up   down

The idea is to customize the order of the items by moving them up and down with the LinkButtons.

This is what I do:

  • I get the row index from the RowClick Event

    LinkButton lb = (sender as LinkButton);
    string OrderNr = lb.CommandArgument;
    int OrderNummer = Convert.ToInt16(OrderNr);
    GridViewRow row = (GridViewRow)lb.NamingContainer;
    int idx = row.RowIndex;
    
  • Call the Session table and change the Order Parameter

    DataTable t = Session["SessionData"] as DataTable;
    t.Rows[idx][1] = Convert.ToString(OrderNummer - 1);
    t.Rows[idx-1][1] = Convert.ToString(OrderNummer);
    
  • I then reorder the DataTable and bind it back to the Grid

    t.DefaultView.Sort = "OderNr";
    t = t.DefaultView.ToTable();
    

This unfortunately works only on the first Operation. Afterwards what is returned from t.Rows[idx] is unpredictable to me as the Gridrow Row Index doesn’t match the DataTable Row index.

Very confusing

2

Answers


  1. Not influent in C#, code may need optimization/fine-tuning.

    aspx

    <asp:GridView ID="GridView1" runat="server">
        <Columns>
            <asp:TemplateField ShowHeader="false">
                <ItemTemplate>
                    <asp:LinkButton ID="Btn_UP" runat="server" Text="UP" CommandArgument='<%# Eval("Order") %>' OnCommand="Btn_UP_Command"></asp:LinkButton>
                    <asp:LinkButton ID="Btn_DN" runat="server" Text="Down" CommandArgument='<%# Eval("Order") %>' OnCommand="Btn_DN_Command"></asp:LinkButton>
                </ItemTemplate>
            </asp:TemplateField>
        </Columns>
    </asp:GridView>
    

    Page_Load

    if (!IsPostBack)
    {
        GridView1.DataSource = Get_DataTable();
        GridView1.DataBind();
    }
    

    Get_DataTable

    public DataTable Get_DataTable()
    {
        if (Session["dt"] == null)
        {
            DataTable dt = new DataTable();
            dt.Columns.Add("Item", typeof(string));
            dt.Columns.Add("Order", typeof(int));
            for (int i = 1; i <= 10; i++)
                dt.Rows.Add($"Item {i}", i);
            return dt;
        }
        else
            return (DataTable)Session["dt"];
    }
    

    Btn_UP_Command

    DataTable dt = Get_DataTable();
    int order = int.Parse(e.CommandArgument.ToString());
    if (order == 1)
        return;
    dt.Select($"Order={order}")[0]["Order"] = -1;
    dt.Select($"Order={order - 1}")[0]["Order"] = order;
    dt.Select("Order=-1")[0]["Order"] = order - 1;
    dt.DefaultView.Sort = "Order";
    Session["dt"] = dt.DefaultView.ToTable();
    GridView1.DataSource = dt;
    GridView1.DataBind();
    

    Btn_DN_Command

    DataTable dt = Get_DataTable();
    int order = int.Parse(e.CommandArgument.ToString());
    if (order == dt.Rows.Count)
        return;
    dt.Select($"Order={order}")[0]["Order"] = -1;
    dt.Select($"Order={order + 1}")[0]["Order"] = order;
    dt.Select("Order=-1")[0]["Order"] = order + 1;
    dt.DefaultView.Sort = "Order";
    Session["dt"] = dt.DefaultView.ToTable();
    GridView1.DataSource = dt;
    GridView1.DataBind();
    
    Login or Signup to reply.
  2. The problem here is that you using "default" view for the grid binding.

    But default view DOES NOT change the row index of the base table!!!

    This results in 2 possible solutions:

    You consider using dataitem index from the GridView, and NOT row index.

    Or, simpler is to sort the base table.

    You can do this with this:

            rstData.DefaultView.Sort = "MyOrder";
            rstData = rstData.DefaultView.ToTable();
            Session["rstData"] = rstData;
    

    Note VERY close in above, we have to shove the rstData table BACK into session[], since we have re-built the table with .ToTable(), and that in effect is a new instance of the object.

    So, here is a working example (I have included the MyOrder column in this example). Also keep in mind, that rows are 0 based, and your example started with 1. For this example, "MyOrder" column starts at 0, and not one.

    So, say this markup:

    <asp:GridView ID="GVHotels" runat="server" AutoGenerateColumns="False"
        DataKeyNames="ID" CssClass="table" 
        Width="45%" >
        <Columns>
            <asp:BoundField DataField="FirstName" HeaderText="FirstName" />
            <asp:BoundField DataField="LastName" HeaderText="LastName" />
            <asp:BoundField DataField="City" HeaderText="City" />
            <asp:BoundField DataField="HotelName" HeaderText="HotelName" />
            <asp:BoundField DataField="Description" HeaderText="Description" />
            <asp:BoundField DataField="MyOrder" HeaderText="Order" />
            <asp:TemplateField>
                <ItemTemplate>
                    <asp:Button ID="cmdUp" runat="server" Text="UP"
                        OnClick="cmdUp_Click" CssClass="btn" />
                </ItemTemplate>
            </asp:TemplateField>
    
            <asp:TemplateField>
                <ItemTemplate>
                    <asp:Button ID="cmdDown" runat="server" Text="Down"
                        OnClick="cmdDown_Click" CssClass="btn" />
                </ItemTemplate>
            </asp:TemplateField>
        </Columns>
    </asp:GridView>
    

    And code behind:

        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                string strSQL = @"SELECT * FROM tblHotelsA
                            WHERE Active = 1";
    
                rstData = General.MyRst(strSQL);
                LoadGrid();
            }
            else
                rstData = (DataTable)Session["rstData"];
        }
    
        void LoadGrid()
        {
            rstData.DefaultView.Sort = "MyOrder";
            rstData = rstData.DefaultView.ToTable();
            Session["rstData"] = rstData;
            GVHotels.DataSource = rstData;
            GVHotels.DataBind();
    
        }
    
        protected void cmdUp_Click(object sender, EventArgs e)
        {
            Button btn = (Button)sender;
            GridViewRow gRow = (GridViewRow)btn.NamingContainer;
            int IX = gRow.RowIndex;            
            if (IX > 0)
            {
                rstData.Rows[IX]["MyOrder"] = IX - 1;
                rstData.Rows[IX - 1]["MyOrder"] = IX;
                LoadGrid();
            }
        }
    
        protected void cmdDown_Click(object sender, EventArgs e)
        {
            Button btn = (Button)sender;
            GridViewRow gRow = (GridViewRow)btn.NamingContainer;
            int IX = gRow.RowIndex;
            if (IX < rstData.Rows.Count - 1)
            {
                rstData.Rows[IX]["MyOrder"] = IX + 1;
                rstData.Rows[IX + 1]["MyOrder"] = IX;
                LoadGrid();
            }
        }
    

    The result is this:

    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search