我需要在WPF控件层次结构中搜索与给定名称或类型匹配的控件。我该怎么做呢?
当前回答
因为这个问题很普遍,它可能会吸引人们去寻找非常琐碎的情况的答案:如果你只想要一个孩子而不是后代,你可以使用Linq:
private void ItemsControlItem_Loaded(object sender, RoutedEventArgs e)
{
if (SomeCondition())
{
var children = (sender as Panel).Children;
var child = (from Control child in children
where child.Name == "NameTextBox"
select child).First();
child.Focus();
}
}
或者显然的for循环遍历Children。
其他回答
下面是我的代码,通过类型来查找控件,同时控制我们进入层次结构的深度 (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();
}
}
试试这个
<TextBlock x:Name="txtblock" FontSize="24" >Hai Welcom to this page
</TextBlock>
后面的代码
var txtblock = sender as Textblock;
txtblock.Foreground = "Red"
我找不到@CrimsonX或@Drew Noakes方法的控件,因为我的ControlTemplate位于一个单独的XAML文件中。 我用下面的方法找到了控件:
private Image backImage;
private void Diagram_Loaded(object sender, System.Windows.RoutedEventArgs e)
{
// here is the example of the ControlTemplate declaration
//<ControlTemplate x:Key="DiagramControlTemplate1" TargetType="{x:Type Diagram}">
var ctrlTemplate = (ControlTemplate)FindResource("DiagramControlTemplate1");
// diagram is the x:Name of TemplatedControl and, "backImage" is the name of control that I want to find.
var imageControl = ctrlTemplate.FindName("backImage", diagram);
if (imageControl != null)
{
this.backImage = (Image)imageControl;
}
}
这对我很有用。
exciton80……我有一个问题,你的代码不递归通过用户控件。它击中了网格根并抛出了一个错误。我相信这能解决我的问题:
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;
if (String.Equals(childrenProperty, "Content") || String.Equals(childrenProperty, "Children"))
{
var collection = o.GetType().GetProperty(childrenProperty).GetValue(o, null);
if (collection is System.Windows.Controls.UIElementCollection) // snelson 6/6/11
{
foreach (var c in (IEnumerable)collection)
{
if (c.GetType().FullName == childType.FullName)
list.Add(c);
if (maxDepth == 0 || depth < maxDepth)
list.AddRange(RecursiveFindControls(
c, childType, depth + 1, maxDepth));
}
}
else if (collection != null && collection.GetType().BaseType.Name == "Panel") // snelson 6/6/11; added because was skipping control (e.g., System.Windows.Controls.Grid)
{
if (maxDepth == 0 || depth < maxDepth)
list.AddRange(RecursiveFindControls(
collection, childType, depth + 1, maxDepth));
}
}
}
return list.ToArray();
}
下面是一个使用灵活谓词的解决方案:
public static DependencyObject FindChild(DependencyObject parent, Func<DependencyObject, bool> predicate)
{
if (parent == null) return null;
int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < childrenCount; i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
if (predicate(child))
{
return child;
}
else
{
var foundChild = FindChild(child, predicate);
if (foundChild != null)
return foundChild;
}
}
return null;
}
例如,你可以这样称呼它:
var child = FindChild(parent, child =>
{
var textBlock = child as TextBlock;
if (textBlock != null && textBlock.Name == "MyTextBlock")
return true;
else
return false;
}) as TextBlock;
推荐文章
- 没有ListBox。SelectionMode="None",是否有其他方法禁用列表框中的选择?
- 在c#代码中设置WPF文本框的背景颜色
- 禁用Visual Studio 2015额外调试选项
- 将WPF组合框绑定到自定义列表
- 如何将枚举绑定到WPF中的组合框控件?
- 我如何腾出一个StackPanel的子元素?
- 如何使用查找命令从列表中查找所有具有扩展名的文件?
- Windows窗体中的标签的换行
- WPF和初始焦点
- 查找文件名以指定字符串开头的所有文件?
- 在find中使用分号(;)vs +(+)和exec
- 如何进入每个目录并执行命令?
- WPF数据网格底部空行
- 窗口vs页面vs用户控件的WPF导航?
- 在窗口上设置设计时间DataContext是一个编译器错误?