在this问题上,有一个递归函数找到父:
public static T FindParent<T>(DependencyObject child) where T : DependencyObject
{
DependencyObject parentObject = VisualTreeHelper.GetParent(child);
if (parentObject == null) return null;
var parent = parentObject as T;
if (parent != null)
{
return parent;
}
return FindParent<T>(parentObject);
}
Resharper让我把它转换成循环而不是递归,就像那样:
public static T FindParent<T>(DependencyObject child) where T : DependencyObject
{
while (true)
{
DependencyObject parentObject = VisualTreeHelper.GetParent(child);
if (parentObject == null) return null;
var parent = parentObject as T;
if (parent != null)
{
return parent;
}
child = parentObject;
}
}
现在我有一个功能可以折叠扩展组及其所有子组:
不幸的是,Reshaper不会像上面那样转换它:(
private void MenuItemCollapseAll_OnClick(object sender, RoutedEventArgs e)
{
// ... truncated for brievety
IEnumerable<CollectionViewGroup> groups = grid.Items.Groups.OfType<CollectionViewGroup>().ToArray();
CollapseGroups(grid, groups);
}
public void CollapseGroups(DataGridControl grid, IEnumerable<CollectionViewGroup> groups)
{
foreach (var @group in groups)
{
grid.CollapseGroup(group);
var subGroups = @group.Items.OfType<CollectionViewGroup>().ToArray();
if (subGroups.Any())
{
CollapseGroups(grid, subGroups);
}
}
}
我只是无法弄清楚如何使用while
语句以相同的方式转换它,并不完全确定这个函数是否可能。
有什么想法吗?
答案 0 :(得分:3)
它不是尾递归的。递归调用之后是foreach循环的另一次迭代。但是,并非所有希望都失去了。
将它转换为迭代可以做的是创建一个Stack<Tuple<DataGridControl, IEnumerable<CollectionViewGroup>>
并将新元组推入堆栈来替换递归调用。然后循环直到堆栈耗尽。
但首先,我注意到第一个参数永远不会改变。因此,迭代版本实际上并不需要将其保留在堆栈中:
public void CollapseGroups(DataGridControl grid, IEnumerable<CollectionViewGroup> groups)
{
var to_process = new Stack<IEnumerable<CollectionViewGroup>>();
to_process.Push(groups);
do {
groups = to_process.Pop();
foreach (var @group in groups)
{
grid.CollapseGroup(@group);
to_process.Push(@group.Items.OfType<CollectionViewGroup>());
}
} while (to_process.Count > 0);
}