无法从代码隐藏在FormView上加载DropDownList?

时间:2010-03-12 19:19:53

标签: asp.net .net drop-down-menu formview

我有一个UserControl,包含一个FormView,包含一个DropDownList。 FormView绑定到数据控件。

像这样:

<asp:FormView ID="frmEdit" DataKeyNames="MetricCode" runat="server" DefaultMode="Edit" DataSourceID="llbDataSource" Cellpadding="0" >
    <EditItemTemplate>
        <asp:DropDownList ID="ParentMetricCode"  runat="server" SelectedValue='<%# Bind("ParentMetricCode") %>' />
    </EditItemTemplate>
<asp:FormView>

我正在尝试从代码隐藏中填充DropDownList。如果这不包含在FormView中,我通常只会在Page_Load事件中执行此操作。但是,这在FormView中不起作用,因为我尝试这样做,在代码中访问下拉列表,即:

theListcontrol = CType(formView.FindControl(listControlName), ListControl)  

...调用FormView的数据绑定机制,当然,它试图将DropDownList绑定到底层数据源,导致**'ParentMetricCode'具有一个无效的SelectedValue,因为它不存在于项目清单。 “参数名称:值...”错误,因为还没有填充DropDownList。

我尝试在FormView的DataBinding()事件中执行加载,但随后:

theListcontrol = CType(formView.FindControl(listControlName), System.Web.UI.WebControls.ListControl)

...失败,因为此时FormView.Controls.Count = 0。

这不可能吗? (我不想使用辅助ObjectDataSource将下拉列表绑定到)

3 个答案:

答案 0 :(得分:4)

直接在OnDataBinding上实施DropDownList

将formview绑定到某些数据时,OnDataBinding的{​​{1}}将会触发。此时,您可以将所需的值加载到列表中,并将所选值绑定到加载的列表中。

以下是一个例子:

DropDownList

然后实现OnDataBinding:

<asp:DropDownList ID="ParentMetricCode"  runat="server" OnDataBinding="ParentMetricCode_DataBinding" />

当你的FormView protected void ParentMetricCode_DataBinding(object sender, System.EventArgs e) { DropDownList ddl = (DropDownList)(sender); // Fill the list items however you want ddl.Items.Add(new ListItem("1", "1")); ddl.Items.Add(new ListItem("2", "2")); // etc... // Set the selected value ddl.SelectedValue = Eval("ParentMetricCode").ToString(); } 时,一切都将开始发挥其魔力:)

此外,如果您从数据库或某些内容加载DataBind的列表数据,则可能需要对其进行缓存,因为每个“行”数据都会导致加载列表数据。

修改 既然你认为我不可能写一个快速的演示应用来证明它是如何工作的:

在您的aspx文件中包含以下内容:

DropDownList

然后在.cs文件中:

<asp:FormView ID="fvTest" runat="server">
    <ItemTemplate>
        <asp:DropDownList ID="ddlTest" runat="server" OnDataBinding="ddlTest_DataBinding"></asp:DropDownList>
    </ItemTemplate>
</asp:FormView>

运行代码...... public class MockData { public string ID { get; set; } public string Text { get; set; } } protected void Page_Load(object sender, EventArgs e) { List<MockData> lst = new List<MockData>(); lst.Add(new MockData() { ID = "3", Text = "Test3" }); fvTest.DataSource = lst; fvTest.DataBind(); } protected void ddlTest_DataBinding(object sender, System.EventArgs e) { DropDownList ddl = (DropDownList)(sender); ddl.Items.Add("1"); ddl.Items.Add("2"); ddl.Items.Add("3"); ddl.Items.Add("4"); ddl.Items.Add("5"); ddl.SelectedValue = Eval("ID").ToString(); } 将加载所有值,并设置为在模拟对象中设置的正确选定值。

我不知道还能做些什么来证明它更好......我认为你错过了DataBinding的实际工作方式。如果您尝试在DropDownList级别执行此操作,则在FormView实际绑定之前不会进行控制。当绑定发生时,您可以通过实现它的FormView事件来触发模板中的每个控件来执行某些操作。此时,绑定对象及其值的当前迭代可用,您可以在此处看到我的代码执行OnDataBinding

答案 1 :(得分:2)

对我来说,使用OnDataBound事件而不是在创建控件之前发生的OnDataBinding。

<asp:DropDownList ID="ddlCountry" runat="server" DataSourceID="SqlDataSrcCountries" AutoPostBack="True" DataTextField="name" DataValueField="code" OnDataBound="ddlCountry_DataBound">
</asp:DropDownList>

代码隐藏:

Protected Sub ddlCountry_DataBound(ByVal sender As Object, ByVal e As System.EventArgs)

    Dim ddlCountry As New DropDownList
    Dim strCountry As String = String.Empty
    Dim lstItemToFind As New ListItem

    ddlCountry = FormViewUsers.FindControl("ddlCountry")
    strCountry = Eval("country")
    lstItemToFind = ddlCountry.Items.FindByValue(strCountry)

    If (Not IsNothing(lstItemToFind)) Then
        ddlCountry.SelectedValue = strCountry
    End If

End Sub

如果您在除了您只需要验证的编辑之外的其他模板上使用此功能:

    If (FormViewUsers.CurrentMode = FormViewMode.Edit) Then

    End If

答案 2 :(得分:1)

好的,找到“一个”解决方案:
 1.从FormView_ItemCreated事件中调用DDL填充函数  2.修改代码以填充DDL,如下所示:

Public Overloads Shared Sub BindListControl(Of theLLBLgenEntityType As EntityBase) _   
        (ByVal formView As FormView, _
        ByVal listControlName As String, _
        ByVal theCollection As CollectionCore(Of theLLBLgenEntityType), _
        ByVal DataValueField As EntityField, _
        ByVal DataTextField As EntityField, _
        ByVal IncludeEmptyItem As Boolean)

    If formView.CurrentMode = FormViewMode.Edit Then
        Dim theListcontrol As System.Web.UI.WebControls.ListControl
        theListcontrol = CType(formView.FindControl(listControlName), System.Web.UI.WebControls.ListControl)

    For Each entity As theLLBLgenEntityType In theCollection
        theListcontrol.Items.Add(New ListItem(entity.Fields(DataTextField.Name).CurrentValue.ToString, entity.Fields(DataValueField.Name).CurrentValue.ToString))
    Next

    If IncludeEmptyItem Then 
        theListcontrol.Items.Insert(0, New ListItem("", ""))
    End If
End Sub

有点似乎基本上归结为,你不能在运行时以编程方式在FormView中进行额外的“数据绑定”。

(任何人都知道为什么我的代码的格式化在这篇文章中搞砸了?)

更新

此解决方案引发了另一批与插入新项目相关的问题。经过大量的拧紧后,我终于找到了解决方法。在这一点上,我基本上建议完全避免使用FormView控件,或者绝对避免以编程方式更改绑定控件。希望,也许为每个DropDownList使用单独的数据控件可能会更好,但这也可能是一厢情愿的想法。