Не возможно загрузить DropDownList на FormView из кода позади? - PullRequest
4 голосов
/ 12 марта 2010

У меня есть 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 еще не заполнен.

Я попытался выполнить загрузку в событии DataBinding () FormView, но затем:

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

... происходит сбой, так как FormView.Controls.Count = 0 в этой точке.

Разве это невозможно? (Я не хочу использовать вторичный ObjectDataSource для привязки выпадающего списка к)

Ответы [ 3 ]

4 голосов
/ 12 марта 2010

Реализация OnDataBinding прямо на вашем DropDownList.

Когда вы связываете свой вид формы с некоторыми данными, OnDataBinding для DropDownList срабатывает. Теперь вы можете загрузить нужные значения в список и привязать выбранное значение к загруженному списку.

Вот пример:

<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 из БД или чего-то еще, возможно, вы захотите их кэшировать, поскольку каждая «строка» данных будет вызывать загрузку данных списка.

EDIT: Поскольку вы думаете, что это невозможно, я написал небольшое демонстрационное приложение, чтобы доказать, как оно работает:

В вашем 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").

2 голосов
/ 31 мая 2011

Это работает для меня с событием 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

Если вы используете это на других шаблонах, кроме Edit, вам просто нужно подтвердить:

    If (FormViewUsers.CurrentMode = FormViewMode.Edit) Then

    End If
1 голос
/ 12 марта 2010

Хорошо, найдено «а» решение:
1. Вызвать функцию заполнения DDL из события FormView_ItemCreated.
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 будет работать лучше, но это может быть и желаемое за действительное.

...