我需要在WPF控件层次结构中搜索与给定名称或类型匹配的控件。我该怎么做呢?
当前回答
下面是我的代码,通过类型来查找控件,同时控制我们进入层次结构的深度 (maxDepth == 0表示无限深)。
public static class FrameworkElementExtension
{
public static object[] FindControls(
this FrameworkElement f, Type childType, int maxDepth)
{
return RecursiveFindControls(f, childType, 1, maxDepth);
}
private static object[] RecursiveFindControls(
object o, Type childType, int depth, int maxDepth = 0)
{
List<object> list = new List<object>();
var attrs = o.GetType()
.GetCustomAttributes(typeof(ContentPropertyAttribute), true);
if (attrs != null && attrs.Length > 0)
{
string childrenProperty = (attrs[0] as ContentPropertyAttribute).Name;
foreach (var c in (IEnumerable)o.GetType()
.GetProperty(childrenProperty).GetValue(o, null))
{
if (c.GetType().FullName == childType.FullName)
list.Add(c);
if (maxDepth == 0 || depth < maxDepth)
list.AddRange(RecursiveFindControls(
c, childType, depth + 1, maxDepth));
}
}
return list.ToArray();
}
}
其他回答
对代码的扩展。
增加了重载,以按类型、按类型和标准(谓词)查找一个子元素,查找符合标准的所有类型的子元素 FindChildren方法除了是DependencyObject的扩展方法外,还是一个迭代器 FindChildren还遍历逻辑子树。请参阅博客中链接的Josh Smith的文章。
来源: https://code.google.com/p/gishu-util/source/browse/#git%2FWPF%2FUtilities
解释性博客文章: http://madcoderspeak.blogspot.com/2010/04/wpf-find-child-control-of-specific-type.html
我编辑了CrimsonX的代码,因为它不能处理超类类型:
public static T FindChild<T>(DependencyObject depObj, string childName)
where T : DependencyObject
{
// Confirm obj is valid.
if (depObj == null) return null;
// success case
if (depObj is T && ((FrameworkElement)depObj).Name == childName)
return depObj as T;
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
//DFS
T obj = FindChild<T>(child, childName);
if (obj != null)
return obj;
}
return null;
}
如果您希望找到特定类型的ALL控件,那么您可能也会对这个代码段感兴趣
public static IEnumerable<T> FindVisualChildren<T>(DependencyObject parent)
where T : DependencyObject
{
int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < childrenCount; i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
var childType = child as T;
if (childType != null)
{
yield return (T)child;
}
foreach (var other in FindVisualChildren<T>(child))
{
yield return other;
}
}
}
您还可以使用FrameworkElement.FindName(string)按名称查找元素。
考虑到:
<UserControl ...>
<TextBlock x:Name="myTextBlock" />
</UserControl>
在代码隐藏文件中,你可以这样写:
var myTextBlock = (TextBlock)this.FindName("myTextBlock");
当然,因为它是使用x:Name定义的,所以您可以只引用生成的字段,但是您可能希望动态而不是静态地查找它。
这种方法也可用于模板,其中命名项出现多次(每次使用模板一次)。
试试这个
<TextBlock x:Name="txtblock" FontSize="24" >Hai Welcom to this page
</TextBlock>
后面的代码
var txtblock = sender as Textblock;
txtblock.Foreground = "Red"
推荐文章
- 没有ListBox。SelectionMode="None",是否有其他方法禁用列表框中的选择?
- 在c#代码中设置WPF文本框的背景颜色
- 禁用Visual Studio 2015额外调试选项
- 将WPF组合框绑定到自定义列表
- 如何将枚举绑定到WPF中的组合框控件?
- 我如何腾出一个StackPanel的子元素?
- 如何使用查找命令从列表中查找所有具有扩展名的文件?
- Windows窗体中的标签的换行
- WPF和初始焦点
- 查找文件名以指定字符串开头的所有文件?
- 在find中使用分号(;)vs +(+)和exec
- 如何进入每个目录并执行命令?
- WPF数据网格底部空行
- 窗口vs页面vs用户控件的WPF导航?
- 在窗口上设置设计时间DataContext是一个编译器错误?