我正在编写一个函数来递归我的XAML并将所有控件添加到哈希表中,其名称是键。不幸的是,似乎我必须通过并列出所有可能的类型:
void Recurse_Controls(object start)
{
string start_type = start.GetType().ToString();
if (start_type == "StackPanel")
{
ControlsByName.Add(((StackPanel)start).Name, start);
foreach (object item in ((StackPanel)start).Children)
{
Recurse_Controls(item);
}
}
if (start_type == "Grid")
{
ControlsByName.Add(((Grid)start).Name, start);
foreach (object item in ((Grid)start).Children)
{
Recurse_Controls(item);
}
}
}
有更简单的方法吗?
答案 0 :(得分:4)
您真正想要做的是获取逻辑树中的所有对象。逻辑树将包含除控件之外的其他内容(例如RowDefinitions),因此在将对象添加到字典之前,应检查以确保该对象实际存在。
由于Name属性是在FrameworkElement(和FrameworkContentElement,但它们使用AddOwner,因此这两个属性实际上是同一个实例)上定义的,因此您可以使用GetValue来检索值。这应该做你需要的:
void Recurse_Controls(DependencyObject start)
{
if (start == null) return;
var name = (string)start.GetValue(FrameworkElement.NameProperty);
if (!String.IsNullOrEmpty(name))
ControlsByName.Add(name, start);
foreach (var child in LogicalTreeHelper.GetChildren(start))
Recurse_Controls(child);
}
旁注:通过使用队列而不是递归,可以轻松地进行迭代:
void Add_Controls(DependencyObject start)
{
if (start == null) return;
var items = new Queue<DependencyObject>();
items.Enqueue(start);
while (items.Count > 0)
{
var item = items.Dequeue();
var name = (string)item.GetValue(FrameworkElement.NameProperty);
if (!String.IsNullOrEmpty(name))
ControlsByName.Add(name, item);
foreach (var child in LogicalTreeHelper.GetChildren(item))
items.Enqueue(child);
}
}
答案 1 :(得分:0)
您可以循环遍历基类型,例如按钮控制等,或者循环嵌套类型的ContainerControl。这将大大削减if条款的数量。
我想知道为什么你会需要这样的东西。您正在尝试使用Wat来列出所有控件吗?
编辑:
刚刚意识到你不能像这样使用基类型;您需要将start.GetType().ToString()
替换为start.GetType().BaseType.ToString();
答案 2 :(得分:0)
它不会比你做得好多少。但是,您应该使用is
子句而不是比较字符串。这更安全,更快。您也可以在支票中使用基类。例如,对于所有派生类,if (start is ButtonBase)
也是如此(如果这适合您的需要)。