GridView bound DataTable - how to get updates working?

Discussion in 'ASP .Net' started by Tomasz Jastrzebski, Dec 4, 2006.

  1. Hello Everyone,



    I have a GridView control bound to a plain DataTable object.

    AutoGenerateEditButton is set to true, Edit button gets displayed, and
    RowEditing event fires as expected.



    What do I need to change so that GridView control displays textboxes while
    editing and Edit button changes to Cancel button?

    What do I need to do to be able to select a row? Setting
    AutoGenerateSelectButton to true and defining <SelectedRowStyle> template
    does not seem to be sufficient in this scenario.



    Thank you,



    Tomasz
    Tomasz Jastrzebski, Dec 4, 2006
    #1
    1. Advertising

  2. Hi Tomasz,

    Whatever data source object you bind to a control, a data source view
    object is created. A data source view object is a class that can perform
    SELECT, INSERT, DELETE, and UPDATE operations on a bound object.

    If you're binding the GridView to a SqlDataSource or an ObjectDataSource
    which incorporates data source view object that fully supports these 4
    operations, the GridView will automatically enable editing the data, for
    example:

    <asp:GridView ID="GridView1" runat="server"
    AutoGenerateColumns="False" DataKeyNames="ProductID"
    DataSourceID="SqlDataSource1">
    <Columns>
    <asp:CommandField ShowEditButton="true" />
    <asp:BoundField DataField="ProductID"
    HeaderText="ProductID" InsertVisible="False"
    ReadOnly="True" SortExpression="ProductID" />
    <asp:BoundField DataField="ProductName"
    HeaderText="ProductName" SortExpression="ProductName" />
    </Columns>
    </asp:GridView>
    <asp:SqlDataSource ID="SqlDataSource1" runat="server"
    ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
    SelectCommand="SELECT [ProductID], [ProductName] FROM
    [Alphabetical list of products]"
    UpdateCommand="Update [Alphabetical list of products] Set
    [ProductName]=@ProductName Where [ProductID]=@ProductID"
    >

    </asp:SqlDataSource>


    However, when you're directly binding to a DataTable which doesn't have a
    data source view object, it will be wrapped in a dynamically created data
    source view object of type ReadOnlyDataSource--an internal undocumented
    class. In such scenario, the automatic editing feature is not possible. You
    will have to use template column to setup the editing template and handle
    the updating yourself.

    Here's a short example on how to do that manually:

    <asp:GridView AutoGenerateColumns="false" ID="GridView1"
    runat="server" OnRowCancelingEdit="GridView1_RowCancelingEdit"
    OnRowEditing="GridView1_RowEditing" OnRowUpdating="GridView1_RowUpdating">
    <Columns>
    <asp:CommandField ShowEditButton="true" />
    <asp:BoundField HeaderText="ID" DataField="ID"
    ReadOnly="true" />
    <asp:TemplateField HeaderText="Name">
    <ItemTemplate>
    <asp:Label ID="lblName" runat="server" Text='<%#
    Eval("Name") %>'></asp:Label>
    </ItemTemplate>
    <EditItemTemplate>
    <asp:TextBox ID="txtName" runat="server" Text='<%#
    Bind("Name") %>'></asp:TextBox>
    </EditItemTemplate>
    </asp:TemplateField>
    </Columns>
    </asp:GridView>


    protected void Page_Load(object sender, EventArgs e)
    {
    if (!IsPostBack)
    {
    BindGrid();
    }
    }

    private void BindGrid()
    {
    GridView1.DataSource = GetDataSource();
    GridView1.DataBind();
    }

    protected DataTable GetDataSource()
    {
    const string key = "MyDataSource";
    DataTable dt = Session[key] as DataTable;
    if (dt == null)
    {
    dt = new DataTable();
    dt.Columns.Add("ID", typeof(int));
    dt.Columns.Add("Name", typeof(string));
    dt.Rows.Add(1, "first object");
    dt.Rows.Add(2, "second object");
    Session[key] = dt;
    }
    return dt;
    }
    protected void GridView1_RowEditing(object sender,
    GridViewEditEventArgs e)
    {
    GridView1.EditIndex = e.NewEditIndex;
    BindGrid();
    }
    protected void GridView1_RowCancelingEdit(object sender,
    GridViewCancelEditEventArgs e)
    {
    GridView1.EditIndex = -1;
    BindGrid();
    }
    protected void GridView1_RowUpdating(object sender,
    GridViewUpdateEventArgs e)
    {
    int id = int.Parse(GridView1.Rows[e.RowIndex].Cells[1].Text);
    TextBox txtName =
    GridView1.Rows[e.RowIndex].Cells[2].FindControl("txtName") as TextBox;
    string newname = txtName.Text;

    DataTable dt = GetDataSource();
    DataRow[] rows = dt.Select("ID = " + id.ToString());
    rows[0]["Name"] = newname;
    GridView1.EditIndex = -1;
    BindGrid();
    }


    You can find more information here:

    #Working with GridView without using Data Source Controls
    http://www.dotnetbips.com/articles/displayarticle.aspx?id=511

    Let me know if you need further information. Thanks.


    Sincerely,
    Walter Wang (, remove 'online.')
    Microsoft Online Community Support

    ==================================================
    Get notification to my posts through email? Please refer to
    http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
    ications. If you are using Outlook Express, please make sure you clear the
    check box "Tools/Options/Read: Get 300 headers at a time" to see your reply
    promptly.

    Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
    where an initial response from the community or a Microsoft Support
    Engineer within 1 business day is acceptable. Please note that each follow
    up response may take approximately 2 business days as the support
    professional working with you may need further investigation to reach the
    most efficient resolution. The offering is not appropriate for situations
    that require urgent, real-time or phone-based interactions or complex
    project analysis and dump analysis issues. Issues of this nature are best
    handled working with a dedicated Microsoft Support Engineer by contacting
    Microsoft Customer Support Services (CSS) at
    http://msdn.microsoft.com/subscriptions/support/default.aspx.
    ==================================================

    This posting is provided "AS IS" with no warranties, and confers no rights.
    Walter Wang [MSFT], Dec 5, 2006
    #2
    1. Advertising

  3. Thank you Walter, I appreciate your helpful response.
    Do you also, by a chance, know how to make DetailsView bound to a DataTable
    work?

    Tomasz


    "Walter Wang [MSFT]" <> wrote in message
    news:...
    > Hi Tomasz,
    >
    > Whatever data source object you bind to a control, a data source view
    > object is created. A data source view object is a class that can perform
    > SELECT, INSERT, DELETE, and UPDATE operations on a bound object.
    >
    > If you're binding the GridView to a SqlDataSource or an ObjectDataSource
    > which incorporates data source view object that fully supports these 4
    > operations, the GridView will automatically enable editing the data, for
    > example:
    >
    > <asp:GridView ID="GridView1" runat="server"
    > AutoGenerateColumns="False" DataKeyNames="ProductID"
    > DataSourceID="SqlDataSource1">
    > <Columns>
    > <asp:CommandField ShowEditButton="true" />
    > <asp:BoundField DataField="ProductID"
    > HeaderText="ProductID" InsertVisible="False"
    > ReadOnly="True" SortExpression="ProductID" />
    > <asp:BoundField DataField="ProductName"
    > HeaderText="ProductName" SortExpression="ProductName" />
    > </Columns>
    > </asp:GridView>
    > <asp:SqlDataSource ID="SqlDataSource1" runat="server"
    > ConnectionString="<%$ ConnectionStrings:NorthwindConnectionString %>"
    > SelectCommand="SELECT [ProductID], [ProductName] FROM
    > [Alphabetical list of products]"
    > UpdateCommand="Update [Alphabetical list of products] Set
    > [ProductName]=@ProductName Where [ProductID]=@ProductID"
    > >

    > </asp:SqlDataSource>
    >
    >
    > However, when you're directly binding to a DataTable which doesn't have a
    > data source view object, it will be wrapped in a dynamically created data
    > source view object of type ReadOnlyDataSource--an internal undocumented
    > class. In such scenario, the automatic editing feature is not possible.
    > You
    > will have to use template column to setup the editing template and handle
    > the updating yourself.
    >
    > Here's a short example on how to do that manually:
    >
    > <asp:GridView AutoGenerateColumns="false" ID="GridView1"
    > runat="server" OnRowCancelingEdit="GridView1_RowCancelingEdit"
    > OnRowEditing="GridView1_RowEditing" OnRowUpdating="GridView1_RowUpdating">
    > <Columns>
    > <asp:CommandField ShowEditButton="true" />
    > <asp:BoundField HeaderText="ID" DataField="ID"
    > ReadOnly="true" />
    > <asp:TemplateField HeaderText="Name">
    > <ItemTemplate>
    > <asp:Label ID="lblName" runat="server" Text='<%#
    > Eval("Name") %>'></asp:Label>
    > </ItemTemplate>
    > <EditItemTemplate>
    > <asp:TextBox ID="txtName" runat="server" Text='<%#
    > Bind("Name") %>'></asp:TextBox>
    > </EditItemTemplate>
    > </asp:TemplateField>
    > </Columns>
    > </asp:GridView>
    >
    >
    > protected void Page_Load(object sender, EventArgs e)
    > {
    > if (!IsPostBack)
    > {
    > BindGrid();
    > }
    > }
    >
    > private void BindGrid()
    > {
    > GridView1.DataSource = GetDataSource();
    > GridView1.DataBind();
    > }
    >
    > protected DataTable GetDataSource()
    > {
    > const string key = "MyDataSource";
    > DataTable dt = Session[key] as DataTable;
    > if (dt == null)
    > {
    > dt = new DataTable();
    > dt.Columns.Add("ID", typeof(int));
    > dt.Columns.Add("Name", typeof(string));
    > dt.Rows.Add(1, "first object");
    > dt.Rows.Add(2, "second object");
    > Session[key] = dt;
    > }
    > return dt;
    > }
    > protected void GridView1_RowEditing(object sender,
    > GridViewEditEventArgs e)
    > {
    > GridView1.EditIndex = e.NewEditIndex;
    > BindGrid();
    > }
    > protected void GridView1_RowCancelingEdit(object sender,
    > GridViewCancelEditEventArgs e)
    > {
    > GridView1.EditIndex = -1;
    > BindGrid();
    > }
    > protected void GridView1_RowUpdating(object sender,
    > GridViewUpdateEventArgs e)
    > {
    > int id = int.Parse(GridView1.Rows[e.RowIndex].Cells[1].Text);
    > TextBox txtName =
    > GridView1.Rows[e.RowIndex].Cells[2].FindControl("txtName") as TextBox;
    > string newname = txtName.Text;
    >
    > DataTable dt = GetDataSource();
    > DataRow[] rows = dt.Select("ID = " + id.ToString());
    > rows[0]["Name"] = newname;
    > GridView1.EditIndex = -1;
    > BindGrid();
    > }
    >
    >
    > You can find more information here:
    >
    > #Working with GridView without using Data Source Controls
    > http://www.dotnetbips.com/articles/displayarticle.aspx?id=511
    >
    > Let me know if you need further information. Thanks.
    >
    >
    > Sincerely,
    > Walter Wang (, remove 'online.')
    > Microsoft Online Community Support
    >
    > ==================================================
    > Get notification to my posts through email? Please refer to
    > http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
    > ications. If you are using Outlook Express, please make sure you clear the
    > check box "Tools/Options/Read: Get 300 headers at a time" to see your
    > reply
    > promptly.
    >
    > Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
    > where an initial response from the community or a Microsoft Support
    > Engineer within 1 business day is acceptable. Please note that each follow
    > up response may take approximately 2 business days as the support
    > professional working with you may need further investigation to reach the
    > most efficient resolution. The offering is not appropriate for situations
    > that require urgent, real-time or phone-based interactions or complex
    > project analysis and dump analysis issues. Issues of this nature are best
    > handled working with a dedicated Microsoft Support Engineer by contacting
    > Microsoft Customer Support Services (CSS) at
    > http://msdn.microsoft.com/subscriptions/support/default.aspx.
    > ==================================================
    >
    > This posting is provided "AS IS" with no warranties, and confers no
    > rights.
    >
    Tomasz Jastrzebski, Dec 6, 2006
    #3
  4. Hi Tomasz,

    It should be similar to above approach. Based on above example, we can
    create a DataView and apply the filter with selected row in GridView to
    update the data source that is binding to the DetailsView.

    Here's some example code:

    <asp:GridView DataKeyNames="ID" AutoGenerateColumns="false" ID="GridView1"
    runat="server"
    OnRowCancelingEdit="GridView1_RowCancelingEdit"
    OnRowEditing="GridView1_RowEditing"
    OnRowUpdating="GridView1_RowUpdating"
    OnSelectedIndexChanged="GridView1_SelectedIndexChanged">
    <Columns>
    <asp:CommandField ShowEditButton="true" ShowSelectButton="true" />
    <asp:BoundField HeaderText="ID" DataField="ID" ReadOnly="true" />
    <asp:TemplateField HeaderText="Name">
    <ItemTemplate>
    <asp:Label ID="lblName" runat="server" Text='<%#
    Eval("Name") %>'></asp:Label>
    </ItemTemplate>
    <EditItemTemplate>
    <asp:TextBox ID="txtName" runat="server" Text='<%#
    Bind("Name") %>'></asp:TextBox>
    </EditItemTemplate>
    </asp:TemplateField>
    </Columns>
    </asp:GridView>
    <asp:DetailsView AutoGenerateEditButton="true" AutoGenerateRows="false"
    ID="DetailsView1"
    runat="server" DataKeyNames="ID"
    OnModeChanging="DetailsView1_ModeChanging"
    OnItemUpdating="DetailsView1_ItemUpdating">
    <Fields>
    <asp:BoundField HeaderText="ID" DataField="ID" ReadOnly="true" />
    <asp:TemplateField HeaderText="Name">
    <ItemTemplate>
    <asp:Label ID="lblName" runat="server" Text='<%#
    Eval("Name") %>'></asp:Label>
    </ItemTemplate>
    <EditItemTemplate>
    <asp:TextBox ID="txtName" runat="server" Text='<%#
    Bind("Name") %>'></asp:TextBox>
    </EditItemTemplate>
    </asp:TemplateField>
    </Fields>
    </asp:DetailsView>





    protected void Page_Load(object sender, EventArgs e)
    {
    if (!IsPostBack)
    {
    BindGrid();
    }
    }

    private void BindGrid()
    {
    GridView1.DataSource = GetDataSource();
    GridView1.DataBind();
    }

    protected DataTable GetDataSource()
    {
    const string key = "MyDataSource";
    DataTable dt = Session[key] as DataTable;
    if (dt == null)
    {
    dt = new DataTable();
    dt.Columns.Add("ID", typeof(int));
    dt.Columns.Add("Name", typeof(string));
    dt.Rows.Add(1, "first object");
    dt.Rows.Add(2, "second object");
    Session[key] = dt;
    }
    return dt;
    }
    protected void GridView1_RowEditing(object sender, GridViewEditEventArgs e)
    {
    GridView1.EditIndex = e.NewEditIndex;
    BindGrid();
    }
    protected void GridView1_RowCancelingEdit(object sender,
    GridViewCancelEditEventArgs e)
    {
    GridView1.EditIndex = -1;
    BindGrid();
    }
    protected void GridView1_RowUpdating(object sender, GridViewUpdateEventArgs
    e)
    {
    int id = int.Parse(GridView1.Rows[e.RowIndex].Cells[1].Text);
    TextBox txtName =
    GridView1.Rows[e.RowIndex].Cells[2].FindControl("txtName") as TextBox;
    string newname = txtName.Text;

    FindRowsByID(id)[0]["Name"] = newname;
    GridView1.EditIndex = -1;
    BindGrid();
    }

    private DataRow[] FindRowsByID(int id)
    {
    DataRow[] rows = GetDataSource().Select("ID = " + id.ToString());
    return rows;
    }

    private DataView CreateDataViewByID(int id)
    {
    DataView dv = new DataView(GetDataSource());
    dv.RowFilter = "ID = " + id.ToString();
    return dv;
    }

    protected void GridView1_SelectedIndexChanged(object sender, EventArgs e)
    {
    BindDetailsView();
    }

    private void BindDetailsView()
    {
    int id = (int)GridView1.SelectedValue;
    DetailsView1.DataSource = CreateDataViewByID(id);
    DetailsView1.DataBind();
    }

    protected void DetailsView1_ModeChanging(object sender,
    DetailsViewModeEventArgs e)
    {
    DetailsView1.ChangeMode(e.NewMode);
    BindDetailsView();
    }

    protected void DetailsView1_ItemUpdating(object sender,
    DetailsViewUpdateEventArgs e)
    {
    int id = (int)DetailsView1.DataKey[0];
    TextBox txtName = DetailsView1.FindControl("txtName") as TextBox;
    string newname = txtName.Text;
    FindRowsByID(id)[0]["Name"] = newname;
    BindGrid();
    DetailsView1.ChangeMode(DetailsViewMode.ReadOnly);
    BindDetailsView();
    }



    Regards,
    Walter Wang (, remove 'online.')
    Microsoft Online Community Support

    ==================================================
    When responding to posts, please "Reply to Group" via your newsreader so
    that others may learn and benefit from your issue.
    ==================================================

    This posting is provided "AS IS" with no warranties, and confers no rights.
    Walter Wang [MSFT], Dec 6, 2006
    #4
  5. Hi Tomasz,

    This is just a quick note to check the status of this post. What do you
    think of above solution on DetailsView? Please feel free to reply here if
    there's anything I can help.

    Regards,
    Walter Wang (, remove 'online.')
    Microsoft Online Community Support

    ==================================================
    When responding to posts, please "Reply to Group" via your newsreader so
    that others may learn and benefit from your issue.
    ==================================================

    This posting is provided "AS IS" with no warranties, and confers no rights.
    Walter Wang [MSFT], Dec 8, 2006
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. sunil panda

    Lower bound & Upper bound

    sunil panda, Dec 25, 2003, in forum: Java
    Replies:
    9
    Views:
    7,240
    thushara wijeratna
    Oct 7, 2008
  2. Elmo Watson
    Replies:
    0
    Views:
    2,758
    Elmo Watson
    Aug 17, 2006
  3. Replies:
    2
    Views:
    925
  4. Replies:
    2
    Views:
    716
  5. Mel
    Replies:
    0
    Views:
    304
Loading...

Share This Page