Accessing Controls on ListView Edit Command

2020-05-08 07:02发布

问题:

In my ListView I have an ItemTemplate and EditItemTemplate which look something like this, respectively.

------->

When I click the "Edit" button, and it switches to the EditItemTemplate view on the right, I want to prefill the Textbox and select the corresponding option in the DropDownList. How can I do this?

Before you say to use something like the following, please know that I've already explored every possible variation I can think of. Sorry to be so demanding, but please be prepared to walk me through this one if you answer. ^.^ I've been stuck on this issue for literally months :(

Dim lv As ListView = DirectCast(sender, ListView) 'sender is the ListView on the ItemCommand event
Dim ddl As DropDownList = DirectCast(lv.Items(0).FindControl("NewProductName_ddl"), DropDownList)
Dim tb As TextBox = DirectCast(lv.Items(0).FindControl("NewProductName_tb"), TextBox)

UPDATE - RAWR!!

Oh my freaking goodness, SO CLOSE, but no cigar. The following code worked for prefilling when only one item was in the ListView, but when more than one items exist, it throws a NullReferenceException :(

'PROBLEM WAS HERE: Compare to the working code in my answer.
Protected Sub NewProduct_ItemDataBound(ByVal sender As ListView, ByVal e As ListViewItemEventArgs) Handles NewProduct.ItemDataBound
    If sender.EditIndex > -1 Then
        Dim ddl As DropDownList = DirectCast(e.Item.FindControl("NewProductName_ddl"), DropDownList)
        Dim tb As TextBox = DirectCast(e.Item.FindControl("NewProductName_cb"), TextBox)

        ddl.Items.FindByValue(sender.DataKeys(sender.EditIndex)("ID").ToString).Selected = True 'Prefills the DropDownList
        tb.Text = sender.DataKeys(sender.EditIndex)("Product").ToString 'Prefills the TextBox
    End If
End Sub

回答1:

EUREKA!!

I am elated beyond imagination!! All caps, nor bold do justice to how happy I am right now :)

First I wanna give props to this question which got me pointed in the right direction. Now onto the answer, which is the most ideal variation I have found of the answer provided in the above link:

The ItemDataBound event is the key, but it's important to note that this event will fire for each item that exists in your ListView and for that reason, you must be careful in your approach. Here are two options that worked equally well for me.

Option 1 - Most elegant; only runs FindControl on the item in question rather than all items.

Protected Sub NewProduct_ItemDataBound(ByVal sender As ListView, ByVal e As ListViewItemEventArgs) Handles NewProduct.ItemDataBound
    Dim i As Integer = sender.EditIndex
    If i = e.Item.DataItemIndex Then
        Dim ddl As DropDownList = DirectCast(e.Item.FindControl("NewProductName_ddl"), DropDownList)
        Dim tb As TextBox = DirectCast(e.Item.FindControl("NewProductName_cb"), TextBox)

        ddl.Items.FindByValue(sender.DataKeys(i)("ID").ToString).Selected = True 'Prefills the DropDownList
        tb.Text = sender.DataKeys(i)("Product").ToString 'Prefills the TextBox
    End If
End Sub

Option 2 - Based on the referenced question, but with a crucial check to ensure non-null object.

Protected Sub NewProduct_ItemDataBound(ByVal sender As ListView, ByVal e As ListViewItemEventArgs) Handles NewProduct.ItemDataBound
    Dim i As Integer = sender.EditIndex
    If i > -1 Then
        Dim ddl As DropDownList = DirectCast(e.Item.FindControl("NewProductName_ddl"), DropDownList)
        Dim tb As TextBox = DirectCast(e.Item.FindControl("NewProductName_cb"), TextBox)

        If Not IsNothing(ddl) Then
            ddl.Items.FindByValue(sender.DataKeys(i)("ID").ToString).Selected = True 'Prefills the DropDownList
        End If
        If Not IsNothing(tb) Then
            tb.Text = sender.DataKeys(i)("Product").ToString 'Prefills the TextBox
        End If
    End If
End Sub

I may make improvements to this answer later, but this did the trick for me. :)



回答2:

Great post! I had the same problem and you saved me hours of trial and error. Just wanted to point out that when using your first option with .NET Framework 3.5 or lower, DataItemIndex isn't available. To work around it you can replace

If i = e.Item.DataItemIndex Then

With

If i = DirectCast(e.Item, IDataItemContainer).DataItemIndex Then