字典< T>列表< T>和ASP.NET中的ListViews
我问这个问题,因为即使我已经阅读了很多ListView资源,我还没有得到。
I'm asking this question because even though I've read through a lot of ListView resources, I'm still not 'getting' it.
我有一堆 Foo
它们具有与它们相关联的项目列表(被称为 Bar
),我将它们从数据访问/业务逻辑图层作为词典保存 Foo
及其关联的栏
。我想在网页上将这些项目吐出一个 ListView
,其中包含 Foo.Name
左边,右下角的列表< Bar>
。 (如下图所示):
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):
------------------------------------------------------------------
| Name Of Item | DropDownList (of List<T>) |
|---------------------------------| _____________________ |
| foo1 | | bar1 | v | |
| | |_______________|___| |
------------------------------------------------------------------
| | DropDownList (of List<T>) |
| | _____________________ |
| foo2 | | bar2 | v | |
| | |_______________|___| |
------------------------------------------------------------------
好的,这是发生了什么。这是一个ListView;这些项目从数据库被拉到 Dictionary< Foo,List< Bar>
中。我试图从字典中获取键值,显示在项目名称下,我试图获得List< T> Bar'在ListView右侧显示为DropDownList。
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.
----------------- -----------------
| Foo | | Bar |
----------------- -----------------
| Id | | ItemName |
| Name | | ItemValue |
| BarID | | |
----------------- -----------------
所以要回顾一下,我想将Dictionary.KeyName放在ListView的左侧,并将Dictionary.Value(恰好是一个列表)放在一个DropdownList上右边。
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.
所以,对于每个Key / Value对,都会有一个名称和一个下拉列表,可以容纳每个Key的价值。
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.
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代码:
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):
- 可以用这种方式使用字典吗?
- 任何指向我出错的指针? (资源,提示等)将有帮助)
- 有更好的方法吗?
- 如果这个问题是泥泞的话,请评论,所以我可以弄清楚如何改善它。
- Is it possible to use a Dictionary in this way?
- Any pointers on where I'm going wrong? (Resources, hints, etc. would help)
- Is there a better way to do this?
- If this question is clear as mud, please comment so I can figure out how to improve it.
在DataBindFooList()中对数据绑定ddlListOfBars有意义,因为没有一个DropDownList用于数据绑定。当调用lv.DataBind()时,ListView会为每个Foo创建一个ItemTemplate的副本,每个都包含一个ddlListOfBars。您需要告诉它将每个DropDownList绑定到正确的List< Bar>就这样您可以通过使用数据绑定表达式设置数据源ddlListOfBars而不是在代码后面:
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>
请注意,您还需要使用Key.Name获取您的Foo的名称属性。您绑定到的各个字典项目是KeyValuePair< Foo,List< Bar>>,其具有访问Foo和List< Bar>的Key属性和Value属性。
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.
编辑
如果您在ItemTemplate中有很多事情,那么这对于将内容移动到用户控件中。用户控件可以具有访问DataItem的强类型属性,并且具有对其子控件的强类型访问。这可以让您具有ItemDataBound事件的灵活性,而不需要所有的转换和FindControl()噪声。我怀疑我会在这种情况下烦恼,但它会像
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 ...
ListViewContents.ascx...
<asp:Label ID="lbName" runat="server"/>
<asp:DropDownList ID="ddlListOfBars" runat="server"></asp:DropDownList>
ListViewContents.ascx.cs ...
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();
}