Using ASP.NET and the DataGrid, how do I bind a HyperLinkColumn to more than one field?
Dim detail As New HyperLinkColumn
With detail
.Text = "View Details"
.HeaderText = ""
.NavigateUrl = "\TeamDetail.aspx?Account={0}&Broker={1}"
.DataNavigateUrlField = "AccountKey, BrokerNumberKey"
End With
I was hoping for an data-binding event on HyperLinkColumn but no such luck.
You need to use a TemplateColumn. This will give you named controls you can work with in the ItemDataBound event.
ASP
<asp:TemplateColumn>
<ItemTemplate>
<asp:HyperLink runat="server" ID="LinkColumn" NavigateUrl="" Text="View Details"></asp:HyperLink>
</ItemTemplate>
</asp:TemplateColumn>
VB
Private Sub ReportGrid_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DataGridItemEventArgs) Handles ReportGrid.ItemDataBound
Const target = "/TeamsDetail.aspx?Account={0}&Broker={1) Select Case e.Item.ItemType
Case ListItemType.Item, ListItemType.AlternatingItem
Dim ctrl = CType(e.Item.FindControl("LinkColumn"), HyperLink)
Dim row = CType(e.Item.DataItem, DataRowView)
If ctrl IsNot Nothing Then
Dim accountKey = CInt(row("PrincipalAccountKey"))
Dim brokerNumberKey = CInt(row("BrokerNumberKey"))
ctrl.NavigateUrl = String.Format(target, accountKey, brokerNumberKey)
End If
End Select
End Sub
Related
I have got a gridview which when you press select on a row it transfers you to another gridview page,
which displays more columns from that table to give more detail about that row.
I know how to do this using:
<asp:HyperLinkField DataNavigateUrlFields="MISAppID" DataNavigateUrlFormatString="ApplicationsDetails.aspx?MISAppID={0}" Text="Select" />
In the 1st Gridview then using a Stored-procedure on the second page it displays the correct row using the ID field.
In my current site on the second page, I have added an edit button that does edit the row correctly in my database but on completion, it breaks the site and I can't work out how to get it to just refresh the gridview
This is the error I get:
Exception Details: System.NotSupportedException: Updating is not
supported by data source 'SqlDataSource1' unless UpdateCommand is
specified.
Is it the case that my BindGrid is missing something or is the way I am using my Stored-procedure?
Here is my VB code:
Public Sub BindGrid() Handles SqlDataSource1.Selecting
End Sub
Protected Sub OnRowEditing(sender As Object, e As GridViewEditEventArgs)
GridView1.EditIndex = e.NewEditIndex
Me.BindGrid()
End Sub
Protected Sub OnRowUpdating(sender As Object, e As GridViewUpdateEventArgs)
Dim row As GridViewRow = GridView1.Rows(e.RowIndex)
Dim misappId As Integer = Convert.ToInt32(GridView1.DataKeys(e.RowIndex).Values(0))
Dim application As String = TryCast(row.Cells(2).Controls(0), TextBox).Text
Dim url As String = TryCast(row.Cells(3).Controls(0), TextBox).Text
Dim access_group As String = TryCast(row.Cells(4).Controls(0), TextBox).Text
Dim creator_ein As String = TryCast(row.Cells(5).Controls(0), TextBox).Text
Dim data_location As String = TryCast(row.Cells(6).Controls(0), TextBox).Text
Dim purpose As String = TryCast(row.Cells(7).Controls(0), TextBox).Text
Dim active As String = TryCast(row.Cells(8).Controls(0), TextBox).Text
Dim business_owner As String = TryCast(row.Cells(9).Controls(0), TextBox).Text
Dim area As String = TryCast(row.Cells(10).Controls(0), TextBox).Text
Dim constr As String = ConfigurationManager.ConnectionStrings("myLocalConnectionString").ConnectionString
Using con As New SqlConnection(constr)
Using cmd As New SqlCommand("UPDATE tbl_AutomationCompassApplications SET Application = #Application, URL = #URL, Access_Group = #Access_Group, Creator_EIN = #Creator_EIN, Data_location = #Data_location, Purpose = #Purpose, Active = #Active, Business_Owner = #Business_Owner, Area = #Area WHERE MISAppID = #MISAppID")
cmd.Parameters.AddWithValue("#MISAppID", misappId)
cmd.Parameters.AddWithValue("#Application", application)
cmd.Parameters.AddWithValue("#URL", url)
cmd.Parameters.AddWithValue("#Access_Group", access_group)
cmd.Parameters.AddWithValue("#Creator_EIN", creator_ein)
cmd.Parameters.AddWithValue("#Data_location", data_location)
cmd.Parameters.AddWithValue("#Purpose", purpose)
cmd.Parameters.AddWithValue("#Active", active)
cmd.Parameters.AddWithValue("#Business_Owner", business_owner)
cmd.Parameters.AddWithValue("#Area", area)
cmd.Connection = con
con.Open()
cmd.ExecuteNonQuery()
con.Close()
End Using
End Using
GridView1.EditIndex = -1
Me.BindGrid()
End Sub
Ok, say we have a list of hotels - we want to display them, and then click on a row to eit.
(and you writing WAY too much code here).
So, lets say we drop in a gridview. Use the connection wizard - let it generate the markup.
THEN REMOVE the data source on the page, remove the datasource property of the gridview.
So, in less time then it takes me to write above? We have this markup:
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:Button ID="cmdView" runat="server" Text="Edit"
PK = '<%# Container.DataItemIndex %>' OnClick="cmdView_Click" />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="FirstName" HeaderText="FirstName" />
<asp:BoundField DataField="HotelName" HeaderText="HotelName" />
<asp:BoundField DataField="City" HeaderText="City" />
</Columns>
</asp:GridView>
Note the cool trick I used to get the PK row index.
When you are looking at the grid, you can't double click on the button to wire up a event (code behind), but you CAN DO THIS!!!!
Note VERY care full in above - I typed in OnClick "=", when you HIT "=", then NOTE the inteli-sense that popped up - the create NEW event is what we need. Click on create new event - NOTHING seems to happen, but if we NOW go to code behind, we have a code stub for the button!!!
And note how I needed/wanted the PK row value - so I just shoved in and created my OWN custom attribute for that button. ("PK").
Ok, so our code to load up the grid is now this - and I included the button click code:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If IsPostBack = False Then
LoadGrid()
End If
End Sub
Sub LoadGrid()
Dim strSQL As String
strSQL = "SELECT * from tblHotels Order by HotelName"
Using cmdSQL As New SqlCommand(strSQL, New SqlConnection(My.Settings.TEST3))
cmdSQL.Connection.Open()
Dim MyTable As New DataTable
MyTable.Load(cmdSQL.ExecuteReader)
GridView1.DataSource = MyTable
GridView1.DataBind()
Session("MyTable") = MyTable
End Using
End Sub
Protected Sub cmdView_Click(sender As Object, e As EventArgs)
Dim MyBtn As Button = sender
Session("RowID") = MyBtn.Attributes.Item("PK")
Response.Redirect("~/EditHotel.aspx")
End Sub
Look how clean and simple the above is!!! I find this as easy say as MS-Access coding!!!
Ok, so the grid now looks like this:
Note the button click code.
So, our markup is this for the new page (to edit hte ONE row).
<div style="float:left;width:20%">
<div style="text-align:right">
First Name :<asp:TextBox ID="txtFirstname" runat="server" Width="150"></asp:TextBox> <br />
Last Name :<asp:TextBox ID="txtLastname" runat="server" Width="150"></asp:TextBox> <br />
Hotel Name :<asp:TextBox ID="txtHotel" runat="server" Width="150"></asp:TextBox> <br />
City :<asp:TextBox ID="txtCity" runat="server" Width="150"></asp:TextBox> <br />
Active :<asp:CheckBox ID="Active" runat="server" Width="150"></asp:CheckBox>
</div>
</div>
<div style="clear:both">
<br />
<asp:Button ID="cmdSave" runat="server" Text ="Save " />
<asp:Button ID="cmdCancel" runat="server" Text="Cancel" Style="margin-left:20px" />
</div>
</form>
and it looks like this:
and the load code and save button code for this page?
This:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If IsPostBack = False Then
LoadInfo()
End If
End Sub
Sub LoadInfo()
Dim MyTable As DataTable = Session("MyTable")
Dim MyRow As DataRow = MyTable.Rows(Session("RowID"))
txtFirstname.Text = MyRow("FirstName")
txtLastname.Text = MyRow("LastName")
txtCity.Text = MyRow("City")
txtHotel.Text = MyRow("HotelName")
Active.Checked = MyRow("Active")
End Sub
Protected Sub cmdSave_Click(sender As Object, e As EventArgs) Handles cmdSave.Click
Dim MyTable As DataTable = Session("MyTable")
Dim MyRow As DataRow = MyTable.Rows(Session("RowID"))
MyRow("FirstName") = txtFirstname.Text
MyRow("LastName") = txtLastname.Text
MyRow("City") = txtCity.Text
MyRow("HotelName") = txtHotel.Text
MyRow("Active") = Active.Checked
Using cmdSQL As New SqlCommand("SELECT * from tblHotels where ID = 0",
New SqlConnection(My.Settings.TEST3))
Dim da As New SqlDataAdapter(cmdSQL)
Dim cmdUpdate As New SqlCommandBuilder(da)
da.Update(MyTable)
End Using
Response.Redirect("~/MyTours.aspx")
End Sub
Again, look how easy, clean and readable the code is.
Study the above example - you see that you don't need all that parameters code, and you see how little code is in fact required to select a row - jump to page to edit, and then you hit save - update the data and jump back to the grid row page.
I am trying to do a nested repeater control with check box inside. Basically, what i want is
categorize the checkboxes like,
Group 1
Item 1
Item 2
Group 2
Item 3
Item 4
Group 3
Item 5
Item 6
The problem I am facing is, I getting the error :
Error 1 : 'DataRowView' is not declared. It may be inaccessible due to its protection level.
Error 2 : Name 'DataRowView' is not declared.
ASPX :
<asp:Repeater ID="rp_Groups" runat="server" OnItemDataBound="rp_Groups_ItemDataBound" >
<ItemTemplate>
<ul>
<asp:CheckBox runat="server" ID="chk_Group" Text='<%# Eval("category_type") %>' Value='<%# Eval("service_type_category_id") %>' onclick="OnGroupClick" />
<p class="nested">
<asp:CheckBoxList runat="server" ID="chk_Items" DataValueField="ServiceTypeID" DataTextField="Name"
DataSource='<%# ((DataRowView)Container.DataItem).CreateChildView("FK_esnServiceType_Service_Type_Categorization") %>' ></asp:CheckBoxList>
</p>
</ul>
</ItemTemplate>
</asp:Repeater>
Codebehind:
Public Sub Fill()
Dim dtServiceCategory As DataTable = ServiceTypeModel.GetService_Categories()
Dim dtServiceType As DataTable = ServiceTypeModel.Search("", True)
rp_Groups.DataSource = dtServiceCategory
rp_Groups.DataBind()
Dim ds As New DataSet()
ds.Tables.Add(dtServiceCategory)
ds.Tables.Add(dtServiceType)
Dim relation As New DataRelation("FK_esnServiceType_Service_Type_Categorization", ds.Tables("dtServiceCategory").Columns("service_type_category_id"), ds.Tables("dtServiceType").Columns("CategorizationID"), False)
ds.Relations.Add(relation)
relation.Nested = True
End Sub
Protected Sub rp_Groups_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.RepeaterItemEventArgs) Handles rp_Groups.ItemDataBound
Dim chklist As CheckBoxList = DirectCast(e.Item.FindControl("chk_Items"), CheckBoxList)
If chklist IsNot Nothing Then
chklist.DataSource = DirectCast(e.Item.DataItem, DataRowView).CreateChildView("FK_esnServiceType_Service_Type_Categorization")
chklist.DataBind()
End If
End Sub
What am i missing ?
You should check which itemtype is being fired on the ItemDataBound event, this may or may not be the problem, as you don't have a header and footer template, however it is still good practice.
Protected Sub rp_Groups_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.RepeaterItemEventArgs) Handles rp_Groups.ItemDataBound
If e.Item.ItemType = ListItemType.Item OrElse e.Item.ItemType = ListItemType.AlternatingItem Then
Dim chklist As CheckBoxList = DirectCast(e.Item.FindControl("chk_Items"), CheckBoxList)
If chklist IsNot Nothing Then
chklist.DataSource = DirectCast(e.Item.DataItem, DataRowView).CreateChildView("FK_esnServiceType_Service_Type_Categorization")
chklist.DataBind()
End If
End If
End Sub
EDIT
I've just noticed that you are adding the relation after you have already binded the repeater's datasource. Try moving the .databind after the relation has been added.
EDIT 2
OK can you try this. Add the datatables to the dataset and set the repeaters datasource to: ds.Tables(0)
Public Sub Fill()
Dim ds As New DataSet()
Dim dtServiceCategory As DataTable = ServiceTypeModel.GetService_Categories()
Dim dtServiceType As DataTable = ServiceTypeModel.Search("", True)
ds.Tables.Add(dtServiceCategory)
ds.Tables.Add(dtServiceType)
Dim relation As New DataRelation("FK_esnServiceType_Service_Type_Categorization", ds.Tables("dtServiceCategory").Columns("service_type_category_id"), ds.Tables("dtServiceType").Columns("CategorizationID"), False)
relation.Nested = True
ds.Relations.Add(relation)
rp_Groups.DataSource = ds.Tables(0)
rp_Groups.DataBind()
End Sub
Ensure that you have imported namespace System.Data
Try to add
<%# Import Namespace="System.Data" %>
to your ASPX file.
As another option you can import namespaces globally, not only in one page:
http://msmvps.com/blogs/simpleman/archive/2006/01/11/80804.aspx
I am a AS400 programmer asked to write a program in asp.net using vb.net. I have never done this before and I am having issues with populating a listbox in Gridview. I have researched this subject for days but all the code I have tried, found in examples, do not work. Please forgive any really bad code, with me being so new to .net, I am sure this could be written much better. I appreciate any help you may be able to offer. the grid is "AdjusterList" and the Listbox is called "MAICD". I think the 'failing/bad' code in
Public Sub AdjusterList_RowDataBound. It is giving me a null exception error the line before the databind; oCtrl.DataSource = oRs
I am using code given to me by a senior .net programmer, whom is not able to offer any more assistance to this newbie. Just Fyi....
Here is my aspx.
<div id="div1" runat="server">
<asp:GridView ID="AdjusterList" runat="server" Width="1100px"
ClientIDMode="Static" AllowSorting="True"
AutoGenerateColumns="False"
OnRowCommand="AdjusterList_RowCommand"
OnRowEditing="AdjusterList_RowEditing"
OnRowUpdating="AdjusterList_RowUpdating"
OnRowDeleting="AdjusterList_RowDeleting"
OnRowCancelingEdit="AdjusterList_RowCancelingEdit"
OnRowDataBound="AdjusterList_RowDataBound"
DataKeyNames="INSCD, INSSEQ"
ShowHeaderWhenEmpty="True" EditRowStyle-BackColor="#FF9900" PageSize="20"
EmptyDataText="NO RECORDS FOUND FOR THIS INSURER"
ShowFooter="True"EnableViewState="true">
<EditRowStyle BackColor="#FF9900" />
<RowStyle BackColor="White" ForeColor="Black" />
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton id="btnedit" runat="server" CommandName="Edit"/>
</ItemTemplate>
<EditItemTemplate>
<asp:LinkButton id="btnupdate" runat="server" CommandName="Update" Text="Save" />
<asp:LinkButton id="btncancel" runat="server" CommandName="Cancel" Text=Cancel"/>
</EditItemTemplate>
<FooterTemplate>
<asp:LinkButton id="btninsert" runat="server" CommandName="Insert" Text="Insert"/>
</FooterTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText ="Mail Code" ItemStyle-HorizontalAlign="Center">
<ItemTemplate>
<asp:Label ID="lblmaicd" runat="server" Text='<%# Bind("MAICD")%>'></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:ListBox ID="MAICD" runat="server" Rows="1"DataTextField="Text"
DataValueField='<%# Bind("MAICD")%></asp:ListBox>
</EditItemTemplate>
<FooterTemplate>
<asp:ListBox ID="MAICD" runat="server" width="200" DataTextField="Text">
</asp:ListBox>
</FooterTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
My code behind...
Imports System.Data
Imports System.Data.SqlClient
Imports System.Data.OleDb
Public Class EditAdjusterData
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e AsSystem.EventArgs)
Dim sAdjuster As String = Session("Adjuster")
Dim sSeqNo As String = Session("SeqNo")
PopulateEdit(sAdjuster, sSeqNo, dateok)
If IsPostBack Then
'divEdit.Visible = False
'divSelect.Visible = True
'ShowForm()
Else
AdjusterList.DataBind()
'divEdit.Visible = True
'divSelect.Visible = False
End If
End Sub
Protected Sub PopulateEdit(sValue As String, sValue2 As String, sValue3 As String)
' CALL TO PGRTSTLIB FILE INSP TO GET INSURER NAME
' 2ND CALL TO PGRTSTLIB FILE INSD
Dim oConn As New OleDbConnection()
Dim sConn As String = ""
Dim oCmd As New OleDbCommand()
Dim oAdapter As New OleDbDataAdapter()
Dim oRs As DataSet = New DataSet
Dim sSql As String = ""
sConn = "Provider=IBMDA400.DataSource.1;
oConn = New OleDb.OleDbConnection(sConn)
oConn.Open()
sSql = "SELECT INSCD, INSSEQ, MAICD, MAISEQ, (substr(char(EFFDT),5,2) || '-' || substr(char(EFFDT),7,2) || '-' || substr(char(EFFDT),1,4)) AS EFFDT, (substr(char(CANDT),5,2) || '-' || substr(char(CANDT),7,2) || '-' || substr(char(CANDT),1,4)) AS CANDT, ACCFIL FROM PGRTSTLIB.INSD WHERE INSCD = '" & sValue & "' "
oCmd = New OleDbCommand(sSql, oConn)
Session(INSCD) = INSCD
Session(EFFDT) = EFFDT
Session(MAICD) = MAICD
Session("CANDT") = CANDT
oCmd.CommandType = CommandType.Text
oAdapter.SelectCommand = oCmd
oAdapter.Fill(oRs, "Data")
Dim sMailCode As String = " "
Dim sMailSeq As String = " "
Dim pRow As DataRow
For Each pRow In oRs.Tables("Data").Rows
sMailCode = pRow("MAICD").ToString()
Next
Session(sMailCode) = MAICD
Session(MAICD) = sMailCode
Session(sMailCode) = sMailCode
AdjusterList.DataSource = oRs
'AdjusterList.DataBind()
'If sMailCode <> " " Then
' PopulateMailCode(sMailCode)
'End If
oRs.Dispose()
oAdapter.Dispose()
oCmd.Dispose()
oConn.Dispose()
End Sub
Protected Sub AdjusterList_PageIndexChanging(ByVal sender As Object,
ByVal e As System.Web.UI.WebControls.GridViewPageEventArgs)
AdjusterList.PageIndex = e.NewPageIndex
AdjusterList.DataBind()
End Sub
Protected Sub AdjusterList_RowCommand(ByVal sender As Object,
ByVal e As System.Web.UI.WebControls.GridViewCommandEventArgs)
End Sub
Protected Sub AdjusterList_RowCreated(ByVal sender As Object,
ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs)
End Sub
Public Sub AdjusterList_RowDataBound(ByVal Sender As Object,
ByVal e As GridViewRowEventArgs) Handles AdjusterList.RowDataBound
If e.Row.RowType = DataControlRowType.DataRow Then
If e.Row.FindControl("MAICD") IsNot Nothing Then
Dim MAICD As ListBox = e.Row.FindControl("MAICD")
'If (e.Row.RowState And DataControlRowState.Edit) > 0 Then
BindAjusterList()
End If
End If
End Sub
Public Sub BindAjusterList()
Dim oConn As New OleDbConnection()
Dim sConn As String = ""
Dim oCmd As New OleDbCommand()
Dim oAdapter As New OleDbDataAdapter()
Dim oRs As DataSet = New DataSet
Dim sSql As String = ""
sConn = "Provider=IBMDA400.DataSource.1; "
oConn = New OleDb.OleDbConnection(sConn)
oConn.Open()
'sSql = "SELECT MAICD as Value, MAICD AS Text from PGRTSTLIB.INSM order by MAICD"
sSql = "SELECT MAICD As Value, MAICD AS TEXT from PGRTSTLIB.INSM"
oCmd = New OleDbCommand(sSql, oConn)
'oCmd.Parameters.Add(New SqlParameter("#Type", Insurer))
oCmd.CommandType = CommandType.Text
oAdapter.SelectCommand = oCmd
oAdapter.Fill(oRs, "ListBox")
Dim oCtrl As ListBox
oCtrl = AdjusterList.FindControl("MAICD")
oCtrl.Items.Add(New ListItem("", ""))
oCtrl.DataSource = oRs
oCtrl.DataBind()
oCtrl.Items.Insert(0, New ListItem(String.Empty, String.Empty))
If Len(sValue) > 0 Then
oCtrl.SelectedValue = sValue
Else
sValue = " "
End If
oRs.Dispose()
oAdapter.Dispose()
oCmd.Dispose()
oConn.Dispose()
End Sub
Public Sub AdjusterList_RowEditing(ByVal sender As Object,
ByVal e As System.Web.UI.WebControls.GridViewEditEventArgs)
AdjusterList.EditIndex = e.NewEditIndex
AdjusterList.DataBind()
End Sub
Protected Sub AdjusterList_RowUpdating(ByVal sender As Object,
ByVal e As System.Web.UI.WebControls.GridViewUpdateEventArgs)
' Dim row As GridViewRow = DirectCast(SubsidaryList.Rows(e.RowIndex), GridViewRow)
Dim INSCD As String = DirectCast(AdjusterList.Rows(e.RowIndex).Cells (0).FindControl ("INSCD"), TextBox).Text
Dim INSSEQ As String = DirectCast(AdjusterList.Rows(e.RowIndex).Cells(1).FindControl("INSSEQ"), TextBox).Text
Dim MAICD As String = DirectCast(AdjusterList.Rows(e.RowIndex).Cells(2).FindControl("MAICD"), ListBox).Text
Dim MAISEQ As String = DirectCast(AdjusterList.Rows(e.RowIndex).Cells(3).FindControl("MAISEQ"), TextBox).Text
Dim EFFDT As String = DirectCast(AdjusterList.Rows(e.RowIndex).Cells(4).FindControl("EFFDT"), TextBox).Text
Dim CANDT As String = DirectCast(AdjusterList.Rows(e.RowIndex).Cells(5).FindControl("CANDT"), TextBox).Text
Dim ACCFIL As String = DirectCast(AdjusterList.Rows(e.RowIndex).Cells(6).FindControl("ACCFIL"), TextBox).Text
AdjusterList.EditIndex = -1
AdjusterList.DataBind()
' New Data to DataBind to sql datasource and resend page after RECORD updated
Response.Redirect("EditAdjusterData.aspx")
End Sub
Protected Sub AdjusterList_RowCancelingEdit() Handles AdjusterList.RowCancelingEdit
AdjusterList.EditIndex = -1
AdjusterList.DataBind()
End Sub
End Class
I am so new to .net and I may not fully understand every example. I think the senior .net programmers think it is funny : (
Thanks so much and please feel free to contact me with any help you may be able to offer. I just need the darn listbox to populate. I removed any code I considered unrelated to this listbox issue.
In your markup, you should change the DataValueField property of your ListBox to the "Value" string, because it's the alias you are giving to the property in the query ("SELECT MAICD As Value, MAICD AS TEXT from PGRTSTLIB.INSM"):
<asp:ListBox ID="MAICD" runat="server" Rows="1"DataTextField="Text" DataValueField="Value"></asp:ListBox>
Also, in RowDataBound event, you are retrieving the ListBox instance for that row using the FindControl method, but then you are retrieving it again in the BindAjusterList() method. Try changing the method to receive the control found:
Public Sub AdjusterList_RowDataBound(ByVal Sender As Object, ByVal e As GridViewRowEventArgs) Handles AdjusterList.RowDataBound
If e.Row.RowType = DataControlRowType.DataRow Then
If e.Row.FindControl("MAICD") IsNot Nothing Then
Dim MAICD As ListBox = e.Row.FindControl("MAICD")
BindAjusterList(MAICD)
End If
End If
End Sub
Public Sub BindAjusterList(ByVal oCtrl As ListBox)
' existing logic
oCtrl.Items.Add(New ListItem("", ""))
oCtrl.DataSource = oRs
oCtrl.DataBind()
' existing logic
End Sub
I have a DataGrid bound to a DataView which, among other columns has, an ID Column and ParentID Column, I need the user to be able to specify a ParentID using using a DropDownList (ComboBox).
Now, I have already added the DropDownList to the DataGrid like this:
<Columns>
[...]
<asp:TemplateColumn HeaderText="Parent" >
<ItemTemplate>
<asp:DropDownList ID="ddlParentID"
runat="server"
DataValueField="ID"
DataTextField="Short_Description"
Width="100%"
DataSource="<%# dsDV %> ">
</asp:DropDownList>
</ItemTemplate>
</asp:TemplateColumn>
</Columns>
In the code-behind I have the following a method:
Protected dsDV As New DataView
Protected Sub PopulateDropDownList()
Dim conn As SqlClient.SqlConnection = New SqlClient.SqlConnection(myConnString)
Dim comm As SqlClient.SqlCommand = New SqlClient.SqlCommand("SELECT * FROM myTable", conn)
comm.CommandType = CommandType.Text
Dim myTableTable As New DataTable
conn.Open()
myTableTable.Load(comm.ExecuteReader)
Me.dsDV = myTableTable.DefaultView
End Sub
That PopulateDropDownMethod is called on the form Load Event but, albeit DDLs do show, they show empty, as if no DataBinding is being made.
How can I properly bind the DDL with a dataSource in the codebehind? Or, if that's not the issue, how do I properly fill the DDL?
Update 1
After the first answer I went ahead and tried this (still no luck):
Protected Sub dg_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DataGridItemEventArgs) Handles dgData.ItemDataBound
If e.Item.ItemType = ListItemType.Item Or e.Item.ItemType = ListItemType.AlternatingItem Then
Dim ddl As DropDownList = CType(e.Item.Cells(3).FindControl("ddlParentID"), DropDownList)
Me.PopulateDropDownList(ddl)
End If
End Sub
Protected dsDV As New DataView
Protected Sub PopulateDropDownList(ddl As DropDownList)
Dim conn As SqlClient.SqlConnection = New SqlClient.SqlConnection(myConnString)
Dim comm As SqlClient.SqlCommand = New SqlClient.SqlCommand("SELECT * FROM myTable", conn)
comm.CommandType = CommandType.Text
Dim myTableTable As New DataTable
conn.Open()
myTableTable.Load(comm.ExecuteReader)
ddl.DataSource = myTableTable.DefaultView
ddl.DataBind()
End Sub
Note that I also removed the call to PopulateDropDownList from the Form Load Event handler.
you may try to call ddlParent.DataBind() after setting the datasource.
I don't why but taking the binding code from the aspx to the aspx.vb fixed the issue, so it all looks like this now:
<asp:TemplateColumn HeaderText="Parent" >
<ItemTemplate>
<asp:DropDownList ID="ddlParentID" runat="server" Width="100%" >
</asp:DropDownList>
</ItemTemplate>
</asp:TemplateColumn>
And for the code-behind, for each row:
Dim ddl As DropDownList = CType(e.Item.Cells(3).FindControl("ddlParentID"), DropDownList)
ddl.DataValueField = "ID"
ddl.DataTextField = "Short_Description"
ddl.DataSource = myTable.DefaultView
ddl.DataBind()
Losing my mind with this one. My button gets a commandargument of empty string even though the commandargument gets set. I have verified it gets set to the correct ID in debug mode, but then when I go to access this commandargument later in the repeaters ItemCommand event the commandarguments are empty string. And I have no idea why. I end up getting a sq foreign key exception because it is inserting an ID of 0 from the empty string values. There is no other code regarding the repeaters buttons that would be resetting it.
Repeater:
<asp:Repeater ID="repeaterAddresses" ViewStateMode="Enabled" DataSourceID="sqlFacilityAddresses" runat="server">
<ItemTemplate>
<Select:Address ID="AddressControl" runat="server" />
<asp:Button ID="btnMarkAsBilling" runat="server" EnableViewState="true" CommandName="Billing" Text="Mark as billing address" />
<asp:button ID="btnMarkAsPhysical" runat="server" EnableViewState="true" CommandName="Physical" Text="Mark as physical address" />
</ItemTemplate>
</asp:Repeater>
Code behind:
Protected Sub repeaterAddresses_ItemCreated(ByVal sender As Object, ByVal e As RepeaterItemEventArgs) Handles repeaterAddresses.ItemCreated
If Not IsNothing(DirectCast(e.Item.DataItem, DataRowView)) Then
If (e.Item.ItemType = ListItemType.Item) Or (e.Item.ItemType = ListItemType.AlternatingItem) Then
Dim addressControl As Address = DirectCast(e.Item.FindControl("AddressControl"), Address)
addressControl.AddressID = CInt(DirectCast(e.Item.DataItem, DataRowView)("Address_ID").ToString())
Dim btnBilling As Button = DirectCast(e.Item.FindControl("btnMarkAsBilling"), Button)
btnBilling.CommandArgument = CInt(DirectCast(e.Item.DataItem, DataRowView)("Address_ID").ToString())
Dim btnPhysical As Button = DirectCast(e.Item.FindControl("btnMarkAsPhysical"), Button)
btnPhysical.CommandArgument = CInt(DirectCast(e.Item.DataItem, DataRowView)("Address_ID").ToString())
End If
End If
End Sub
Protected Sub repeaterAddress_ItemCommand(ByVal sender As Object, ByVal e As RepeaterCommandEventArgs) Handles repeaterAddresses.ItemCommand
Dim conn As New SqlConnection(ConfigurationManager.ConnectionStrings("Trustaff_ESig2").ConnectionString)
Dim button As Button = CType(e.CommandSource, Button)
Select Case e.CommandName
Case "Billing"
Dim cmdBillingAddress As New SqlCommand("[SP_Facility_UpdateBillingAddress]", conn)
With cmdBillingAddress
.CommandType = CommandType.StoredProcedure
.Parameters.Add(New SqlParameter("#Facility_ID", DbType.Int32)).Value = sqlFacilityAddresses.SelectParameters("Facility_ID").DefaultValue
.Parameters.Add(New SqlParameter("#BillingAddress_ID", DbType.Int32)).Value = e.CommandArgument
End With
conn.Open()
cmdBillingAddress.ExecuteNonQuery()
conn.Close()
Case "Physical"
Dim cmdPhysicalAddress As New SqlCommand("[SP_Facility_UpdatePhysicalAddress]", conn)
With cmdPhysicalAddress
.CommandType = CommandType.StoredProcedure
.Parameters.Add(New SqlParameter("#Facility_ID", DbType.Int32)).Value = sqlFacilityAddresses.SelectParameters("Facility_ID").DefaultValue
.Parameters.Add(New SqlParameter("#PhysicalAddress_ID", DbType.Int32)).Value = e.CommandArgument
End With
conn.Open()
cmdPhysicalAddress.ExecuteNonQuery()
conn.Close()
End Select
PopulateBillingPhysicalAddresses(sqlFacilityAddresses.SelectParameters("Facility_ID").DefaultValue)
End Sub
Try this:
<asp:Button ID="btnMarkAsBilling" runat="server" EnableViewState="true"
CommandName="Billing" Text="Mark as billing address"
CommandArgument='<%# Eval("Address_ID") %>'/>
Note the single quotes around the attribute value. ASP.NET will not execute the server side data binding code if they are double quotes. You'll need to remove the CommandArgument assignments from your code behind.
Address_ID will need to be a property on the object you are databinding to the repeater.