Okay, so I'm having issues getting the value of a DropDownList that's inside of a TemplateField when updating my GridView. Originally I was using the RowCommand event to check the command name and then performing the appropriate task (update/delete), but I had problems with the event firing twice, so I switched it out for separate events (RowUpdating, RowDeleting). After doing this, FindControl is returning null every time. Just FYI, the gridview is inside of an UpdatePanel that has an AsyncPostBackTriggers for RowEditing, RowUpdating and RowDeleting events.
Here's my TemplateField inside of the GridView:
<asp:TemplateField HeaderText="Type">
<ItemTemplate>
<asp:Label
ID="lblMedTypeEdit"
Text='<%# Bind("medDesc") %>'
runat="server">
</asp:Label>
</ItemTemplate>
<EditItemTemplate>
<asp:DropDownList
ID="ddlMedTypeEdit"
DataSourceID="srcMedTypes"
SelectedValue='<%# Bind("medtype") %>'
runat="server"
DataTextField="medDesc"
DataValueField="medCode">
</asp:DropDownList>
</EditItemTemplate>
</asp:TemplateField>
Here is the code I'm using inside of
Protected Sub gvCurrentMeds_RowUpdating(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewUpdateEventArgs) Handles gvCurrentMeds.RowUpdating
Dim intRowIndex As Integer = e.RowIndex
Dim ddlMedType As DropDownList = CType(Me.gvCurrentMeds.Rows(intRowIndex).Cells(1).FindControl("ddlMedTypeEdit"),DropDownList)
End Sub
I also tried using a recursive function to find the control (below), but it is still returning back null.
Public Function FindControlRecursive(ByVal root As Control, ByVal id As String) As Control
If root.ID = id Then
Return root
End If
For Each c As Control In root.Controls
Dim t As Control = FindControlRecursive(c, id)
If Not t Is Nothing Then
Return t
End If
Next
Return Nothing
End Function
If you just want to know what the new value of the dropdown is, this is already provided for you in the NewValues property of the GridViewUpdateEventArgs object passed to the event handler.
In your example, e.NewValues["medtype"] should be the updated value.
You've already specified <%# Bind(...) %> on the dropdown, so ASP.NET will do the work of finding the controls and getting the new values for you - you don't have to plumb the control hierarchy yourself.
Related
I have a GridView. When I go into edit mode on a row, I want one of the columns to be a dropdown. My first draft included this:
<asp:TemplateField HeaderText="Type">
<ItemTemplate>
<%# Eval("type_name") %>
</ItemTemplate>
<EditItemTemplate>
<asp:DropDownList ID="ctlItemType" runat="server" datasourceid="dsItemTypes"
DataTextField="name" DataValueField="id"
selectedvalue='<%# Bind("item_type_id") %>' />
</EditItemTemplate>
</asp:TemplateField>
I should clarify that my data source included "type_name" as the name of the type and "item_type_id" as the ID corresponding to that name. That worked great. Cool.
But I need to restrict the values appearing in the drop down depending on other data about the record. So okay, fine, I removed the datasourceid, and instead populated the dropdown with code:
Private Sub ItemsGridView_RowDataBound(sender As Object, e As GridViewRowEventArgs)
Handles ItemsGridView.RowDataBound
If e.Row.RowState = DataControlRowState.Edit Then
Dim ctlItemType As DropDownList = e.Row.FindControl("ctlItemType")
Dim parent_id = ItemsGridView.DataKeys(e.Row.RowIndex).Values(1)
ctlItemType.DataSource = ItemTypeActions.List(parent_id)
ctlItemType.DataBind()
End If
End Sub
That blows up with a "SelectedValue not found" error, I presume because it's trying to set the selected value before I populate the values.
So I tried setting the SelectedValue in code also. After the DataBind above I added:
ctlItemType.SelectedValue = DataBinder.Eval(e.Row.DataItem, "item_type_id")
That displays fine when I go into edit mode, but when I click "Update", it blows up, because item_type_id doesn't get included in the list of parameters passed to the update function. Because it's not Bind'ed, it's just set with an Eval.
So how do I make this work? Is there a way to bind a control to a datasource with code? I could find anything like DataBinder.Eval that is equivalent to <%# bind("whatever") %>. Or ... what?
I have a Gridview column called "Path" and when the user clicks on it I want it to pass that value of the "Path" cell to a sub procedure to execute the following code,
process.start(Path)
Currently the table is filled via SQL query and the "Path" is clickable but it wants to take me to URL which won't work for my situation. I also tried the Hyperlink column as well but was having the same problem. Any guidance would be appreciated! Thanks in advance.
You could use a LinkButton instead of a HyperLink.
Set the CommandArgument on the LinkButton, you could use either the GridView.RowCommand event handler or a LinkButton.OnClick event handler to call your sub.
<asp:GridView ID="gridView" runat="server" AutoGenerateColumns="False" OnRowCommand="gridView_RowCommand">
<Columns>
<asp:TemplateField HeaderText="Path">
<ItemTemplate>
<asp:LinkButton ID="lbPath" runat="server" CommandArgument="<%# Eval("Path")%>" OnClick="lbPath_Click"></asp:LinkButton>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
Then in code behind:
Protected Sub lbPath_Click(sender As Object, e As EventArgs)
Dim linkButton As LinkButton = CType(sender, LinkButton)
Process.Start(linkButton.CommandArgument)
End Sub
For reference
https://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.linkbutton(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.gridview.rowcommand(v=vs.110).aspx
Here is the setup:
I programmatically populate my gridview using LINQ to SQL query. Then I enter the edit mode and want to replace some standard TextBox controls with DropDownLists like this:
'excerpt from GridView1_RowEditing
Dim ddlist1 As New DropDownList
Dim res1 = From items1 In mydb.Items
Select items1.Col10
ddlist1.DataSource = res1
ddlist1.DataBind()
GridView1.Rows.Item(0).Cells(1).Controls.Add(ddlist1)
At this moment I have my gridview showing standard textbox control and new DDList control (in the Column 1).
The problem is -- I cant read the value from DDList in the RowUpdating method. It seems like DDList control is not in the GridView1.Rows.Item(0).Cells(1).Controls collection.
RowUpdating method sees only standard TextBox control and can read it's value.
Any suggestions are welcome. I just don't understand something here :(
Use TemplateField, and then you can locate your dropdown using FindControl
<asp:GridView ID="GridView1" runat="server">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
</ItemTemplate>
<EditItemTemplate>
<asp:DropDownList ID="DropDownList1" runat="server">
</asp:DropDownList>
</EditItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
...
Protected Sub GridView1_RowUpdating(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewUpdateEventArgs) Handles GridView1.RowUpdating
Dim ddl = CType(GridView1.Rows(e.RowIndex).Cells(1).FindControl("DropDownList1"), DropDownList)
End Sub
I want to access the data associated with the RepeaterItem in which an ItemCommand fired up. The scenario is, I have multiple RepeaterItems which Button controls in which the Command is set declaratively like this:
<asp:Repeater ID="Repeater3"
runat="server"
DataSource='<%# ClientManager.GetClientEmployees(Eval("ClientID")) %>'
OnItemCommand="RemoveEmployeeFromClient">
<ItemTemplate>
<asp:LinkButton ID="LinkButton1"
runat="server"
Text="(x)"
CommandName="RemoveEmployeeFromClient">
</asp:LinkButton>
</ItemTemplate>
<SeparatorTemplate>,<br /></SeparatorTemplate>
</asp:Repeater>
The code behind is:
Protected Sub RemoveEmployeeFromClient(ByVal source As Object,
ByVal e As RepeaterCommandEventArgs)
' I want to access the data associated with
' the RepeaterItem which the Button was clicked.
End Sub
You can use e.Item.DataItem to get down to the data for the object, or you could store it in a hidden field.
Building on what Mitchel said, make sure you check to see that the RowType is DataRow. Don't want to do crap when you can't. The cast from e.Item.DataItem to your type would fail on the header or footer row.
In a detailsview, how can I prepopulate one of the textboxes on the insertcommand (When the user clicks insert and the view is insert).
I think this would work for codebehind:
Dim txtBox As TextBox = FormView1.FindControl("txtbox")
txtbox.Text = "Whatever I want"
Is this right? What do I need in the aspx (not as sure)? Also, I'm assuming the server-side code will go in the itemcommand or insertcreating event.
I have typed this in VB.NET but I am using C# (I can do both so on a language agnostic forum I might type the problem in another language). I am also using a SqlDataSource, with my parameters and insert/delete/edit commands all created.
I am trying to generate a random GUID (using the GUID object), which will be prepopulated in the textbox.
Also, is the postbackurl property of a button not another way of preserving form state?
Thanks
I would update the field in the DetailsView to a TemplateField:
<asp:TemplateField>
<InsertItemTemplate>
<asp:TextBox ID="txtField" runat="server" Text='<%# Bind("GUID") %>'/>
</InsertItemTemplate>
<ItemTemplate>
<asp:Label ID="lblField" runat="server" Text='<%# Bind("GUID") %>'/>
</ItemTemplate>
</asp:TemplateField>
Then you have two options:
generate your GUID and insert into
your datasource. This may have to be done with SQL since you mentioned using SqlDataSource
remove the binding and access the controls from code in the
DataBound event of your DetailsView
Private Sub dv_DataBound(ByVal sender As Object, ByVal e As EventArgs) Handles dv.DataBound
dim txt as Textbox = dv.FindControl("txtField")
txt.Text = GenerateGUID()
End Sub
I'm guessing you need to use one of detailsview events.
Hook up to ItemCommand, ModeChanging or ModeChanged events and fill your value there.
I am doing something like this as well. I am hiding the DetailsView and showing it when the user clicks a button.
dvDetails.ChangeMode(DetailsViewMode.Insert)
pnlDetailMenu.Visible = True
Dim ColumnTextBox As TextBox
ColumnTextBox = dvDetails.Rows(0).Cells(1).Controls(0)
If Not ColumnTextBox Is Nothing Then
ColumnTextBox.Text = "Initial Value"
End If