R
Rishad Quazi
Hello All,
I've been diligently going through the examples in Scott Mitchell's
"ASP Data Web Controls" book (I would recommend this work -- cleared
up a lot of questions for me). All of the examples are in VB.NET and
though I've been able to convert pretty much all of the examples so
far into C# (my preferred language), there's one critical example that
has me stumped. In Chapter 9, he demonstrates how to create a DataGrid
containing a column with a DropDownList containing a foreign key to
another table (using the pubs database, displaying the books table
with FK to publishers name table).
Here's the working VB.NET example:
http://2602a.frsc01.forestry.ubc.ca/KickStartVB/Listing9.7.aspx
I managed to get the VB.NET example to work perfectly, but am stumped
at a critical step of converting it to C#.
Here's the code for the VB.NET example:
..
..
..
..
<asp
ataGrid runat="server" id="dgTitle" Font-Name="Verdana"
Font-Size="9pt"
CellPadding="5"
AlternatingItemStyle-BackColor="#dddddd" AutoGenerateColumns="False"
DataKeyField="title_id"
OnEditCommand="dgTitle_EditRow" OnUpdateCommand="dgTitle_UpdateRow"
OnCancelCommand="dgTitle_CancelRow">
<HeaderStyle BackColor="Navy" ForeColor="White" Font-Size="13pt"
Font-Bold="True"
HorizontalAlign="Center" />
<Columns>
<asp:EditCommandColumn ButtonType="LinkButton" HeaderText="Edit"
EditText="Edit" UpdateText="Update" CancelText="Cancel" />
<asp:BoundColumn DataField="title" HeaderText="Title" ReadOnly="True"
/>
<asp:TemplateColumn HeaderText="Publisher">
<ItemTemplate>
<%# DataBinder.Eval(Container.DataItem, "pub_name") %>
</ItemTemplate>
<EditItemTemplate>
<asp
ropDownList id="ddlPublisher" runat="server"
DataTextField="pub_name"
DataValueField="pub_id"
DataSource="<%# GetPublishers() %>"
SelectedIndex='<%# GetSelectedIndex(Container.DataItem("pub_id")) %>'
/>
</EditItemTemplate>
</asp:TemplateColumn>
<asp:BoundColumn DataField="price" DataFormatString="{0:c}"
HeaderText="Price" ReadOnly="True" />
</Columns>
</asp
ataGrid>
And the server-side code:
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles
MyBase.Load
'Put user code to initialize the page here
If Not Page.IsPostBack Then
BindData()
End If
End Sub
Dim ddlDataSet As DataSet = New DataSet
Sub BindData()
'1. Create a connection
Const strConnString As String =
"server=XXX;uid=pubs;pwd=XXX;database=pubs"
Dim objConn As New SqlConnection(strConnString)
'2. Create a command object for the query
Dim strSQL As String = _
"SELECT title_id, title, t.pub_id, p.pub_name, price FROM titles t " &
_
"INNER JOIN publishers p ON t.pub_id = p.pub_id ORDER BY title"
Dim objCmd As New SqlCommand(strSQL, objConn)
objConn.Open() 'Open the connection
'Finally, specify the DataSource and call DataBind()
dgTitle.DataSource =
objCmd.ExecuteReader(CommandBehavior.CloseConnection)
dgTitle.DataBind()
objConn.Close() 'Close the connection
End Sub
Function GetPublishers() As DataSet
'1. Create a connection
Const strConnString As String =
"server=XXX;uid=pubs;pwd=XXX;database=pubs"
Dim objConn As New SqlConnection(strConnString)
'2. Create a command object for the query
Const strSQL As String = _
"SELECT pub_id, pub_name FROM publishers ORDER BY pub_name"
Dim myDataAdapter As SqlDataAdapter
myDataAdapter = New SqlDataAdapter(strSQL, objConn)
'Fill the DataSet
objConn.Open() 'Open the connection
myDataAdapter.Fill(ddlDataSet, "Publishers")
objConn.Close() 'Close the connection
Return ddlDataSet 'Return the DataSet
End Function
Function GetSelectedIndex(ByVal pub_id As String) As Integer
'Loop through the DataSet ddlDataSet
Dim iLoop As Integer
Dim dt As DataTable = ddlDataSet.Tables("Publishers")
For iLoop = 0 To dt.Rows.Count - 1
If pub_id = dt.Rows(iLoop)("pub_id").ToString() Then
Return iLoop
End If
Next iLoop
End Function
Sub dgTitle_EditRow(ByVal sender As Object, ByVal e As
DataGridCommandEventArgs)
dgTitle.EditItemIndex = e.Item.ItemIndex
BindData()
End Sub
Sub dgTitle_UpdateRow(ByVal sender As Object, ByVal e As
DataGridCommandEventArgs)
'Get information from columns...
Dim ddlPublishers As DropDownList =
e.Item.Cells(2).FindControl("ddlPublisher")
Dim titleID As String = dgTitle.DataKeys(e.Item.ItemIndex)
'Update the database...
Dim strSQL As String
strSQL = "UPDATE titles SET pub_id = @pubIDParam " & _
"WHERE title_id = @titleIDParam"
Const strConnString As String =
"server=XXX;uid=pubs;pwd=XXX;database=pubs"
Dim objConn As New SqlConnection(strConnString)
Dim objCmd As New SqlCommand(strSQL, objConn)
Dim pubIDParam As New SqlParameter("@pubIDParam", SqlDbType.Char, 4)
Dim titleIDParam As New SqlParameter("@titleIDParam",
SqlDbType.VarChar, 6)
pubIDParam.Value = ddlPublishers.SelectedItem.Value
objCmd.Parameters.Add(pubIDParam)
titleIDParam.Value = titleID
objCmd.Parameters.Add(titleIDParam)
'Issue the SQL command
objConn.Open()
objCmd.ExecuteNonQuery()
objConn.Close()
dgTitle.EditItemIndex = -1
BindData()
End Sub
Sub dgTitle_CancelRow(ByVal sender As Object, ByVal e As
DataGridCommandEventArgs)
dgTitle.EditItemIndex = -1
BindData()
End Sub
..
..
..
..
..
and here is my non-working C# version. The part that does not work is
the SelectionIndex section of the front-end code - if I omit it, the
page works fine, except that when I go into edit mode for a row, the
dropdown list defaults to the first entry in the list, as expected.
..
..
..
..
<asp
ataGrid runat="server" id="dgTitle" Font-Name="Verdana"
Font-Size="9pt" CellPadding="5"
AlternatingItemStyle-BackColor="#dddddd"
AutoGenerateColumns="False" DataKeyField="title_id"
OnEditCommand="dgTitle_EditRow" OnUpdateCommand="dgTitle_UpdateRow"
OnCancelCommand="dgTitle_CancelRow"
Font-Names="Verdana">
<AlternatingItemStyle BackColor="#DDDDDD"></AlternatingItemStyle>
<HeaderStyle Font-Size="13pt" Font-Bold="True"
HorizontalAlign="Center" ForeColor="White"
BackColor="Navy"></HeaderStyle>
<Columns>
<asp:EditCommandColumn ButtonType="LinkButton"
UpdateText="Update" HeaderText="Edit" CancelText="Cancel"
EditText="Edit"></asp:EditCommandColumn>
<asp:BoundColumn DataField="title" ReadOnly="True"
HeaderText="Title"></asp:BoundColumn>
<asp:TemplateColumn HeaderText="Publisher"> <ItemTemplate>
<%# DataBinder.Eval(Container.DataItem, "pub_name") %>
</ItemTemplate>
<EditItemTemplate>
<asp
ropDownList id="ddlPublisher"
runat="server" DataTextField="pub_name" DataValueField="pub_id"
DataSource="<%# GetPublishers() %>"
*** PROBLEM CODE IS HERE ***
SelectedIndex='< % # GetSelectedIndex(Container.DataItem("pub_id")) %
/>
</EditItemTemplate>
</asp:TemplateColumn>
<asp:BoundColumn DataField="price" ReadOnly="True" HeaderText="Price"
DataFormatString="{0:c}"></asp:BoundColumn>
</Columns>
</asp
ataGrid>
Server side code:
..
..
..
public class ForeignKeyDDL : System.Web.UI.Page
{
protected System.Web.UI.WebControls.DataGrid dgTitle;
protected DataSet ddlDataSet = new DataSet();
private void Page_Load(object sender, System.EventArgs e)
{
if (!IsPostBack)
BindData();
}
private void BindData() {
// create conn string
string strConn = "server=XXX;uid=pubs;pwd=XXX";
SqlConnection conn = new SqlConnection(strConn);
// create command obj for the query
string strSQL = "SELECT title_id, title, t.pub_id, p.pub_name, price
FROM
titles t ";
strSQL += "INNER JOIN publishers p ON t.pub_id = p.pub_id
ORDER BY title";
SqlCommand cmd = new SqlCommand(strSQL, conn);
conn.Open();
dgTitle.DataSource =
cmd.ExecuteReader(CommandBehavior.CloseConnection);
dgTitle.DataBind();
conn.Close();
}
protected DataSet GetPublishers() {
// create conn string
string strConn = "server=XXX;uid=pubs;pwd=XXX";
SqlConnection conn = new SqlConnection(strConn);
// create command obj for the query
string strSQL = "SELECT pub_id, pub_name from publishers order by
pub_name";
SqlDataAdapter da = new SqlDataAdapter();
da = new SqlDataAdapter(strSQL, conn);
conn.Open();
da.Fill(ddlDataSet, "Publishers");
conn.Close();
return ddlDataSet;
}
protected int GetSelectedIndex(string pub_id) {
int iLoop;
DataTable dt = ddlDataSet.Tables["Publishers"];
for (iLoop=0; iLoop<dt.Rows.Count - 1; iLoop++) {
if (pub_id.Equals(dt.Rows[iLoop]["pub_id"].ToString()))
return iLoop;
};
return 0;
}
protected void dgTitle_EditRow(object sender, DataGridCommandEventArgs
e) {
dgTitle.EditItemIndex = e.Item.ItemIndex;
BindData();
}
protected void dgTitle_UpdateRow(object sender,
DataGridCommandEventArgs e) {
// get information from columns
DropDownList ddlPublishers = (DropDownList)
e.Item.Cells[2].FindControl("ddlPublisher");
string titleID = dgTitle.DataKeys[e.Item.ItemIndex].ToString();
// update the database
string strSQL = "UPDATE titles set pub_id= @pubIDParam where
title_id=@titleIDParam";
string strConn = "server=XXX;uid=pubs;pwd=XXX;database=pubs;";
SqlConnection conn = new SqlConnection(strConn);
SqlCommand cmd = new SqlCommand(strSQL, conn);
SqlParameter pubIDParam = new SqlParameter("@pubIDParam",
SqlDbType.Char,
4);
SqlParameter titleIDParam = new SqlParameter("@titleIDParam",
SqlDbType.VarChar, 6);
pubIDParam.Value = ddlPublishers.SelectedItem.Value;
cmd.Parameters.Add(pubIDParam);
titleIDParam.Value = titleID;
cmd.Parameters.Add(titleIDParam);
// issue the SQL command
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
dgTitle.EditItemIndex = -1;
BindData();
}
protected void dgTitle_CancelRow(object sender,
DataGridCommandEventArgs e) {
dgTitle.EditItemIndex = -1;
BindData();
}
..
..
..
I think the C# server side code is working fine. My problem is with
the syntax in the front-end .aspx code. When I try to run the code, I
get the following compile time error:
..
..
..
Description: An error occurred during the compilation of a resource
required to service this
request. Please review the following specific error details and modify
your source code appropriately.
Compiler Error Message: CS0118:
'System.Web.UI.WebControls.DataGridItem.DataItem' denotes a
'property' where a 'method' was expected
Source Error:
Line 26: </ItemTemplate>
Line 27: <EditItemTemplate>
Line 28: <asp
ropDownList id="ddlPublisher"
runat="server" DataTextField="pub_name" DataValueField="pub_id"
DataSource="<%# GetPublishers() %>"
Line 29: SelectedIndex='<%#
GetSelectedIndex(Container.DataItem("pub_id")) %>'
/>
Line 30: </EditItemTemplate>
..
..
..
I've pretty sure the problem is with my expression of the
SelectedIndex attribute of the
EditItemTemplate, but I've tried quite a few combinations and nothing
seems to work.
Sorry about the long post folks.
Thanks again for any help anyone can provide.
Regards,
- Rishad
I've been diligently going through the examples in Scott Mitchell's
"ASP Data Web Controls" book (I would recommend this work -- cleared
up a lot of questions for me). All of the examples are in VB.NET and
though I've been able to convert pretty much all of the examples so
far into C# (my preferred language), there's one critical example that
has me stumped. In Chapter 9, he demonstrates how to create a DataGrid
containing a column with a DropDownList containing a foreign key to
another table (using the pubs database, displaying the books table
with FK to publishers name table).
Here's the working VB.NET example:
http://2602a.frsc01.forestry.ubc.ca/KickStartVB/Listing9.7.aspx
I managed to get the VB.NET example to work perfectly, but am stumped
at a critical step of converting it to C#.
Here's the code for the VB.NET example:
..
..
..
..
<asp
Font-Size="9pt"
CellPadding="5"
AlternatingItemStyle-BackColor="#dddddd" AutoGenerateColumns="False"
DataKeyField="title_id"
OnEditCommand="dgTitle_EditRow" OnUpdateCommand="dgTitle_UpdateRow"
OnCancelCommand="dgTitle_CancelRow">
<HeaderStyle BackColor="Navy" ForeColor="White" Font-Size="13pt"
Font-Bold="True"
HorizontalAlign="Center" />
<Columns>
<asp:EditCommandColumn ButtonType="LinkButton" HeaderText="Edit"
EditText="Edit" UpdateText="Update" CancelText="Cancel" />
<asp:BoundColumn DataField="title" HeaderText="Title" ReadOnly="True"
/>
<asp:TemplateColumn HeaderText="Publisher">
<ItemTemplate>
<%# DataBinder.Eval(Container.DataItem, "pub_name") %>
</ItemTemplate>
<EditItemTemplate>
<asp
DataTextField="pub_name"
DataValueField="pub_id"
DataSource="<%# GetPublishers() %>"
SelectedIndex='<%# GetSelectedIndex(Container.DataItem("pub_id")) %>'
/>
</EditItemTemplate>
</asp:TemplateColumn>
<asp:BoundColumn DataField="price" DataFormatString="{0:c}"
HeaderText="Price" ReadOnly="True" />
</Columns>
</asp
And the server-side code:
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles
MyBase.Load
'Put user code to initialize the page here
If Not Page.IsPostBack Then
BindData()
End If
End Sub
Dim ddlDataSet As DataSet = New DataSet
Sub BindData()
'1. Create a connection
Const strConnString As String =
"server=XXX;uid=pubs;pwd=XXX;database=pubs"
Dim objConn As New SqlConnection(strConnString)
'2. Create a command object for the query
Dim strSQL As String = _
"SELECT title_id, title, t.pub_id, p.pub_name, price FROM titles t " &
_
"INNER JOIN publishers p ON t.pub_id = p.pub_id ORDER BY title"
Dim objCmd As New SqlCommand(strSQL, objConn)
objConn.Open() 'Open the connection
'Finally, specify the DataSource and call DataBind()
dgTitle.DataSource =
objCmd.ExecuteReader(CommandBehavior.CloseConnection)
dgTitle.DataBind()
objConn.Close() 'Close the connection
End Sub
Function GetPublishers() As DataSet
'1. Create a connection
Const strConnString As String =
"server=XXX;uid=pubs;pwd=XXX;database=pubs"
Dim objConn As New SqlConnection(strConnString)
'2. Create a command object for the query
Const strSQL As String = _
"SELECT pub_id, pub_name FROM publishers ORDER BY pub_name"
Dim myDataAdapter As SqlDataAdapter
myDataAdapter = New SqlDataAdapter(strSQL, objConn)
'Fill the DataSet
objConn.Open() 'Open the connection
myDataAdapter.Fill(ddlDataSet, "Publishers")
objConn.Close() 'Close the connection
Return ddlDataSet 'Return the DataSet
End Function
Function GetSelectedIndex(ByVal pub_id As String) As Integer
'Loop through the DataSet ddlDataSet
Dim iLoop As Integer
Dim dt As DataTable = ddlDataSet.Tables("Publishers")
For iLoop = 0 To dt.Rows.Count - 1
If pub_id = dt.Rows(iLoop)("pub_id").ToString() Then
Return iLoop
End If
Next iLoop
End Function
Sub dgTitle_EditRow(ByVal sender As Object, ByVal e As
DataGridCommandEventArgs)
dgTitle.EditItemIndex = e.Item.ItemIndex
BindData()
End Sub
Sub dgTitle_UpdateRow(ByVal sender As Object, ByVal e As
DataGridCommandEventArgs)
'Get information from columns...
Dim ddlPublishers As DropDownList =
e.Item.Cells(2).FindControl("ddlPublisher")
Dim titleID As String = dgTitle.DataKeys(e.Item.ItemIndex)
'Update the database...
Dim strSQL As String
strSQL = "UPDATE titles SET pub_id = @pubIDParam " & _
"WHERE title_id = @titleIDParam"
Const strConnString As String =
"server=XXX;uid=pubs;pwd=XXX;database=pubs"
Dim objConn As New SqlConnection(strConnString)
Dim objCmd As New SqlCommand(strSQL, objConn)
Dim pubIDParam As New SqlParameter("@pubIDParam", SqlDbType.Char, 4)
Dim titleIDParam As New SqlParameter("@titleIDParam",
SqlDbType.VarChar, 6)
pubIDParam.Value = ddlPublishers.SelectedItem.Value
objCmd.Parameters.Add(pubIDParam)
titleIDParam.Value = titleID
objCmd.Parameters.Add(titleIDParam)
'Issue the SQL command
objConn.Open()
objCmd.ExecuteNonQuery()
objConn.Close()
dgTitle.EditItemIndex = -1
BindData()
End Sub
Sub dgTitle_CancelRow(ByVal sender As Object, ByVal e As
DataGridCommandEventArgs)
dgTitle.EditItemIndex = -1
BindData()
End Sub
..
..
..
..
..
and here is my non-working C# version. The part that does not work is
the SelectionIndex section of the front-end code - if I omit it, the
page works fine, except that when I go into edit mode for a row, the
dropdown list defaults to the first entry in the list, as expected.
..
..
..
..
<asp
Font-Size="9pt" CellPadding="5"
AlternatingItemStyle-BackColor="#dddddd"
AutoGenerateColumns="False" DataKeyField="title_id"
OnEditCommand="dgTitle_EditRow" OnUpdateCommand="dgTitle_UpdateRow"
OnCancelCommand="dgTitle_CancelRow"
Font-Names="Verdana">
<AlternatingItemStyle BackColor="#DDDDDD"></AlternatingItemStyle>
<HeaderStyle Font-Size="13pt" Font-Bold="True"
HorizontalAlign="Center" ForeColor="White"
BackColor="Navy"></HeaderStyle>
<Columns>
<asp:EditCommandColumn ButtonType="LinkButton"
UpdateText="Update" HeaderText="Edit" CancelText="Cancel"
EditText="Edit"></asp:EditCommandColumn>
<asp:BoundColumn DataField="title" ReadOnly="True"
HeaderText="Title"></asp:BoundColumn>
<asp:TemplateColumn HeaderText="Publisher"> <ItemTemplate>
<%# DataBinder.Eval(Container.DataItem, "pub_name") %>
</ItemTemplate>
<EditItemTemplate>
<asp
runat="server" DataTextField="pub_name" DataValueField="pub_id"
DataSource="<%# GetPublishers() %>"
*** PROBLEM CODE IS HERE ***
SelectedIndex='< % # GetSelectedIndex(Container.DataItem("pub_id")) %
*** PROBLEM CODE ENDS HERE ***
/>
</EditItemTemplate>
</asp:TemplateColumn>
<asp:BoundColumn DataField="price" ReadOnly="True" HeaderText="Price"
DataFormatString="{0:c}"></asp:BoundColumn>
</Columns>
</asp
Server side code:
..
..
..
public class ForeignKeyDDL : System.Web.UI.Page
{
protected System.Web.UI.WebControls.DataGrid dgTitle;
protected DataSet ddlDataSet = new DataSet();
private void Page_Load(object sender, System.EventArgs e)
{
if (!IsPostBack)
BindData();
}
private void BindData() {
// create conn string
string strConn = "server=XXX;uid=pubs;pwd=XXX";
SqlConnection conn = new SqlConnection(strConn);
// create command obj for the query
string strSQL = "SELECT title_id, title, t.pub_id, p.pub_name, price
FROM
titles t ";
strSQL += "INNER JOIN publishers p ON t.pub_id = p.pub_id
ORDER BY title";
SqlCommand cmd = new SqlCommand(strSQL, conn);
conn.Open();
dgTitle.DataSource =
cmd.ExecuteReader(CommandBehavior.CloseConnection);
dgTitle.DataBind();
conn.Close();
}
protected DataSet GetPublishers() {
// create conn string
string strConn = "server=XXX;uid=pubs;pwd=XXX";
SqlConnection conn = new SqlConnection(strConn);
// create command obj for the query
string strSQL = "SELECT pub_id, pub_name from publishers order by
pub_name";
SqlDataAdapter da = new SqlDataAdapter();
da = new SqlDataAdapter(strSQL, conn);
conn.Open();
da.Fill(ddlDataSet, "Publishers");
conn.Close();
return ddlDataSet;
}
protected int GetSelectedIndex(string pub_id) {
int iLoop;
DataTable dt = ddlDataSet.Tables["Publishers"];
for (iLoop=0; iLoop<dt.Rows.Count - 1; iLoop++) {
if (pub_id.Equals(dt.Rows[iLoop]["pub_id"].ToString()))
return iLoop;
};
return 0;
}
protected void dgTitle_EditRow(object sender, DataGridCommandEventArgs
e) {
dgTitle.EditItemIndex = e.Item.ItemIndex;
BindData();
}
protected void dgTitle_UpdateRow(object sender,
DataGridCommandEventArgs e) {
// get information from columns
DropDownList ddlPublishers = (DropDownList)
e.Item.Cells[2].FindControl("ddlPublisher");
string titleID = dgTitle.DataKeys[e.Item.ItemIndex].ToString();
// update the database
string strSQL = "UPDATE titles set pub_id= @pubIDParam where
title_id=@titleIDParam";
string strConn = "server=XXX;uid=pubs;pwd=XXX;database=pubs;";
SqlConnection conn = new SqlConnection(strConn);
SqlCommand cmd = new SqlCommand(strSQL, conn);
SqlParameter pubIDParam = new SqlParameter("@pubIDParam",
SqlDbType.Char,
4);
SqlParameter titleIDParam = new SqlParameter("@titleIDParam",
SqlDbType.VarChar, 6);
pubIDParam.Value = ddlPublishers.SelectedItem.Value;
cmd.Parameters.Add(pubIDParam);
titleIDParam.Value = titleID;
cmd.Parameters.Add(titleIDParam);
// issue the SQL command
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
dgTitle.EditItemIndex = -1;
BindData();
}
protected void dgTitle_CancelRow(object sender,
DataGridCommandEventArgs e) {
dgTitle.EditItemIndex = -1;
BindData();
}
..
..
..
I think the C# server side code is working fine. My problem is with
the syntax in the front-end .aspx code. When I try to run the code, I
get the following compile time error:
..
..
..
Description: An error occurred during the compilation of a resource
required to service this
request. Please review the following specific error details and modify
your source code appropriately.
Compiler Error Message: CS0118:
'System.Web.UI.WebControls.DataGridItem.DataItem' denotes a
'property' where a 'method' was expected
Source Error:
Line 26: </ItemTemplate>
Line 27: <EditItemTemplate>
Line 28: <asp
runat="server" DataTextField="pub_name" DataValueField="pub_id"
DataSource="<%# GetPublishers() %>"
Line 29: SelectedIndex='<%#
GetSelectedIndex(Container.DataItem("pub_id")) %>'
/>
Line 30: </EditItemTemplate>
..
..
..
I've pretty sure the problem is with my expression of the
SelectedIndex attribute of the
EditItemTemplate, but I've tried quite a few combinations and nothing
seems to work.
Sorry about the long post folks.
Thanks again for any help anyone can provide.
Regards,
- Rishad