ASP.NET中List 和ListViews的Dictionary

前言

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

背景

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

列表显示

 -------------------------------------------------- ----------------
 | 物品名称|  DropDownList(List )|
 | --------------------------------- |  _____________________ |
 |  foo1 |  |  bar1 |  v |  |
 |  |  | _______________ | ___ |  |  
 -------------------------------------------------- ----------------
 |  |  DropDownList(List )|
 |  |  _____________________ |
 |  foo2 |  |  bar2 |  v |  |
 |  |  | _______________ | ___ |  |
 -------------------------------------------------- ----------------

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

类图

 ----------------- -----------------
 |  Foo |  | 酒吧|
 ----------------- -----------------
 |  Id |  |  ItemName |
 | 名称|  |  ItemValue |
 |  BarID |  |  |
 ----------------- -----------------

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

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

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

代码背后:

  protected Dictionary<Foo, List> FooDictionary { get; set; } protected void DataBindFooList(List SelectedFoos) { System.Web.UI.WebControls.ListView lv = lvFooList; try { Dictionary<Foo, List> fooDictionary = new Dictionary<Foo, List>(); 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代码:

      

问题:

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

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

  <%#Eval("Key.Name") %>   

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

编辑
如果你在ItemTemplate中有很多事情,那么将内容移到用户控件中会很有用。 用户控件可以具有强类型属性来访问DataItem,并且具有对其子控件的强类型访问。 这样就可以获得ItemDataBound事件的灵活性,而不会产生所有的转换和FindControl()噪声。 我怀疑在这种情况下我会烦恼,但它会有类似的东西

      

ListViewContents.ascx …

   

ListViewContents.ascx.cs …

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

这是你想要的东西:

       

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

  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() { new Bar() {ItemName = "bar1", ItemValue = "barV1"}, new Bar() {ItemName = "bar2", ItemValue = "barV2"} }; var fooKey2 = new Foo() {Name = "foo2"}; var barList2 = new List() { new Bar() {ItemName = "bar3", ItemValue = "barV3"}, new Bar() {ItemName = "bar4", ItemValue = "barV4"} }; var dicFooBar = new Dictionary>() {{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>)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(); } 

似乎做你想做的,但我的代码只是快速测试代码,所以要警告。 它确实按预期渲染。