[英]Recursive Lookup of generic List C# using LINQ
I have generic list of a custom class which has 2 properties. 我有一个具有2个属性的自定义类的通用列表。 These properties store the raltionship between on form and another form.
这些属性存储形式和另一形式之间的关系。 The list is structured as a hierachical list (parent / child ) relationship.
该列表被构造为层次列表(父/子)关系。 What I want to be able to do is get a list of all forms based on a parent form reference which will be passed to a function.
我想要做的是基于父表单引用获取所有表单的列表,该列表将传递给函数。 I am thinking the best way to go about this is with a LINQ query using a recursive approach.
我认为最好的方法是使用递归方法的LINQ查询。 I am sure someone can point me in the right direction
我相信有人可以指出我正确的方向
This is the class used in the list 这是列表中使用的类
class FormStack {
#region Declares
private Form _form;
private Form _parent;
#endregion
#region Constructor
static FormStack()
{
}
#endregion
public Form Form
{
get { return _form; }
set { _form = value; }
}
public Form Parent
{
get { return _parent; }
set { _parent = value; }
}
}
So I would like to be able to Call a method and pass a form reference to the function and get all the children form related to this parent. 因此,我希望能够调用一个方法并将一个表单引用传递给该函数,并获取与此父级相关的所有子表单。
This is some of the code I have been stumbling with 这是我一直在摸索的一些代码
// create a lookup list
var list = formStack.ToLookup( p => object.ReferenceEquals( p.Parent, parent ) );
// create a function
Func<IEnumerable<Form>, IEnumerable<Form>> recurse = null;
recurse = qs =>
{
return
qs
.Concat(
from q in qs
from q2 in recurse( list[] )
select q2 );
};
// filter the list
var children = recurse( list[parent] ).ToList();
I have a winform application which has standard CRUD functionality. 我有一个具有标准CRUD功能的Winform应用程序。 Lets say there is a list of customers and each customer can have multiple address and each one of these addresses have multiple buildings, the way I have structured the forms is there is a list of customers, from this list you can open a detail form for a particular customer.
可以说有一个客户列表,每个客户可以有多个地址,这些地址中的每个地址都有多个建筑物,我构造表单的方式是有一个客户列表,您可以从此列表中打开详细的表单特定客户。 This form has the details of the customer and all the addresses in a list.
此表单在列表中包含客户的详细信息和所有地址。 This list allows the user to now selected an address in the list and open the address details form which has a list of buildings and so on.... My problem is I want to close the customer detail and all the related forms for this customer.
此列表使用户现在可以在列表中选择一个地址,然后打开包含建筑物列表的地址详细信息表单,等等。...我的问题是我想关闭该客户的客户详细信息和所有相关表单。 My idea was to keep of the relationship between the forms, but maybe I there is a better way???
我的想法是保持表格之间的关系,但也许我有更好的方法?
Okay, it sounds to me like you have two issues. 好吧,听起来像我有两个问题。 One is a syntax error (
recurse(list[])
is wrong), but the other is that your FormStack isn't really a stack. 一个是语法错误(
recurse(list[])
错误),另一个是您的FormStack并不是真正的堆栈。 It's just two forms, with no way to create a recursive chain. 它只有两种形式,无法创建递归链。 I think you want this:
我想你想要这个:
public class FormStack : IEnumerable<Form> // or just implement SelectMany
{
public Form Form { get; set; }
public FormStack Parent { get; set; }
//implement IEnumerable<Form> or the SelectMany method
}
Then I think you can just do this, but it seems like an awkward thing to do: 那么我想你可以做到这一点,但它似乎是一个尴尬的事:
Func<FormStack, IEnumerable<Form>> recurse = qs =>
{
return from q in qs
select (new[] { qs.Form }).Concat(recurse(qs.Parent));
};
var list = recurse(formStack).ToList();
That's if you're insisting on the query syntax. 那就是如果您坚持使用查询语法。
If I were you, though, I'd forget all that and implement an IEnumerator<Form>
to do it all for you: 但是,如果我是你,我会忘记所有这些,并实现一个
IEnumerator<Form>
为您完成所有操作:
public class FormStack : IEnumerable<Form>
{
public Form Form { get; set; }
public FormStack Parent { get; set; }
public IEnumerator IEnumerable:GetEnumerator()
{
return (IEnumerator)GetEnumerator();
}
public IEnumerator<Form> GetEnumerator()
{
return new FormStackEnumerator(this);
}
}
public class FormStackEnumerator : IEnumerator<Form>
{
private FormStack _stack;
private FormStack _first;
public Form Current { get { return _stack.Form; } }
object IEnumerator.Current { get { return Current; } }
public FormStackEnumerator(FormStack stack)
{
_stack = stack;
_first = stack;
}
public bool MoveNext()
{
if (_stack.Parent == null)
{
return false;
}
_stack = _stack.Parent;
return true;
}
public void Reset() { _stack = _first; }
void IDisposable.Dispose() { }
}
Then all you'd need to do in your main code is this: 然后,您需要在主代码中执行的所有操作是:
var list = new List<Form>();
foreach (var node in formStack)
{
list.Add(node.Form);
}
By the way, I just looked up the Form class (I'm not a WinForms developer) and the Forms themselves have a Parent member. 顺便说一下,我只是查找了Form类(我不是WinForms开发人员),并且Forms本身有一个Parent成员。 So you don't really need to wrap them in a node-type construct;
因此,您实际上不需要将它们包装在节点类型的构造中。 they're already nodes!
他们已经是节点了! That makes everything easy:
这使一切变得容易:
var list = new List<Form>();
Action<Control> recurse = target =>
{
var form = target as Form;
if (form != null)
{
list.Add(form);
recurse(target.Parent);
}
}
here is what I made up: 这是我组成的:
Create a base Form for all your Forms: 为所有表单创建一个基本表单:
public class MyFormBase : Form { public MyFormBase() { FormRepository.RegisterForm(this); } public MyFormBase(MyFormBase parent) : this() { Parent = parent; } public MyFormBase Parent { get; set; } }
Each Form can only have one Parent that is passed in the constuctor. 每个表单只能在构造函数中传递一个父级。
Create a Repository (or something simiar) to store your forms -> I do not want to store all children in the Form itself 创建一个存储库(或类似的东西)来存储您的表单->我不想在表单本身中存储所有子级
//infrastructure - simulated with a static class
public static class FormRepository
{
private static List<MyFormBase> _allForms = new List<MyFormBase>();
public static void RegisterForm(MyFormBase form)
{
_allForms.Add(form);
}
public static void CloseFormAndChildren(MyFormBase form)
{
_allForms.Where(x => x.Parent.Equals(form)).ToList().ForEach(x => CloseFormAndChildren(x));
form.Close();
}
}
Call CloseFormAndChildren on any form you want to close (including the children). 以您要关闭的任何形式(包括子项)调用CloseFormAndChildren。 This could be called in the closing event...
这可以在结束事件中调用...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.