我正在编写一个简单的扩展方法来对控件及其所有子节点执行操作,我想知道是否必须担心两次运行相同的控件。
安全:
public static void Traverse(this Control control, Action<Control> action)
{
Traverse(control, action, new HashSet<control>());
}
private static void Traverse(this Control control, Action<Control> action, HashSet<Control> handled)
{
handled.Add(control);
foreach (Control child in control.Controls)
if (!handled.Contains(child))
Traverse(child, action, handled);
action.Invoke(control);
}
可能不安全:
public static void Traverse(this Control control, Action<Control> action)
{
foreach (Control child in control.Controls)
Traverse(child, action, handled);
action.Invoke(control);
}
是否需要使用哈希集来保持此代码的安全?它只需要在每个控件上调用一次动作,并且它不能进入无限循环。父子控制的结构是否让我不必担心这个?
用法:
this.Traverse(o => o.SuspendLayout());
// Do lots of UI changes
this.Traverse(o => o.ResumeLayout());
(可能)全面的方法:
public static class ControlExtensions
{
public static void Traverse(this Control control, Action<Control> action)
{
Traverse(control, action, TraversalMethod.DepthFirst);
}
public static void Traverse(this Control control, Action<Control> action, TraversalMethod method)
{
switch (method)
{
case TraversalMethod.DepthFirst:
TraverseDepth(control, action);
break;
case TraversalMethod.BreadthFirst:
TraverseBreadth(control, action);
break;
case TraversalMethod.ReversedDepthFirst:
TraverseDepthReversed(control, action);
break;
case TraversalMethod.ReversedBreadthFirst:
TraverseBreadthReversed(control, action);
break;
}
}
private static void TraverseDepth(Control control, Action<Control> action)
{
Stack<Control> controls = new Stack<Control>();
Queue<Control> queue = new Queue<Control>();
controls.Push(control);
while (controls.Count != 0)
{
control = controls.Pop();
foreach (Control child in control.Controls)
controls.Push(child);
queue.Enqueue(control);
}
while (queue.Count != 0)
action.Invoke(queue.Dequeue());
}
private static void TraverseBreadth(Control control, Action<Control> action)
{
Queue<Control> controls = new Queue<Control>();
Queue<Control> queue = new Queue<Control>();
controls.Enqueue(control);
while (controls.Count != 0)
{
control = controls.Dequeue();
foreach (Control child in control.Controls)
controls.Enqueue(child);
queue.Enqueue(control);
}
while (queue.Count != 0)
action.Invoke(queue.Dequeue());
}
private static void TraverseDepthReversed(Control control, Action<Control> action)
{
Stack<Control> controls = new Stack<Control>();
Stack<Control> stack = new Stack<Control>();
controls.Push(control);
while (controls.Count != 0)
{
control = controls.Pop();
foreach (Control child in control.Controls)
controls.Push(child);
stack.Push(control);
}
while (stack.Count != 0)
action.Invoke(stack.Pop());
}
private static void TraverseBreadthReversed(Control control, Action<Control> action)
{
Queue<Control> controls = new Queue<Control>();
Stack<Control> stack = new Stack<Control>();
controls.Enqueue(control);
while (controls.Count != 0)
{
control = controls.Dequeue();
foreach (Control child in control.Controls)
controls.Enqueue(child);
stack.Push(control);
}
while (stack.Count != 0)
action.Invoke(stack.Pop());
}
}
答案 0 :(得分:4)
每个孩子都有一个父母,所以没必要担心。
答案 1 :(得分:2)
控件实际上只能有一个父级。没有理由跟踪“处理”,因为您只会在控件上执行一次方法。
现在,如果您使用的框架允许控件具有多个父级(我不知道任何允许这样做的.NET框架),那么可能需要这样做。但是,如果您使用的是Windows窗体(看起来是这样)或WPF,则可以将其简化为:
private static void Traverse(this Control control, Action<Control> action)
{
foreach (Control child in control.Controls)
Traverse(child, action);
action(control);
}
答案 2 :(得分:0)
您需要使用递归
public sub DoStuffToControlAndChildren(TargetControl as Control)
'Insert code to do stuff to TargetControl here
if TargetControl.Controls.count = 0 then
return
end if
For each ChildControl in TargetControl.Controls
DoStuffToControlAndChildren(ChildControl)
next
end sub