【问题标题】:Dictionary<T> of List<T> and ListViews in ASP.NETASP.NET 中 List<T> 和 ListViews 的 Dictionary<T>
【发布时间】:2010-10-09 16:20:22
【问题描述】:

序言

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

背景

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

列表视图

-------------------------------------------------- ---------------- |物品名称 | DropDownList (List) | |----------------------------------| _____________________ | | foo1 | |酒吧1 | v | | | | |_______________|___| | -------------------------------------------------- ---------------- | | DropDownList (List) | | | _____________________ | | foo2 | |酒吧2 | v | | | | |_______________|___| | -------------------------------------------------- ----------------

好的,这就是正在发生的事情。这是一个列表视图;这些项目从数据库中提取到Dictionary&lt;Foo, List&lt;Bar&gt;&gt;。我试图从字典中获取键值以显示在“项目名称”下,并试图让“List Bar”显示为 ListView 右侧的 DropDownList。

类图

----------------- ----------------- |福 | |酒吧 | ----------------- ----------------- |身份证 | |物品名称 | |姓名 | |项目价值 | |条码 | | | ----------------- -----------------

回顾一下,我想将 Dictionary.Key “Name” 放入 ListView 的左侧,并将 Dictionary.Value(恰好是一个列表)放入右侧的 DropdownList 中。

因此,对于每个键/值对,都会有一个名称和一个下拉列表,其中包含每个键的值。

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

代码隐藏:

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

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>

问题:

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

【问题讨论】:

  • +1 写得很好的问题。我几乎找不到任何可以破解和削减的东西!
  • FooDictionary 是从哪里来的,为什么要赋值 FooDictionary = fooDictionary;和 lv.DataSource = FooDictionary;?
  • Manu:在那个 foreach 语句中有很多巫术。本质上,它通过 Foo 和与该 foo 关联的 Bars 创建一个字典。我只是为了方便而展示了最终产品。数据源不应该是 FooDictionary 以便获得名称吗?

标签: c# .net asp.net data-binding listview


【解决方案1】:

你想要这样的东西吗:

   <asp:ListView ID="lvFooList" runat="server">
    <LayoutTemplate>
      <asp:PlaceHolder runat="server" ID="itemPlaceholder"></asp:PlaceHolder>
    </LayoutTemplate>
      <ItemSeparatorTemplate>
         <hr />
      </ItemSeparatorTemplate>
    <ItemTemplate>
      <asp:Label ID="lbName" runat="server"/>
      <asp:DropDownList ID="ddlListOfBars" runat="server"></asp:DropDownList>
    </ItemTemplate>
   </asp:ListView>

然后我写了一个非常快速的讨厌的测试

    public class Foo
    {
        public string Name;
    }

    public class Bar
    {
        public string ItemName { get; set; }
        public string ItemValue { get; set; }
    }

    protected void Page_Load(object sender, EventArgs e)
    {

        var fooKey1 = new Foo() {Name = "foo1"};
        var barList1 = new List<Bar>()
               {
                   new Bar() {ItemName = "bar1", ItemValue = "barV1"},
                   new Bar() {ItemName = "bar2", ItemValue = "barV2"}
               };
        var fooKey2 = new Foo() {Name = "foo2"};
        var barList2 = new List<Bar>()
               {
                   new Bar() {ItemName = "bar3", ItemValue = "barV3"},
                   new Bar() {ItemName = "bar4", ItemValue = "barV4"}
               };

        var dicFooBar = new Dictionary<Foo, List<Bar>>() {{fooKey1, barList1}, {fooKey2, barList2}};

        lvFooList.ItemDataBound += lvFooList_ItemDataBound;
        lvFooList.DataSource = dicFooBar;
        lvFooList.DataBind();
    }

    void lvFooList_ItemDataBound(object sender, ListViewItemEventArgs e)
    {
        var dataItem = (ListViewDataItem)e.Item;
        var fooBarList = (KeyValuePair<Foo, List<Bar>>)dataItem.DataItem;

        ((Label) dataItem.FindControl("lbName")).Text = fooBarList.Key.Name;

        var ddlListOfBars = (DropDownList) dataItem.FindControl("ddlListOfBars");
        ddlListOfBars.DataTextField = "ItemName";
        ddlListOfBars.DataValueField = "ItemValue";
        ddlListOfBars.DataSource = fooBarList.Value;
        ddlListOfBars.DataBind();
    }

似乎做你想做的,但我的代码只是快速测试代码,所以要注意。它确实按预期呈现。

【讨论】:

    【解决方案2】:

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

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

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

    编辑
    如果您在 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>
    

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

    【讨论】:

      猜你喜欢
      • 2015-10-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-06
      • 2012-06-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多