我有这个C#类:
public class Option
{
public int OptionId { get; set; }
public string OptionName { get; set; }
public string OptionType { get; set; } //Three different types A,B,C
public int SortOrder { get; set; } //100-199, 200-299, etc.
}
GetOptions返回一个数组Option []。
现在我想要的是什么:
首先:按OptionType对选项进行分组
然后:通过SortOrder对第一组中的项目进行分组,条件是SortOrder在100-199之间的选项应该在一个组中,200-299在另一个组中,等等。
我能够做第一个:
IEnumerable<IGrouping<string, Option>> groupedOptions =
from option in options
group option by option.OptionType;
或者
var groupedOptions2 = options.GroupBy(p=>p.OptionType);
其次我不知道怎么做。我尝试添加另一个GroupBy但是没有用。当然做错了。
感谢。
更新: 我使用嵌套转发器工作,但我不确定这是否正确。
我使用上面的第一个查询获取选项:groupedOptions
将它绑定到Repeater。在该Repeater中显示OptionType。 在转发器的数据绑定事件中,我做了另一个分组:
IGrouping<OptionType, Option> itm =(IGrouping<OptionType, Option>) e.Item.DataItem;
IEnumerable<IGrouping<int, Option>> nestedGroupedOptions =
from option in itm
group option by option.SortOrder/100;
然后我将它绑定到具有checkboxlist的内部转发器。 这是我的整个.aspx测试页面。它是一个独立页面,可以通过将其放入asp.net webforms网站进行测试。
<%@ Page Language="C#" %>
<!DOCTYPE html>
<script runat="server">
Dictionary<int, string> OptionGroupNames = null;
protected void Page_Load(object sender, EventArgs e)
{
OptionGroupNames = GetOptionGroupNames();
DisplayDrinks();
}
public void DisplayDrinks()
{
Option[] options = GetOptions();
IEnumerable<IGrouping<OptionType, Option>> groupedOptions =
from option in options
group option by option.OptionType;
rptrGroupOptions.DataSource = groupedOptions;
rptrGroupOptions.DataBind();
}
protected void rptrGroupOptions_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
IGrouping<OptionType, Option> itm = (IGrouping<OptionType, Option>)e.Item.DataItem;
Label lblHeader = e.Item.FindControl("lblOptionGroup") as Label;
Repeater rptrOptions = e.Item.FindControl("rptrOptions") as Repeater;
lblHeader.Text = itm.Key.ToString();
IEnumerable<IGrouping<int, Option>> groupedOptions =
from option in itm
group option by option.SortOrder / 100;
rptrOptions.DataSource = groupedOptions;
rptrOptions.DataBind();
}
}
protected void rptrOptions_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
IGrouping<int, Option> itm = (IGrouping<int, Option>)e.Item.DataItem;
CheckBoxList cbl = e.Item.FindControl("cblOptions") as CheckBoxList;
Label lblOptionGroup = e.Item.FindControl("lblOptionGroupNum") as Label;
if (itm.Key != 1 && itm.Key != 2)
{
lblOptionGroup.Text = OptionGroupNames.First(p => p.Key == itm.Key).Value;
}
cbl.DataSource = itm;
cbl.DataBind();
}
}
public Option[] GetOptions()
{
var Options = new Option[]{
new Option{OptionId=1, DisplayName="Green", OptionType = OptionType.Tea, SortOrder=100},
new Option{OptionId=2, DisplayName="Black", OptionType = OptionType.Tea, SortOrder=101},
new Option{OptionId=3, DisplayName="French", OptionType = OptionType.Coffee, SortOrder=202},
new Option{OptionId=4, DisplayName="Espresso", OptionType = OptionType.Coffee, SortOrder=206},
new Option{OptionId=4, DisplayName="Cappuccino", OptionType = OptionType.Coffee, SortOrder=250},
new Option{OptionId=1, DisplayName="Coke", OptionType = OptionType.Drinks, SortOrder=300},
new Option{OptionId=2, DisplayName="Pepsi", OptionType = OptionType.Drinks, SortOrder=301},
new Option{OptionId=3, DisplayName="Sprite", OptionType = OptionType.Drinks, SortOrder=302},
new Option{OptionId=4, DisplayName="Apple Juice", OptionType = OptionType.Drinks, SortOrder=406},
new Option{OptionId=1, DisplayName="Orange Juice", OptionType = OptionType.Drinks, SortOrder=400},
new Option{OptionId=2, DisplayName="Wine", OptionType = OptionType.Drinks, SortOrder=501},
new Option{OptionId=3, DisplayName="Beer", OptionType = OptionType.Drinks, SortOrder=502},
new Option{OptionId=4, DisplayName="Rum", OptionType = OptionType.Drinks, SortOrder=520}
};
return Options.ToArray();
}
public static Dictionary<int, string> GetOptionGroupNames()
{
Dictionary<int, string> optionGroups = new Dictionary<int, string>();
optionGroups.Add(1, "Tea");
optionGroups.Add(2, "Coffee");
optionGroups.Add(3, "Soda");
optionGroups.Add(4, "Juice");
optionGroups.Add(5, "Alcohol");
return optionGroups;
}
public class Option
{
public int OptionId { get; set; }
public string DisplayName { get; set; }
public OptionType OptionType { get; set; } //Three different types A,B,C
public int SortOrder { get; set; } //100-199, 200-299, etc.
}
public enum OptionType
{
Coffee,
Tea,
Drinks
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Repeater ID="rptrGroupOptions" runat="server" OnItemDataBound="rptrGroupOptions_ItemDataBound">
<ItemTemplate>
<asp:Label ID="lblOptionGroup" runat="server" ForeColor="Maroon"></asp:Label><br />
<asp:Repeater ID="rptrOptions" runat="server" OnItemDataBound="rptrOptions_ItemDataBound">
<ItemTemplate>
<asp:Label ID="lblOptionGroupNum" runat="server" ForeColor="Sienna"></asp:Label>
<asp:CheckBoxList ID="cblOptions" runat="server" DataTextField="DisplayName" DataValueField="OptionId"></asp:CheckBoxList>
</ItemTemplate>
</asp:Repeater>
<br />
</ItemTemplate>
</asp:Repeater>
</div>
</form>
</body>
</html>
对不起,我仍然想要抓住Linq和GroupBy。
答案 0 :(得分:1)
我会这样做:
options.GroupBy(x => new { x.OptionType, Group = x.SortOder / 100 })
您将获得像( "A", 1 ) ("B", 1) ("B", 2)
这样的关键对象,并将原始对象作为值。
答案 1 :(得分:0)
我认为你可以这样做:
var result= options.ToLookup(o => o.OptionType).
ToDictionary(grouping => grouping.Key, grouping => grouping.
ToLookup(o => o.SortOder/100));
这样,您就拥有一个字典,其中键是OptionType
,值是根据您的值范围的Option
组。