[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 729
  • Last Modified:

Datagrid - OnItemCommand Question

Ok Experts here is another datagrid question..

Have a datagrid with 3 columns, 2 bound and 1 a button column.  When the user clicks the button column I want to grab the row data from the first 2 columns and perform an update to a db.  I have the following questions:

1. How do I get the data from the first 2 columns of the row where the button is pressed?
2. In order to trigger an OnItemCommand must the data grid be binded in the page_load?  If I bind the data in the page_load I can display a generic message to the screen when the button is pressed, however if I bind the data in the Page_PreRender the generic message is no longer displayed when the button is pressed.  (Just using the generic message for testing, eventually this is where the call to the db procedure would go...)  Reason why I had the dg bind in the prerender is because the datagrid values were dependent upon a value the user selected in a dropdownlist of the header which posts back to the current page.  If I keep the bind in the pageload the data is always 1 postback behind b/c as I understand it the page_load is executed prior to the dropdown_selectedIndexChange.

DataGrid:
<ASP:DataGrid id="MyDataGrid" runat="server"
    Width="855"
      OnItemCommand="dgrdItemCommand"
    BackColor="#cccccc"
    BorderColor="#FFFFFF"
    ShowFooter="false"
    CellPadding=3
    CellSpacing="0"
    Font-Name="Verdana" Height="16px" BorderWidth="2"
    Font-Size="11px"
    HeaderStyle-BackColor="#999999" HeaderStyle-Height="16px" HeaderStyle-Font-Size="11px"
    EnableViewState="false"
      HorizontalAlign="Center"
      AutoGenerateColumns="false"
>

<columns>
<asp:BoundColumn
      HeaderText="First Name"
      DataField="FirstName"
      HeaderStyle-Font-Bold="true"
      HeaderStyle-HorizontalAlign="Center"
      ItemStyle-HorizontalAlign="Center" />

<asp:BoundColumn
      HeaderText="Last Name"
      DataField="LastName"
      HeaderStyle-Font-Bold="true"
      HeaderStyle-HorizontalAlign="Center" />


<asp:ButtonColumn CommandName="Delete" Text ="<img border=0 src=../images/icons/trash-24.png>">
      <ItemStyle HorizontalAlign="Center"></ItemStyle>
</asp:ButtonColumn>

</columns>
</asp:DataGrid>

Button:
Sub dgrdItemCommand( s As Object, e As DataGridCommandEventArgs )
  'where I would get the 2 bound values & call the procedure

                If e.CommandName="Delete" Then
            lblOutput.Text = "You clicked one of the delete buttons!"
      Else
            lblOutput.Text = "Error"
      End If
               End Sub
0
egdigital
Asked:
egdigital
  • 2
  • 2
2 Solutions
 
KittrickCommented:
This was a good question, and I wanted to find out the answer to this by myself as well.  What I found was:

use a disconnected recordset (set rs.activeconnection = nothing)

Posted by emoreau at:
http://www.experts-exchange.com/Programming/Programming_Languages/Visual_Basic/Q_20279184.html?query=updating+more+than+one+row+in+a+datagrid&clearTAFilter=true

This following code was found at:
http://www.dotnet247.com/247reference/msgs/1/6342.aspx


VB.NET
----------

Dim objTable as Table
objTable = CType(dgCustomers.Controls(0),Table)
'Ignore Header Row and Footer Row
for i = 1 to objTables.Rows.Count - 2

'txtName declared as TextBox Server Control
'inside the Template Column within the DataGrid in the ASPX Page

txtName = (objTables.Rows(i).FindControl("txtName"),TextBox)
Write Update Code
--------------------
----------------------
Next

C#
-----

Table objTable;
objTable = (Table)(dgCustomers.Controls(0)
//Ignore Header Row and Footer Row
for(i=1;i<Count - 1;i++)
{
//txtName declared as TextBox Server Control inside
//the Template Column within the DataGrid in the ASPX Page
txtName = (TextBox)(objTables.Rows(i).FindControl("txtName");

Write Update Code
--------------------
----------------------
}


Hope this helps!
Kittrick
0
 
egdigitalAuthor Commented:
Thanks, Kittrick. Could you explain the disconnected recordset a little, in the code below (VB preferred) it looks as though I would be looping through all of the records that are in the table.  I don't understand how to use the disconnected recordset so I can identify the particular row where the button what pressed.
0
 
dfaithenCommented:
Hi,
 I think I can clear this up for you first a quick explanation. I will give a quick explaination and then code example. I am posting my sample in c# if you need me to help you translate it let me know. You basically want to follow these steps;
1. bind your grid with default data on page load if not page.IsPostBack
2. you do not need to bind in the pre render.
3. set your dropdown list to trigger a postback and in its SelectedIndexChanged event determine your data based on the user selection and then rebind the data to the datagrid.

That should help with #2.

as for #1 just refer to the cells text in the DataGridCommandEvent i.e. e.Item.Cells[0].Text

EXAMPLE:
================
                private void Page_Load(object sender, System.EventArgs e) {
                  if(!Page.IsPostBack) {
                        bindTableToSelectedData("goodGuy");
                  }
            }

            private void bindTableToSelectedData(string selected) {
                  switch(selected) {
                        case  "badguy":
                              MyDataGrid.DataSource = badGuyDataSouce;
                              break;
                        default: //goodguy
                              MyDataGrid.DataSource = goodGuyDataSouce;
                              break;
                  }
                  MyDataGrid.DataBind();
            }

            #region Web Form Designer generated code
            override protected void OnInit(EventArgs e)
            {
                  //
                  // CODEGEN: This call is required by the ASP.NET Web Form Designer.
                  //
                  InitializeComponent();
                  base.OnInit(e);
            }
            
            /// <summary>
            /// Required method for Designer support - do not modify
            /// the contents of this method with the code editor.
            /// </summary>
            private void InitializeComponent()
            {    
                  this.DropDownList1.SelectedIndexChanged += new System.EventHandler(this.DropDownList1_SelectedIndexChanged);
                  this.Load += new System.EventHandler(this.Page_Load);

            }
            #endregion

            protected void dgrdItemCommand( Object s, DataGridCommandEventArgs e) {
                  //where I would get the 2 bound values & call the procedure
                  if( e.CommandName=="Delete") {
                        string item1 = e.Item.Cells[0].Text;
                        string item2 = e.Item.Cells[1].Text;
                        lblOutput.Text = "You clicked to delete "+item1+" "+item2+"!";
                  }
                  else {
                        lblOutput.Text = "Error";
                  }
            }

            private void DropDownList1_SelectedIndexChanged(object sender, System.EventArgs e) {
                  bindTableToSelectedData(DropDownList1.SelectedValue);
            }

Hope it helps, let me know if you need furthur clarification.
Duane
0
 
dfaithenCommented:
By the way I added the init region so that you could see the wireup for the dropdownlist eventhandler. This is only if you wan the dropdown to trigger the event automatically. ( you also have to set AutoPostBack="True" in the control properties). If you want to handle this in a button click just refer to DropDownList1.SelectedValue to determine your data for binding.
Duane
0
 
KittrickCommented:
Hi again,
Paul Wilson gave a great explanation of disconnected recordsets at:
http://www.wilsondotnet.com/tips/ViewPosts.aspx?Thread=14

"ADO.NET can also create both connected or disconnected "recordsets". DataSets get the majority of the attention in ADO.NET -- think of these as disconnected recordsets. Windows client applications should usually be using the DataSet, and some other types of apps may also depending on what they need. DataReaders are the other type of "recordset" in ADO.NET -- think of these as connected recordsets. In particular, DataReaders are always "firehose" cursors, which means read-only and forward-only. I am not aware of any ways to get the other types of connected recordsets that were available in ADO, but this is by design since it is almost always a good thing. Most ASP.NET applications, or other server-based applications, should probably use DataReaders, although you must still make sure they get closed.

Note that I use DataReaders only on my sites, since they are efficient and meet my needs. DataSets are just another layer of overhead that are actually filled internally by a DataReader, so why use them if you don't need them. I use some page and data caching on my sites, but a good use of the DataSet on some ASP.NET sites would be for direct caching of the "recordset". Hopefully this makes some of the choices in ADO.NET more clear, but every situation is different so you should do more reading. By the way, your answer is that NO -- DataSets are disconnected and will not reflect data changes without doing some type of refresh. You can still have any updates that are pushed back check for changes and throw exceptions or otherwise handle any data changes. "

As for code, a simple example would be (I used a datalist, but you can change DataListCommandEventArgs to DataGridCommandEventArgs):

<<<<<<<<<<<<<START CODE-BEHIND>>>>>>>>>>>>>>
Public Sub OnUpdate(ByVal Source As Object,ByVal e As DataListCommandEventArgs)

'field1 is a number
Dim field1_ As String = CTYPE(e.Item.FindControl(" field1"),TextBox).Text
'field2 is text
Dim field2_ As String = CTYPE(e.Item.FindControl("field2"),TextBox).Text
'field3 is a date
Dim field3 As String = CTYPE(e.Item.FindControl("field3"),TextBox).Text
'unique_identifier is a number
Dim unique_identifier_ As String = CTYPE(e.Item.FindControl(" unique_identifier"),TextBox).Text


'opening connection
Dim oleConn As New OleDB.oleDbConnection()
'setting the path to the database
oleConn.ConnectionString="Provider=Microsoft.Jet.OLEDB.4.0;data source=" & server.mappath("\path\toyourDB")
'setting new command object
Dim oleComm AS NEW OleDb.oleDbCommand()
'setting command object equal to connection object
oleComm.Connection=oleConn

Dim SQL as String

SQL = "Update DB set field1=" & field1_  & ",field2=(' " & field2_ & "')"   & ",field3=#" & field3_ &  "#" & " WHERE unique_identifier= " + unique_identifier_  

Trace.Warn(SQL)

oleComm.CommandText= SQL

oleConn.Open()

'opening the dataadapter to send the data
Dim da as New OleDb.OleDbDataAdapter()
'declaring a new dataset (disconnected recordset)
Dim ds as New DataSet()
'setting dataadapter equal to the command object
da.selectCommand=Olecomm

'dont run a query
oleComm.ExecuteNonQuery()

'declaring the itemselected, and setting it equal to it's index, plus 1 if you don't start counting from 0
Dim itemselected=(e.item.itemindex+1)

'show me the index (of record selected)!!
Response.Write("Record " & itemselected & " was the last record in selected.")  

'close connection
OleConn.Close()
end sub

<<<<<<<<<<<<<END CODE-BEHIND>>>>>>>>>>>>>>

Hope this helps!
Kittrick
0

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 2
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now