我有一个类和一组IEnumerables正在使用这个类给我列表中的列表。 (有关详细信息,请参阅此question的答案。)
以下是代码:
public IEnumerable<IEnumerable<WorkItemColumn>> EnumerateResultSet(WorkItemCollection queryResults)//DisplayFieldList displayFieldList)
{
foreach (WorkItem workItem in queryResults)
{
yield return EnumerateColumns(queryResults.DisplayFields, workItem);
}
}
public IEnumerable<WorkItemColumn> EnumerateColumns(DisplayFieldList resultSet, WorkItem workItem)
{
foreach (FieldDefinition column in resultSet)
yield return new WorkItemColumn { Name = column.Name, Value = workItem[column.Name], WorkItemForColumn = workItem};
}
上课:
public class WorkItemColumn
{
public string Name { get; set; }
public object Value { get; set; }
public WorkItem WorkItemForColumn { get; set; }
}
我将此结果设置为ListBox的ItemsSource
Form.QueryResultListSource = EnumerateResultSet(queryResults);
当我尝试捕获此列表框的事件时,问题就出现了:
public void QueryResultsSelectionChanged(SelectionChangedEventArgs e)
{
+-----------------+
v |
foreach (WorkItemColumn workItemColumn in e.AddedItems) |
{ |
AddWorkItemToPad(workItemColumn.WorkItemForColumn); |
} +---------------|
| |
v |
foreach (WorkItemColumn workItemColumn in e.RemovedItems) |
{ |
RemoveWorkItemFromPad(workItemColumn.WorkItemForColumn); |
} |
|
} |
|
These items are where the problem is --------------------------------+
当我在调试时检查e.AddedItems [0]并且它的类型是EnumerateColumns。
当我尝试转换为该类型时,Visual Studio说(可以理解)EnumerateColumns是一个方法但是像类型一样使用。
那么,我怎么能按类型引用它,这样我就可以做一个foreach循环并得到它里面的东西?
这是我根据答案更新的代码:
public void QueryResultsSelectionChanged(SelectionChangedEventArgs e)
{
foreach (IEnumerable<WorkItemColumn> workItemColumns in e.AddedItems)
{
if (workItemColumns.Count() > 0)
AddWorkItemToPad(workItemColumns.First().WorkItemForColumn);
}
foreach (IEnumerable<WorkItemColumn> workItemColumns in e.RemovedItems)
{
if (workItemColumns.Count() > 0)
RemoveWorkItemFromPad(workItemColumns.First().WorkItemForColumn);
}
}
答案 0 :(得分:2)
问题是你的第一个方法并没有产生第一个给出的每个结果 - 它产生了可枚举的本身。迭代器的编译器生成类型的类型 - 但重要的是,实现 IEnumerable<WorkItemColumn>
。
如果您愿意,可以将每个项目投放到IEnumerable<WorkItemColumn>
- 但是您在QueryResultsSelectionChanged
中尝试做的事情并不是很清楚。您可能想要这样做:
foreach (IEnumerable<WorkItemColumn> workItemColumns in e.AddedItems)
{
foreach(WorkItemColumn workItemColumn in workItemColumns)
{
AddWorkItemToPad(workItemColumn.WorkItemForColumn);
}
}
等等......或者你可能没有。如果不知道你真正想要做什么,说这很棘手。无论如何,它的关键在于您目前正在尝试将序列项目视为单个项目。不要那样做:)
答案 1 :(得分:1)
e.AddedItems[0]
是编译器生成的隐藏迭代器类型的实例,您不能直接使用它。
但是,它实现了IEnumerable<WorkItemColumn>
,因此您可以通过该接口使用它。
换句话说:
foreach (IEnumerable<WorkItemColumn> colSet in e.RemovedItems)
foreah(WorkItemColumn workItemColumn in colSet)
RemoveWorkItemFromPad(workItemColumn.WorkItemForColumn);
答案 2 :(得分:1)
尽管使用迭代器可能不是解决此问题的最佳方法,但您可以通过将枚举存储在数组中来避免遇到的问题:
using System.Linq;
...
Form.QueryResultListSource = EnumerateResultSet(queryResults).ToArray();
将您的EnumerateResultSet更改为:
public IEnumerable<WorkItemColumn[]> EnumerateResultSet(WorkItemCollection queryResults)//DisplayFieldList displayFieldList)
{
foreach (WorkItem workItem in queryResults)
{
yield return EnumerateColumns(queryResults.DisplayFields, workItem).ToArray();
}
}
正如其他人所说,使用yield关键字,您实际上会返回一个知道如何迭代您想要枚举的项的函数。但是,将数据源设置为此枚举不会简单地执行一次并存储结果。通过使用迭代器,您可能会遇到很多性能问题,因为只要需要使用结果,迭代就需要重新执行。
答案 3 :(得分:0)
为了完整起见,您确实应该包含AddedItems
和RemovedItems
的相关代码。
尽管如此,使用完全限定的形式(包括名称空间包含)来转换具有类型名称的对象。这将使它绑定到类型而不是方法签名,因为该方法在类型级别不可用,但子类型将可用。