I have a GridView as below
<asp:GridView ID="gvChain" runat="server" Font-Size="Small" CellPadding="3" CellSpacing="1" GridLines="None" AutoGenerateColumns="False">
<headerstyle backcolor="#CCCCCC" />
<columns>
<asp:BoundField DataField="Department" HeaderText="Department" />
<asp:TemplateField HeaderText="Manager Level 1">
<ItemTemplate>
<asp:Label ID="lblManager1" runat="server" Text=""></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:DropDownList ID="cbManager1" runat="server"/>
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Manager Level 2">
<ItemTemplate>
<asp:Label ID="lblManager2" runat="server"/>
</ItemTemplate>
<EditItemTemplate>
<asp:DropDownList ID="cbManager2" runat="server"/>
</EditItemTemplate>
</asp:TemplateField>
<asp:CommandField ShowEditButton="True">
<ControlStyle ForeColor="#009EDD" />
</asp:CommandField>
</columns>
</asp:GridView>
The BoundField 'Department' is being populated in the Page_Load as below which works fine and populates the GridView with a list of departments.
Dim dhandler As DepartmentHandler = New DepartmentHandler
Dim depts As New List(Of Department)
depts = dhandler.GetDepartmentList
gvChain.DataSource = depts
gvChain.DataBind()
I am then populating the ItemTemplates of the TemplateFields in the RowDAtaBound event as below. this is also working fine.
If e.Row.RowType = DataControlRowType.DataRow Then
Dim lblManager1 As Label = DirectCast(e.Row.FindControl("lblManager1"), Label)
Dim lblManager2 As Label = DirectCast(e.Row.FindControl("lblManager2"), Label)
Dim eHandler As EmployeeHandler = New EmployeeHandler
Dim deptCell As TableCell = e.Row.Cells(0)
Dim dept As Department = New Department
dept.Department = deptCell.Text
Dim mgr1 As Manager = eHandler.getManager1(dept)
Dim mgr2 As Manager = eHandler.getManager2(dept)
lblManager1.Text = mgr1.Name
lblManager2.Text = mgr2.Name
End If
What I now want to achieve is when clicking on the 'Edit' field of a row on the GridView, populate cbManager1 and cbManager2 with a list of Managers and set the SelectedValue of each DDL to the same values as I am retrieving in the item template. I can get the data with the below code in the RowEditing event of the GridView:
' Get the list of managers
Dim mgrs As New List(Of Manager)
mgrs = eHandler.GetManagerList
' Get the department name from the BoundField
Dim deptCell As TableCell = gvChain.Rows(e.NewEditIndex).Cells(0)
Dim dept As Department = New Department
dept.Department = deptCell.Text
' Pass the department name to the getManager1/2 functions to return the correct manager for that department
Dim mgr1 As Manager = eHandler.getManager1(dept)
Dim mgr2 As Manager = eHandler.getManager2(dept)
I have set breakpoints to check the data is being returned from the functions and the data is there as expected but where I am stuck is getting a reference on the DDLs in the EditItemTemplate so I can databind them and set the SelectedValue.
I have tried the below but this is giving a NullReference Exception:
Dim cbManager1 As DropDownList = TryCast(gvChain.Rows(e.NewEditIndex).FindControl("cbManager1"), DropDownList)
Dim cbManager2 As DropDownList = TryCast(gvChain.Rows(e.NewEditIndex).FindControl("cbManager2"), DropDownList)
I got round this in the end. I added the following code to the RowEditing event
gvChain.EditIndex = e.NewEditIndex
gvChain.DataBind()
I then did the following in the RowDataBound event
If e.Row.RowState = DataControlRowState.Edit Then
Dim cbManager1 As DropDownList = TryCast(e.Row.FindControl("cbManager1"), DropDownList)
Dim cbManager2 As DropDownList = TryCast(e.Row.FindControl("cbManager2"), DropDownList)
Dim eHandler As EmployeeHandler = New EmployeeHandler
Dim mgrs As New List(Of Manager)
mgrs = eHandler.GetManagerList
cbManager1.DataSource = mgrs
cbManager2.DataSource = mgrs
cbManager1.DataValueField = "Name"
cbManager1.DataTextField = "Name"
cbManager2.DataValueField = "Name"
cbManager2.DataValueField = "Name"
cbManager1.DataBind()
cbManager2.DataBind()
' Got rid of the bound field in the end and did it with a templatefield so needed to get the department from the label
Dim lbl As Label = e.Row.Cells(0).FindControl("lblDepartment")
Dim dept As Department = New Department
dept.Department = lbl.Text
Dim mgr1 As Manager = eHandler.getManager1(dept)
Dim mgr2 As Manager = eHandler.getManager2(dept)
Dim mgr1Name As String = mgr1.Name.ToUpper()
Dim mgr2Name As String = mgr2.Name.ToUpper()
cbManager1.SelectedValue = mgr1Name
cbManager2.SelectedValue = mgr2Name
End If
You could try something like this
If e.Row.RowState = DataControlRowState.Edit Then
Dim cbmanager As DropDownList = e.Row.FindControl("cbmanager1")
If Not cbmanager Is Nothing Then cbmanager.Items.Add(New ListItem("Test1", "Test1"))
End If
Related
In the OnRowDataBoundevent of the ASP.Net GridView I am trying to populate the Department DropDownList (ddlDepts) which will be displayed when a row is edited.
The code below is not working as the DropdownList is empty.
Any ideas what I am doing wrong?
'//GridView markup:
<asp:TemplateField HeaderText="Department" ItemStyle-Width = "150">
<ItemTemplate>
<asp:Label ID = "lblDept" runat="server" Text='<%# Eval("deptName")%>'></asp:Label>
<asp:DropDownList ID="ddlDepts" runat="server" Visible = "false">
</asp:DropDownList>
</ItemTemplate>
</asp:TemplateField>
''//Codefile
Protected Sub OnRowDataBound(ByVal sender As Object, ByVal e As GridViewRowEventArgs)
If e.Row.RowType = DataControlRowType.DataRow Then
Dim cmd As New SqlCommand("SELECT DISTINCT(DeptID,DeptName) FROM Departments")
Dim ddlDepts As DropDownList = TryCast(e.Row.FindControl("ddlDepts"), DropDownList)
ddlDepts.DataSource = Me.ExecuteQuery(cmd, "SELECT")
ddlDepts.DataTextField = "DeptID"
ddlDepts.DataValueField = "DeptName"
ddlDepts.DataBind()
Dim DeptName As ListItem = ddlDepts.Items.FindByValue("lblDept")
If DeptName IsNot Nothing Then
ddlDepts.SelectedValue = DeptName.Value
End If
End If
End Sub
Not sure which SQL you are using, but I think the query may be incorrect.
In MS SQL you would use it like this:
SELECT DISTINCT DeptID, DeptName FROM Departments
And I have no knowledge of MySQL (or other databases), but a quick search seems to indicate it uses the same methods for distinct.
Hi all I have a question about how can I add Items to a dropdownlist with some attributes. My first Idea was:
<asp:GridView ID="GV_Area" runat="server" AutoGenerateColumns="false" CssClass="table table-striped bolsa-table-gv text-center"
DataKeyNames="Area,Oferta">
<Columns>
<asp:BoundField DataField="Nombre" HeaderText="Nombre" ReadOnly="true" />
<asp:TemplateField>
<ItemTemplate>
<asp:DropDownList ID="ddl_Especializaciones" runat="server" CssClass="selectpicker" multiple DataSource='<%#GetDropDownData(Container)%>'></asp:DropDownList>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
And in the code:
Protected Function GetDropDownData(e As System.Web.UI.WebControls.GridViewRow) As ListItem()
Dim item As ListItem = New ListItem
Dim arr As ArrayList = New ArrayList
item.Selected = True
item.Text = "Hello"
item.Value = "Hello2"
arr.Add(item)
Return arr
End Function
The elements are included correctly in the dropdownlist but only with the text attribute. The selected and the value is not working. What do you think I'm doing wrong or, can I do it easily in another way?
Thanks a million for the help
If you use the DropDownList in a GridView, the easiest way to fill them with data is to use the OnRowDataBound event.
<asp:GridView ID="GV_Area" runat="server" OnRowDataBound="GV_Area_RowDataBound">
Code behind
Protected Sub GV_Area_RowDataBound(ByVal sender As Object, ByVal e As GridViewRowEventArgs)
'check if the row is a datarow
If (e.Row.RowType = DataControlRowType.DataRow) Then
'cast the row back to a datarowview
Dim row As DataRowView = CType(e.Row.DataItem,DataRowView)
'use findcontrol to locate the dropdownlist
Dim ddl As DropDownList = CType(e.Row.FindControl("ddl_Especializaciones"),DropDownList)
'if you need to use a datasource value for filling the dropdownlist
Dim Nombre As Integer = Convert.ToInt32(row("Nombre"))
'now fill the dropdownlist with values
'from a datasource, where 'textField' and `valueField` are colums/properties of the datasource
ddl.DataSource = Common.LoadFromDB
ddl.DataTextField = "textField"
ddl.DataValueField = "valueField"
ddl.DataBind
'or add them manually
ddl.Items.Insert(0, New ListItem("Item A", "1", true))
ddl.Items.Insert(1, New ListItem("item B", "1", true))
End If
End Sub
I have this gridview in my application :
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" AllowPaging="True">
<Columns>
<asp:TemplateField >
<ItemTemplate>
<asp:Button ID="Savebtn" runat="server" Text="تحديث البيانات" OnClick="gv_RowEditing"/>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="السعر الأقصى">
<ItemTemplate>
<asp:TextBox ID="mintxt" runat="server" Text='<%#Eval("prix max")%>' />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="السعر الأدنى" >
<ItemTemplate>
<asp:TextBox ID="maxtxt" runat="server" Text='<%#Eval("prix min")%>' />
</ItemTemplate>
</asp:TemplateField>
<asp:BoundField DataField="Datvente" HeaderText="التاريخ" SortExpression="Datvente" />
<asp:BoundField DataField="NomAdh" HeaderText="الإسم و اللقب" SortExpression="NomAdh" />
<asp:BoundField DataField="CodAdh" HeaderText="المنخرط" SortExpression="CodAdh" />
<asp:TemplateField >
<ItemTemplate>
<asp:HiddenField ID="Ref" runat="server" Value='<%#Eval("Ref")%>'/>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
The event of the click into button :
Protected Sub gv_RowEditing(ByVal sender As Object, ByVal e As EventArgs)
Try
Dim min As Double = Double.Parse(GridView1.SelectedRow.Cells("mintxt").ToString())
Dim max As Double = Double.Parse(GridView1.SelectedRow.Cells("maxtxt").ToString())
Dim reference As String = Double.Parse(GridView1.SelectedRow.Cells("Ref").ToString())
If min > max Then
avis2.Text = "الصيغة خاطئة"
Return
End If
DataAccessLayer.updatetraitementprix(min, max, reference)
avis2.Text = ""
FillingGrid(Session("region"), Session("date"), Session("speculation"))
Catch ex As Exception
avis2.Text = "الصيغة خاطئة"
GridView1.Visible = True
Return
End Try
Me.FillingGrid(Session("region"), Session("date"), Session("speculation"))
End Sub
I need to get the value of the column Ref and the new values of fields maxtxt and mintxt . but it didn't work
What are the reasons of this problem?
How can i resolve it?
There is absolutely need of RowEditing event. What you are doing is firing a simple OnClick event. So make these changes.
Markup ( Name change so that you may not confuse it with RowEditing event )
<asp:TemplateField >
<ItemTemplate>
<asp:Button ID="Savebtn" runat="server"
Text="تحديث البيانات"
OnClick="Savebtn_Click" />
</ItemTemplate>
</asp:TemplateField>
Code-behind
Protected Sub Savebtn_Click(sender As Object, e As System.EventArgs)
Dim btn As Button = CType(sender, Button)
Dim clickedRow As GridViewRow = CType(btn.NamingContainer, GridViewRow)
Dim minTextBox As TextBox = CType(clickedRow.FindControl("mintxt"), TextBox)
Dim maxTextBox As TextBox = CType(clickedRow.FindControl("maxtxt"), TextBox)
Dim refHidden As HiddenField = CType(clickedRow.FindControl("Ref"), HiddenField)
Dim min As Double = Double.Parse(minTextBox.Text)
Dim max As Double = Double.Parse(maxTextBox.Text)
Dim reference As Double = Double.Parse(refHidden.Value)
'rest of the code goes here
End Sub
Since the TextBox controls are inside of TemplateField's, you have to use Control#FindControl method to find them. Be aware of the Cell's index for each control.
Dim tbMin As TextBox = CType(GridView1.SelectedRow.Cells(1).FindControl("mintxt"), TextBox)
Dim min As Double = Double.Parse(tbMin.Text)
The reason you're getting this error is actually because the selectedrow is nothing, so you first need to get the current selected row then access all the controls in that row.
Please replace your code to the following:
Protected Sub gv_RowEditing(ByVal sender As Object, ByVal e As EventArgs)
Try
'First, get the saveBtn
Dim saveBtn As Button = DirectCast(sender, Button)
'Next, get the selected row of that button
Dim selectedRow As GridViewRow = DirectCast(saveBtn.Parent.Parent, GridViewRow)
'Now you can access all the controls of that row
Dim mintxt As TextBox = DirectCast(selectedRow.FindControl("mintxt"), TextBox)
Dim maxtxt As TextBox = DirectCast(selectedRow.FindControl("mintxt"), TextBox)
Dim Ref As HiddenField = DirectCast(selectedRow.FindControl("Ref"), HiddenField)
'Get the values of the controls
Dim min As Double = Double.Parse(mintxt.Text)
Dim max As Double = Double.Parse(maxtxt.Text)
Dim refVal As Double = Double.Parse(Ref.Value)
If min > max Then
avis2.Text = "الصيغة خاطئة"
Return
End If
DataAccessLayer.updatetraitementprix(min, max, refVal)
avis2.Text = ""
FillingGrid(Session("region"), Session("date"), Session("speculation"))
Catch ex As Exception
avis2.Text = "الصيغة خاطئة"
GridView1.Visible = True
Return
End Try
Me.FillingGrid(Session("region"), Session("date"), Session("speculation"))
End Sub
I have a GridView as below:
<asp:GridView ID="gvChain" runat="server" Font-Size="Small" CellPadding="3" CellSpacing="1" GridLines="None"
AutoGenerateColumns="False">
<HeaderStyle BackColor="#CCCCCC" />
<Columns>
<asp:TemplateField HeaderText="Department" ControlStyle-Width="175px">
<EditItemTemplate>
<asp:Label ID="lblDepartment" runat="server" Text='<%# Bind("Department") %>'></asp:Label>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="lblDepartment" runat="server" Text='<%# Bind("Department") %>'></asp:Label>
</ItemTemplate>
<ControlStyle Width="175px" />
</asp:TemplateField>
<asp:TemplateField HeaderText="Manager Level 1" ControlStyle-Width="175px">
<ItemTemplate>
<asp:Label ID="lblManager1" runat="server" Text=""></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:DropDownList ID="cbManager1" runat="server"></asp:DropDownList>
</EditItemTemplate>
<ControlStyle Width="175px" />
</asp:TemplateField>
<asp:TemplateField HeaderText="Manager Level 2" ControlStyle-Width="175px">
<ItemTemplate>
<asp:Label ID="lblManager2" runat="server" Text=""></asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:DropDownList ID="cbManager2" runat="server"></asp:DropDownList>
</EditItemTemplate>
<ControlStyle Width="175px" />
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton ID="btnEdit" CommandName="Edit" runat="server" Text="Edit" CssClass="buttonStyle" CausesValidation="false"/>
</ItemTemplate>
<EditItemTemplate>
<asp:LinkButton ID="btnSave" CommandName="Update" runat="server" Text="Save" CssClass="buttonStyle" CausesValidation="false"/>
<asp:LinkButton ID="btnCancel" CommandName="Cancel" runat="server" Text="Cancel" CssClass="buttonStyle" CausesValidation="false" />
</EditItemTemplate>
</asp:TemplateField>
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton ID="btnDelete" CommandName="Delete" runat="server" Text="Delete" CssClass="buttonStyle" CausesValidation="false" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
The BoundField is populated in the Page_Load event as below:
Dim dHandler As DepartmentHandler = New DepartmentHandler
Dim depts As New List(Of Department)
depts = dHandler.GetDepartmentList
gvChain.DataSource = depts.
If Not Page.IsPostBack Then
gvChain.DataBind()
End If
Populating of the TemplateFields is then done in the RowDataBound event as below:
If e.Row.RowType = DataControlRowType.DataRow Then
If e.Row.RowState = DataControlRowState.Edit Then
Dim cbManager1 As DropDownList = TryCast(e.Row.FindControl("cbManager1"), DropDownList)
Dim cbManager2 As DropDownList = TryCast(e.Row.FindControl("cbManager2"), DropDownList)
Dim eHandler As EmployeeHandler = New EmployeeHandler
' Get the list of managers
Dim mgrs As New List(Of Manager)
mgrs = eHandler.GetManagerList
cbManager1.DataSource = mgrs
cbManager2.DataSource = mgrs
cbManager1.DataValueField = "Name"
cbManager1.DataTextField = "Name"
cbManager2.DataValueField = "Name"
cbManager2.DataValueField = "Name"
cbManager1.DataBind()
cbManager2.DataBind()
' Get the department name from the label in cell 0
Dim lbl As Label = e.Row.Cells(0).FindControl("lblDepartment")
Dim dept As Department = New Department
dept.Department = lbl.Text
' Pass the department name to the getManager1/2 functions to return the correct manager for that department
Dim mgr1 As Manager = eHandler.getManager1(dept)
Dim mgr2 As Manager = eHandler.getManager2(dept)
' Upper case the manager name to search the DDLs for item
Dim mgr1Name As String = mgr1.Name.ToUpper()
Dim mgr2Name As String = mgr2.Name.ToUpper()
' Find the manager in the DDL and select
cbManager1.SelectedValue = mgr1Name
cbManager2.SelectedValue = mgr2Name
Else
' If GV isnt in edit mode then populate labels in itemtemplate with manager 1 and 2 values
Dim lblManager1 As Label = DirectCast(e.Row.FindControl("lblManager1"), Label)
Dim lblManager2 As Label = DirectCast(e.Row.FindControl("lblManager2"), Label)
Dim eHandler As EmployeeHandler = New EmployeeHandler
Dim lbl As Label = e.Row.Cells(0).FindControl("lblDepartment")
Dim dept As Department = New Department
dept.Department = lbl.Text
Dim mgr1 As Manager = eHandler.getManager1(dept)
Dim mgr2 As Manager = eHandler.getManager2(dept)
lblManager1.Text = mgr1.Name
lblManager2.Text = mgr2.Name
End If
End If
I then have the below in the RowEditing event
gvChain.EditIndex = e.NewEditIndex
gvChain.DataBind()
When there is only 1 record displayed in the GridView, I click the edit button and the GridView goes into Edit mode I am able to update that record using the RowUpdating event and this works fine. However, if I add another record to the GridView, clicking on the edit button of that record gives a NullReference exception. If I then add another record, that 3rd record will go into edit mode. A 4th record will again fail with a NullReference exception and so on.
When debugging, it seems that on rows indexes 1,3,5 etc. the GridView doesn't go into edit mode however on row indexes 0, 2, 4 etc. the GridView will switch to edit mode.
This seems really strange behaviour. Any ideas what may be causing the GridView not to go into Edit mode on these rows?
A row's state can be one or a combination of the DataControlRowState values, so use bitwise operations to determine whether the state of the row includes a DataControlRowState value.
here
RowState contains more than one value (Alternate | Edit if you check RowState property during edit mode) using bit-logic.
Try
If (e.Row.RowState And DataControlRowState.Edit) > 0 Then
I got round this by amending the getDepartmentList function to return the Manager1 and Manager 2 fields then databinding them in the same was as I had bound 'Department'.
I then amended the RowDataBound event to the following:
If e.Row.RowType = DataControlRowType.DataRow Then
If e.Row.RowState And DataControlRowState.Edit Then
Dim cbManager1 As DropDownList = TryCast(e.Row.FindControl("cbManager1"), DropDownList)
Dim cbManager2 As DropDownList = TryCast(e.Row.FindControl("cbManager2"), DropDownList)
Dim eHandler As EmployeeHandler = New EmployeeHandler
' Get the list of managers
Dim mgrs As New List(Of Manager)
mgrs = eHandler.GetManagerList
cbManager1.DataSource = mgrs
cbManager2.DataSource = mgrs
cbManager1.DataValueField = "Name"
cbManager1.DataTextField = "Name"
cbManager2.DataValueField = "Name"
cbManager2.DataValueField = "Name"
cbManager1.DataBind()
cbManager2.DataBind()
' Get the department name from the label in cell 0
Dim lbl As Label = e.Row.Cells(0).FindControl("lblDepartment")
Dim dept As Department = New Department
dept.Department = lbl.Text
' Pass the department name to the getManager1/2 functions to return the correct manager for that department
Dim mgr1 As Manager = eHandler.getManager1(dept)
Dim mgr2 As Manager = eHandler.getManager2(dept)
' Upper case the manager name to search the DDLs for item
Dim mgr1Name As String = mgr1.Name.ToUpper()
Dim mgr2Name As String = mgr2.Name.ToUpper()
' Find the manager in the DDL and select
cbManager1.SelectedValue = mgr1Name
cbManager2.SelectedValue = mgr2Name
End If
End If
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()