字典<T>列表&lt;T&gt;和 ASP.NET 中的 ListViews [英] Dictionary&lt;T&gt; of List&lt;T&gt; and ListViews in ASP.NET

查看:20
本文介绍了字典<T>列表&lt;T&gt;和 ASP.NET 中的 ListViews的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

序言

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

背景

我有一堆 Foo 有一个与它们相关的项目列表(称为 Bar),我m 将它们从数据访问/业务逻辑层中提取为包含 Foo 及其关联的 Bars 的字典.我想将网页上的这些项目吐出到 ListView 中,其中包含左侧的 Foo.NameList 在下拉列表的右侧.(下面是我漂亮的 ASCII 艺术图):

列表视图

<前>------------------------------------------------------------------|项目名称 |DropDownList(列表的)||---------------------------------|_____________________ ||foo1 ||酒吧1 |v |||||_______________|___||------------------------------------------------------------------||DropDownList(列表的)|||_____________________ ||foo2 ||酒吧2 |v |||||_______________|___||------------------------------------------------------------------

好的,这是怎么回事.这是一个列表视图;这些项目从数据库中提取到 Dictionary>.我正在尝试从字典中获取键值以显示在项目名称"下,并尝试获取List<T>Bar' 以显示为 ListView 右侧的 DropDownList.

类图

<前>----------------- -----------------|福 ||酒吧 |----------------- -----------------|身份证 ||项目名称 ||姓名 ||项目价值 ||条码 |||----------------- -----------------

总结一下,我想将 Dictionary.Key "Name" 放入 ListView 的左侧,将 Dictionary.Value(恰好是一个列表)放入右侧的 DropdownList.

这样,对于每个键/值对,都会有一个名称和一个下拉列表来容纳每个键的值.

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

背后的代码:

 protected Dictionary>美食词典{得到;放;}protected void DataBindFooList(List SelectedFoos){System.Web.UI.WebControls.ListView lv = lvFooList;尝试{字典<Foo, List<Bar>>fooDictionary =new Dictionary>();foreach(SelectedFoos 中的 int Foo){//构建 Foos 列表以添加为 Dictionary.KeysfooDictionary.Add(fooScalar, Bar)}FooDictionary = fooDictionary;lv.DataSource = FooDictionary;lv.DataBind();ddlListOfBars.DataSource = FooDictionary;ddlListOfBars.DataValueField = "ItemValue";ddlListOfBars.DataTextField = "ItemName";ddlListOfBars.DataBind();}捕获(异常前){SetMessage(divFooMsg, "无法检索 Foos:" +ex.Message, true, true);}

ListView 代码:

<布局模板><asp:PlaceHolder runat="server" ID="itemPlaceholder"></asp:PlaceHolder></LayoutTemplate><ItemSeparatorTemplate><小时/></ItemSeparatorTemplate><项目模板><%#Eval("姓名")%><asp:DropDownList ID="ddlListOfBars" runat="server"></asp:DropDownList></ItemTemplate></asp:ListView>

<小时>

问题:

  1. 可以这样使用字典吗?
  2. 有什么关于我哪里出错的提示吗?(资源、提示等会有所帮助)
  3. 有没有更好的方法来做到这一点?
  4. 如果这个问题不清楚,请发表评论,以便我弄清楚如何改进它.

解决方案

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

<%#Eval("Key.Name") %><asp:下拉列表ID="ddlListOfBars"runat="服务器"DataSource='<%#Eval("Value")%>'数据值字段=项目值"DataTextField="项目名称"/></ItemTemplate>

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

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

<布局模板><asp:PlaceHolder runat="server" ID="itemPlaceholder"></asp:PlaceHolder></LayoutTemplate><ItemSeparatorTemplate><小时/></ItemSeparatorTemplate><项目模板><uc:ListViewContents DataItem='<%#Container.DataItem%>'/></ItemTemplate>

ListViewContents.ascx...

<asp:DropDownList ID="ddlListOfBars" runat="server"></asp:DropDownList>

ListViewContents.ascx.cs...

public KeyValuePair>数据项{得到;放;}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();}

Preamble

I'm asking this question because even though I've read through a lot of ListView resources, I'm still not 'getting' it.

Background

I have a bunch of Foo's that have a list of items associated with them (known as Bar), and I'm pulling them from the Data Access/Business Logic layer as Dictionary that holds a Foo and its associated Bars. I'd like to spit these items out in on the Webpage into a ListView that holds the Foo.Name on the left, and the List<Bar> on the right in a dropdownlist. (Shown with my beautiful ASCII art below):

ListView

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

Alright, here's what's going on. This is a ListView; The items are pulled from a database into a Dictionary<Foo, List<Bar>>. I'm trying to get the Key Value from the dictionary to show up under 'Name of Item', and am trying to get the `List<T> Bar' to show up as a DropDownList on the right side of the ListView.

Class Diagrams

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

So to recap, I want to place the Dictionary.Key "Name" into the left side of the ListView, and the Dictionary.Value (which happens to be a list) into a DropdownList on the right side.

So that, for every Key/Value pair, there'd be a Name and a dropdown list that would house each Key's Value.

But I'm running into problems (obviously), and am hoping someone can tell me what I'm doing wrong.

Code Behind:

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

The ListView Code:

<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>


The Question(s):

  1. Is it possible to use a Dictionary in this way?
  2. Any pointers on where I'm going wrong? (Resources, hints, etc. would help)
  3. Is there a better way to do this?
  4. If this question is clear as mud, please comment so I can figure out how to improve it.

解决方案

Your problem arises because it doesn't make sense to databind ddlListOfBars in DataBindFooList(), because there isn't just one DropDownList to databind. When you call lv.DataBind(), the ListView creates a copy of your ItemTemplate for each Foo, each containing a ddlListOfBars. You need to tell it to bind each DropDownList to the right List<Bar> as it goes. You can do this by setting the datasource of ddlListOfBars with data binding expressions rather than in the code behind:

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

Note that you also need to use "Key.Name" to get to the name property of your Foo. The individual dictionary items that you're binding to are KeyValuePair<Foo,List<Bar>>, which has a Key property and a Value property to access the Foo and List<Bar> respectively.

Edit
If you've got a lot going on in your ItemTemplate then it can be useful to move the contents out into a user control. The user control can have a strongly-typed property to access the DataItem, and has strongly-typed access to its child controls. This gets you the flexibility of the ItemDataBound event without all the the casting and FindControl() noise. I doubt I'd bother in this case, but it would go something like

<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>

ListViewContents.ascx...

<asp:Label ID="lbName" runat="server"/>
<asp:DropDownList ID="ddlListOfBars" runat="server"></asp:DropDownList>

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

这篇关于字典<T>列表&lt;T&gt;和 ASP.NET 中的 ListViews的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆