I am looking to get a WPF window and traverse it's controls. I'm able to get the hWnd and i've found other posts on traversing the controls using a DependencyObject. How do I get a DependencyObject from a hWnd? Is it even possible?
-
Are you doing this from within the same process, or from a separate process? You can typically only access WPF objects within the same AppDomain (which in turn restricts you to within your same process). Could you give more background on why you want to traverse the controls - perhaps automation/testing? – BrendanMcK Apr 28 '11 at 23:11
4 Answers
Window window = (Window)HwndSource.FromHwnd(hWnd).RootVisual

- 3,808
- 19
- 22
-
1
-
Maybe your hWnd targeting Window that doesn't belong to WPF? How you obtain hWnd? – Marat Khasanov Apr 28 '11 at 17:51
-
obtained hwnd using FindWindowEx and I also got the same value using EnvDTE.Window.HWnd property. Spy++ shows a different hwnd than what i get. – Dustin Davis Apr 28 '11 at 17:54
-
Can you tell us why do you need to find this Window? Perhaps there will be another solution instead of using native handles ;) – Marat Khasanov Apr 28 '11 at 18:22
-
Solution Explorer in Visual Studio. Making a collapse all function. It doesn't have one built in and EnvDTE doesn't have one either it only has ExpandView() which of course opens everything. – Dustin Davis Apr 28 '11 at 18:52
-
-
@Marat so what do you think? How can I get the context of the tree so I can work with it? – Dustin Davis Apr 28 '11 at 20:33
-
@DustinDavis I have the same problem, how did you solve it without hwnd? – Sven Amann Oct 23 '14 at 09:07
-
@Sven Since I was building a Visual Studio extension, I ended up finding a different way to accomplish what I needed, so hwnd wasn't even needed. Sorry I couldn't help you more. – Dustin Davis Oct 23 '14 at 14:54
-
@DustinDavis that's what I took from EnvDTE ;) I'm in the same boat, so my question still stands: how did you do it? – Sven Amann Oct 23 '14 at 20:06
-
@Sven I don't recall, but here is the project I was building at the time which has the feature I was trying to accomplish in my question https://dfactor.codeplex.com/ it will have the answer you're looking for – Dustin Davis Oct 23 '14 at 20:17
As far as I know WPF completely replaces WinApi model with all that HWNDs. Main window has HWND of course, because it servers as container between WinApi and WPF. You can access HWND using WindowInteropHelper Class, like this. But you will not be able to traverse controls the same way you would do it with native or WinForms app. Check VisualTreeHelper for traversing control trees in WPF.

- 59,039
- 12
- 119
- 163
There is a special case not documented here yet. It could be that the toplevel control is not a standard WPF Window
. This is the case (for instance) in Visual Studio 2010. I discovered this when writing a visual studio Add-in: I wanted to inject some WPF controls in the visual tree, but you need the start of the WPF tree.
Fortunately, there is a solution:
var hwnd = _dte.MainWindow.HWnd;
var window = HwndSource.FromHwnd((IntPtr)hwnd);
dynamic customWindow = window.RootVisual;
UIElement content = customWindow.Content;
The trick is that by declaring the customWindow
as dynamic
you don't need to know or specify its type. In good WPF fashion it has a Content
property that contains all the window's content and everything is normal from there.
After you get the window itself (as Marat points out how to do that) you need to search the visual tree. Here are two helper functions
find all children of a type
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
to find a child by name:
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;
}
-
I already have this as stated in my question. I'm trying to get the window from a hWnd so I can get to this point. – Dustin Davis Apr 28 '11 at 17:22
-
Indeed, Marat's answer should do that. Just added this for completeness in case someone stumbles upon this and needed to know the rest :) – Lugoues Apr 28 '11 at 17:32