我希望得到一个WPF窗口并遍历它的控件。我能够获得hWnd,并且我在使用DependencyObject遍历控件时发现了其他帖子。如何从hWnd获取DependencyObject?它甚至可能吗?
答案 0 :(得分:15)
Window window = (Window)HwndSource.FromHwnd(hWnd).RootVisual
答案 1 :(得分:3)
据我所知,WPF完全取代所有HWND的WinApi模型。主窗口当然有HWND,因为它作为WinApi和WPF之间的容器服务器。您可以使用WindowInteropHelper Class访问HWND,例如this。但是,您将无法像使用本机或WinForms应用程序那样遍历控件。检查VisualTreeHelper是否在WPF中遍历控制树。
答案 2 :(得分:1)
在您获得窗口后(如Marat指出如何操作),您需要搜索可视树。这是两个辅助函数
找到所有类型的孩子
public static IEnumerable<T> FindChildren<T>(this DependencyObject source) where T : DependencyObject
{
if (source != null)
{
var childs = GetChildObjects(source);
foreach (DependencyObject child in childs)
{
//analyze if children match the requested type
if (child != null && child is T)
{
yield return (T)child;
}
//recurse tree
foreach (T descendant in FindChildren<T>(child))
{
yield return descendant;
}
}
}
}
https://sites.google.com/site/bobstechwiki/home/wpf-ji-shu-1/find-element-by-visual-tree
按姓名查找孩子:
public static T FindChild<T>(DependencyObject parent, string childName)
where T : DependencyObject
{
// Confirm parent and childName are valid.
if (parent == null) return null;
T foundChild = null;
int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < childrenCount; i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
// If the child is not of the request child type child
T childType = child as T;
if (childType == null)
{
// recursively drill down the tree
foundChild = FindChild<T>(child, childName);
// If the child is found, break so we do not overwrite the found child.
if (foundChild != null) break;
}
else if (!string.IsNullOrEmpty(childName))
{
var frameworkElement = child as FrameworkElement;
// If the child's name is set for search
if (frameworkElement != null && frameworkElement.Name == childName)
{
// if the child's name is of the request name
foundChild = (T)child;
break;
}
}
else
{
// child element found.
foundChild = (T)child;
break;
}
}
return foundChild;
}
答案 3 :(得分:1)
此处尚未记录特殊情况。可能是顶层控件不是标准WPF Window
。这是Visual Studio 2010中的情况。例如,我在编写visual studio插件时发现了这一点:我想在可视树中注入一些WPF控件,但是你需要WPF树的开头。
幸运的是,有一个解决方案:
var hwnd = _dte.MainWindow.HWnd;
var window = HwndSource.FromHwnd((IntPtr)hwnd);
dynamic customWindow = window.RootVisual;
UIElement content = customWindow.Content;
诀窍是通过将customWindow
声明为dynamic
,您不需要知道或指定其类型。以良好的WPF方式,它有一个Content
属性,包含所有窗口的内容,从那里一切正常。