在 WPF 应用程序中查找嵌入式控件
Find an embedded control within WPF Application
我有一个遗留应用程序,它混合了 WPF 和 Windows 表单。本质上,通过将 ElementHost 添加到 Windows 表单,WPF 应用程序被加载到 Windows 表单应用程序。然后,此 WPF 应用程序将 WPF 用户控件加载到其上。嵌入此 WPF 用户控件的是遗留 Windows 控件(自定义浏览器控件),它最终派生自 System.Windows.Forms
有没有办法从代码中动态获取此控件的句柄?我们不知道控件在呈现时将被赋予的名称。我们所知道的是控件的基本类型,正如我提到的,它源自 System.WIndows.Forms.
到目前为止我看到的所有示例都讨论了如何动态发现最终成为 DependencyObject 的子对象。我还没有找到一个示例来解释如何在 WPF 应用程序中以编程方式发现老式 Windows 表单控件。
为了在 WPF 控件中承载 Winforms 控件,它必须使用 WindowsFormsHost
。 WindowsFormsHost
从 DependencyObject
派生出 。
您必须在 WPF 应用程序中找到 WindowsFormsHost
元素,然后您才能访问包含 WebBrowser
控件的 Child
属性。
伪代码:
var controlYoureLookingFOr = GiveMeAllChildren(WPFApp)
.OfType<WindowsFormsHost>
.First();
var browser = (WebBrowser.Or.Something)controlYoureLookingFOr.Child;
为了完成这里的答案是我添加的递归部分,以确保遍历整个 window 或父控件及其所有后代
public static IEnumerable<T> FindAllChildrenByType<T>(this System.Windows.Forms.Control control)
{
IEnumerable<System.Windows.Forms.Control> controls = control.Controls.Cast<System.Windows.Forms.Control>();
return controls
.OfType<T>()
.Concat<T>(controls.SelectMany<System.Windows.Forms.Control, T>(ctrl => FindAllChildrenByType<T>(ctrl)));
}
public static IEnumerable<T> FindVisualChildren<T>(this DependencyObject depObj) where T : DependencyObject
{
if (depObj != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
if (child != null && child is T)
{
yield return (T)child;
}
foreach (T childOfChild in FindVisualChildren<T>(child))
{
yield return childOfChild;
}
}
}
}
然后您可以将其用作
var windowsFormHost = parentControl.FindVisualChildren<WindowsFormsHost>();
foreach (var item in windowsFormHost)
{
var htmlcontrols = item.Child.FindAllChildrenByType<{sometypehere}
foreach (var control in htmlcontrols)
{
}
}
我有一个遗留应用程序,它混合了 WPF 和 Windows 表单。本质上,通过将 ElementHost 添加到 Windows 表单,WPF 应用程序被加载到 Windows 表单应用程序。然后,此 WPF 应用程序将 WPF 用户控件加载到其上。嵌入此 WPF 用户控件的是遗留 Windows 控件(自定义浏览器控件),它最终派生自 System.Windows.Forms
有没有办法从代码中动态获取此控件的句柄?我们不知道控件在呈现时将被赋予的名称。我们所知道的是控件的基本类型,正如我提到的,它源自 System.WIndows.Forms.
到目前为止我看到的所有示例都讨论了如何动态发现最终成为 DependencyObject 的子对象。我还没有找到一个示例来解释如何在 WPF 应用程序中以编程方式发现老式 Windows 表单控件。
为了在 WPF 控件中承载 Winforms 控件,它必须使用 WindowsFormsHost
。 WindowsFormsHost
从 DependencyObject
派生出 。
您必须在 WPF 应用程序中找到 WindowsFormsHost
元素,然后您才能访问包含 WebBrowser
控件的 Child
属性。
伪代码:
var controlYoureLookingFOr = GiveMeAllChildren(WPFApp)
.OfType<WindowsFormsHost>
.First();
var browser = (WebBrowser.Or.Something)controlYoureLookingFOr.Child;
为了完成这里的答案是我添加的递归部分,以确保遍历整个 window 或父控件及其所有后代
public static IEnumerable<T> FindAllChildrenByType<T>(this System.Windows.Forms.Control control)
{
IEnumerable<System.Windows.Forms.Control> controls = control.Controls.Cast<System.Windows.Forms.Control>();
return controls
.OfType<T>()
.Concat<T>(controls.SelectMany<System.Windows.Forms.Control, T>(ctrl => FindAllChildrenByType<T>(ctrl)));
}
public static IEnumerable<T> FindVisualChildren<T>(this DependencyObject depObj) where T : DependencyObject
{
if (depObj != null)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
if (child != null && child is T)
{
yield return (T)child;
}
foreach (T childOfChild in FindVisualChildren<T>(child))
{
yield return childOfChild;
}
}
}
}
然后您可以将其用作
var windowsFormHost = parentControl.FindVisualChildren<WindowsFormsHost>();
foreach (var item in windowsFormHost)
{
var htmlcontrols = item.Child.FindAllChildrenByType<{sometypehere}
foreach (var control in htmlcontrols)
{
}
}