Is there an easier way to typecast with unknown types?
I am writing a function to recurse my XAML and add all the controls to a hashtable, with their names being the keys. Unfortunately it seems like I have to go through and list every possible type:
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);
}
}
}
Is there a simpler way of doing this?
What you really want to do is get all the objects in the logical tree. The logical tree will include other things than just controls (RowDefinitions for instance), so you should check to ensure the name actually exists on the object before adding it to the dictionary.
Since the Name property is defined on FrameworkElement (and FrameworkContentElement, but they use AddOwner so that these two properties are actually the same instance), you can just use GetValue to retrieve the value. This should do what you need:
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);
}
Side note: this is easily made iterative by using a Queue instead of recursion:
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);
}
}
You could loop through the base types, like Control for buttons etc. or ContainerControl to loop through the nested types. That would cut the amount of if clauses a great deal.
I wonder why you would need something like this though. Wat exactly are you trying to do that you need to list all controls?
Edit:
Just realized you can't just use the base type like that; you need to replace start.GetType().ToString()
with start.GetType().BaseType.ToString();
It won't get much better than you did it. You should however use the is
clause instead of comparing strings. This is much safer and much faster. Also you might be able to use baseclasses in the check. For example if (start is ButtonBase)
will be true for all derived classes too (if that is suitable for your needs).
精彩评论