【问题标题】:Not possible to load DropDownList on FormView from code behind?无法从后面的代码加载 FormView 上的 DropDownList?
【发布时间】:2010-03-12 19:19:53
【问题描述】:

我有一个 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 将下拉列表绑定到)

【问题讨论】:

  • 您究竟为什么要尝试从代码隐藏中填充下拉列表?你能把它绑定到一个单独的数据源吗?
  • 我不需要,但我想。我不喜欢数据源控件,我将一个用于主数据源的唯一一个是这样我可以使用双向数据绑定......但我发现它不值得。

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


【解决方案1】:

直接在您的DropDownList 上实现OnDataBinding

当您将表单视图绑定到某些数据时,DropDownListOnDataBinding 将触发。此时,您可以将所需的值加载到列表中,并将选定的值也绑定到加载的列表中。

这是一个例子:

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

然后实现 OnDataBinding:

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你的FormView时,一切都会开始发挥它的魔力:)

此外,如果您从数据库中加载 DropDownList 的列表数据,或者您可能想要缓存它,因为每“行”数据都会导致列表数据的加载。

编辑: 既然你认为这不可能,我写了一个快速演示应用程序来证明它是如何工作的:

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

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

然后在你的 .cs 文件中:

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();
 }

运行代码...DropDownList 将加载所有值并设置为在模拟对象中设置的正确选定值。

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

【讨论】:

  • 不幸的是,不能这样做.... FormView 上的控件在后面的代码中不可见....这就是为什么必须这样做:theListcontrol = CType(formView.FindControl(listControlName), System .Web.UI.WebControls.ListControl)....然后让我重新陷入混乱,我什么时候可以访问这个控件(即:它已被创建),但在实际的 FormView 数据绑定发生之前。如果此处不涉及 FormView,则您的示例将起作用....但是,我不会遇到此问题! :)
  • 它应该像网格视图一样工作。您没有直接访问权限,但可以通过 onDataBinding 方法访问。试试看,它有效。这就是所有可绑定模板控件的工作方式。
  • 这是你失败的地方:ddl.SelectedValue = Eval("ID").ToString();我认为你已经失去了两种数据绑定方式,对吧?否则,你为什么要这么做?在您的示例代码中,您使用的是 DropDownList.Add(ListItem) 语法...在我给出的示例中,我也是这样做的,因为看起来问题是您不能混合您的“DataBind”类型.我可能已经能够在不同的活动中做我的,但在这一点上它的学术性,我只是想让这个工作。但是您的代码行: ddl.SelectedValue = Eval("ID").ToString();对我来说失败了。
  • ddl.SelectedValue = Eval("ID").ToString(); 怎么会失败???这就是您如何在不使用自动分配的情况下按名称从当前项目中提取绑定数据的方式,而自动分配实际上只是在后台进行。我看不出Bind("ParentMetricCode") 做得更好……这对我来说更失败。
  • 我的意思是,您在实现中丢失了两种方式的数据绑定。对吗?
【解决方案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

【讨论】:

  • 这在类似的情况下对我有用,并且更容易实现。唯一的问题是我没有按照示例从 aspx 标记中删除SelectedValue,否则常规绑定首先进入并出现错误。已删除、测试、完成。
【解决方案3】:

好的,找到“a”解决方案:
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 使用单独的数据控件可能会更好,但这也可能是一厢情愿的想法。

【讨论】:

  • 由于上面的列表,帖子中的代码格式不好。看起来代码在某处也缺少 End If 语句。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-27
  • 1970-01-01
  • 1970-01-01
  • 2014-02-04
相关资源
最近更新 更多