我有一个托管在WindowsFormsHost中的Windows Forms控件。 这是我用来完成此操作的 XAML:
<Window x:Class="Forms.Address.MyWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Forms.Address"
xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
mc:Ignorable="d"
Title="New Window" Height="500" Width="720">
<Grid>
<WindowsFormsHost x:Name="host">
<local:MyFormsControl x:Name="genericName"/>
</WindowsFormsHost>
</Grid>
</Window>
我想从WindowsFormsHost所在的窗口中侦听事件。 这在 Windows 窗体中很简单,因为我可以使用 FindForm
方法来获取我的控件所在的窗体。 但是,由于显而易见的原因,当控件位于 WindowsFormsHost 内部时,FindForm
不起作用。 我的控件的父级是System.Windows.Forms.Integration.WinFormsAdapter
,其父级为 null。
问题是:如何找到包含我的控件的窗口?
感谢elgonzo,他建议我使用反射来获取WinFormsAdapter类中的一个字段。 以下是我找到窗口的方式:
public static Window findParentWindow(Control control) {
WindowsFormsHost host = findWPFHost(control);
return Window.GetWindow(host);
}//FindParentWindow
private static WindowsFormsHost findWPFHost(Control control) {
if (control.Parent != null)
return findWPFHost(control.Parent);
else {
string typeName = "System.Windows.Forms.Integration.WinFormsAdapter";
if (control.GetType().FullName == typeName) {
Assembly adapterAssembly = control.GetType().Assembly;
Type winFormsAdapterType = adapterAssembly.GetType(typeName);
return (WindowsFormsHost)winFormsAdapterType.InvokeMember("_host", BindingFlags.NonPublic | BindingFlags.GetField | BindingFlags.Instance, null, control, new string[0], null);
} else
throw new Exception("The top parent of a control within a host should be a System.Windows.Forms.Integration.WinFormsAdapter, but that is not what was found. Someone should propably check this out.");
}//if
}//FindWPFHost
我所做的是首先递归地找到WinFormsAdapter,然后使用反射从中提取_host
字段。 这是 WPF WindowsFormsHost 对象,因此可以使用 Window.GetWindow(host)
找到它的窗口。
需要注意的是,如果使用 ElementHost 将 WindowsFormsHost 放置在 Windows 窗体中,GetWindow
将返回 null,因为没有 Window。
只需将属性添加到窗口和问题,然后在代码中传递另一个窗口。这听起来技术含量低,你必须能够接受妥协。不确定如何使用 100% Xaml 执行此操作。
如果您不喜欢这样,请将其与其他选项(winapi等(的适口性进行比较。它可以是你的电话!