ASP.NET中List <T>和ListViews的Dictionary <T>

Geo*_*ker 19 .net c# asp.net data-binding listview

前言

我问这个问题,因为即使我已经阅读了很多ListView资源,我仍然没有"得到"它.

背景

我有一堆Foo有与它们相关的项目列表(称为 Bar),我将它们从数据访问/业务逻辑层中拉出来作为包含a Foo及其关联的词典Bars.我想将这些项目在网页上吐出一个ListView保存Foo.Name在左侧,而List<Bar>在右侧的下拉列表中.(以下面我美丽的ASCII艺术所示):

列表显示

------------------------------------------------------------------
|           Name Of Item          |  DropDownList (of List<T>)   |
|---------------------------------|  _____________________       |
|                foo1             |  |     bar1      | v |       |
|                                 |  |_______________|___|       |  
------------------------------------------------------------------
|                                 |  DropDownList (of List<T>)   |
|                                 |  _____________________       |
|                foo2             |  |     bar2      | v |       |
|                                 |  |_______________|___|       |
------------------------------------------------------------------

好的,这是正在发生的事情.这是一个ListView; 这些项目从数据库中拉入Dictionary<Foo, List<Bar>>.我试图从字典中获取Key Value以显示在"Name of Item"下,并且我试图让`List <T> Bar'在ListView的右侧显示为DropDownList.

类图

-----------------          -----------------
|   Foo         |          |  Bar          |
-----------------          -----------------
|  Id           |          |  ItemName     |
|  Name         |          |  ItemValue    |
|  BarID        |          |               |
-----------------          -----------------

所以回顾一下,我想把Dictionary.Key"Name"放在ListView的左侧,将Dictionary.Value(恰好是一个列表)放到右侧的DropdownList中.

因此,对于每个Key/Value对,都会有一个Name和一个下拉列表,用于存放每个Key的Value.

但是我遇到了问题(显然),我希望有人可以告诉我我做错了什么.

代码背后:

  protected Dictionary<Foo, List<Bar>> FooDictionary
        {
            get; 
            set; 
        }

protected void DataBindFooList(List<int> SelectedFoos)
        {
            System.Web.UI.WebControls.ListView lv = lvFooList;

try
            {
                Dictionary<Foo, List<Bar>> fooDictionary =
                    new Dictionary<Foo, List<Bar>>();

                foreach (int Foo in SelectedFoos)
                {
                 // Build List of Foos to add as Dictionary.Keys
                 fooDictionary.Add(fooScalar, Bar)                     
                }
                FooDictionary = fooDictionary;
                lv.DataSource = FooDictionary;
                lv.DataBind();
                ddlListOfBars.DataSource = FooDictionary;
                ddlListOfBars.DataValueField = "ItemValue";
                ddlListOfBars.DataTextField = "ItemName";
                ddlListOfBars.DataBind();
            }
            catch (Exception ex)
            {
                SetMessage(divFooMsg, "Unable to retrieve Foos: " + 
                ex.Message, true, true);
            }
Run Code Online (Sandbox Code Playgroud)

ListView代码:

<asp:ListView ID="lvFooList" runat="server">
   <LayoutTemplate>
      <asp:PlaceHolder runat="server" ID="itemPlaceholder"></asp:PlaceHolder>
   </LayoutTemplate>
      <ItemSeparatorTemplate>
         <hr />
      </ItemSeparatorTemplate>
   <ItemTemplate>
      <%#Eval("Name") %>
      <asp:DropDownList ID="ddlListOfBars" runat="server"></asp:DropDownList>
    </ItemTemplate>
   </asp:ListView>
Run Code Online (Sandbox Code Playgroud)

问题:

  1. 是否有可能以这种方式使用词典?
  2. 关于我哪里出错的指示?(资源,提示等会有所帮助)
  3. 有一个更好的方法吗?
  4. 如果这个问题很明显,请发表评论,以便我可以弄清楚如何改进它.

ste*_*son 9

您的问题出现是因为在DataBindFooList()中数据绑定ddlListOfBars没有意义,因为数据绑定不只有一个DropDownList.当您调用lv.DataBind()时,ListView会为每个Foo创建一个ItemTemplate副本,每个Foo包含一个ddlListOfBars.您需要告诉它将每个DropDownList绑定到正确的List <Bar>.您可以通过使用数据绑定表达式而不是后面的代码设置ddlListOfBars的数据源来执行此操作:

<ItemTemplate>
  <%#Eval("Key.Name") %>
  <asp:DropDownList
        ID="ddlListOfBars"
        runat="server"
        DataSource='<%#Eval("Value")%>'
        DataValueField="ItemValue"
        DataTextField="ItemName" />
</ItemTemplate>
Run Code Online (Sandbox Code Playgroud)

请注意,您还需要使用"Key.Name"来获取Foo的name属性.您绑定的各个字典项是KeyValuePair <Foo,List <Bar >>,它具有Key属性和Value属性,分别用于访问Foo和List <Bar>.

编辑
如果您在ItemTemplate中进行了很多操作,那么将内容移动到用户控件中会很有用.用户控件可以具有强类型属性来访问DataItem,并且具有对其子控件的强类型访问.这为您提供了ItemDataBound事件的灵活性,而没有所有的转换和FindControl()噪声.我怀疑在这种情况下我会烦恼,但它会像是一样

<asp:ListView ID="lvFooList" runat="server">
<LayoutTemplate>
  <asp:PlaceHolder runat="server" ID="itemPlaceholder"></asp:PlaceHolder>
</LayoutTemplate>
  <ItemSeparatorTemplate>
     <hr />
  </ItemSeparatorTemplate>
<ItemTemplate>
  <uc:ListViewContents DataItem='<%# Container.DataItem %>' />
</ItemTemplate>
Run Code Online (Sandbox Code Playgroud)

ListViewContents.ascx ...

<asp:Label ID="lbName" runat="server"/>
<asp:DropDownList ID="ddlListOfBars" runat="server"></asp:DropDownList>
Run Code Online (Sandbox Code Playgroud)

ListViewContents.ascx.cs ...

public KeyValuePair<Foo,List<Bar>> DataItem
{
    get; set;
}

protected override void OnDataBinding(EventArgs e)
{
    base.OnDataBinding(e);

    lbName.Text = DataItem.Key.Name;

    ddlListOfBars.DataTextField = "ItemName";
    ddlListOfBars.DataValueField = "ItemValue";
    ddlListOfBars.DataSource = DataItem.Value;
    ddlListOfBars.DataBind();   
}
Run Code Online (Sandbox Code Playgroud)