有人會說不建議Wpf中使用Winform控件,有人會說建議使用Winform控件在Wpf下的替代方案,然而在實際工作中由於項目的特殊需求,考慮到時間、成本等因素,往往難免會碰到在WPF中使用Winfrom控件的問題,我們知道Wpf可以通過使用WindowsFormsHost容器調用Winform控件,但是在一些場合需要將Wpf元素顯示在Winform控件的上層,此時就會出現Wpf元素被Winform控件遮蓋的問題。
一、場景再現
接到公司命令,在時間緊迫的情況下,需要將原來的Winform程序(別人寫的,自己壓根沒參與任何東西)替換成Wpf實現,給界面做個美容。首先看了看源碼,了解到里面的知識盲點,主要一個就是用於地圖展示的GMap.NET組件(一個開源的GIS二次開發組件),遂對GMap.NET進行了了解:GMap.net分為for winform及form wpf,且在Wpf下沒有圖層的概念,一些類結構的設計也月GMap.net.winform有變化,為了穩妥,不出現不必要的麻煩,快速改版應對項目要求,考慮仍使用要來的GMap.net.winform,只對展示層做修改。
1、添加Wpf調用Winform控件需要的兩個DLL引用:WindowsFormsIntegration.dll,System.Windows.Forms.dll以及GMap.Net.WindowsFroms的兩個DLL引用:GMap.Net.Core.dll及GMap.Net.WindowsForms.dll。
2、程序運行時將MapControl控件處理后加載到WindowsFormsHost容器。
前台關鍵代碼:
<Window x:Class="WpfApplication3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wfi ="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration"
Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded">
<Grid>
<wfi:WindowsFormsHost x:Name="mapContainer">
</wfi:WindowsFormsHost>
<StackPanel VerticalAlignment="Bottom" HorizontalAlignment="Right" Background="Blue" Width="75" Height="45">
</StackPanel>
</Grid>
</Window>
后台關鍵代碼
private void Window_Loaded(object sender, RoutedEventArgs e)
{
GMap.NET.WindowsForms.GMapControl mapControl = new GMap.NET.WindowsForms.GMapControl();
mapContainer.Child = mapControl;
}
設計狀態時右下角圖例區域設置為最頂層,如下圖所示沒有問題

程序運行時,winform類型的GMapControl控件會渲染在最上層,覆蓋用於顯示地圖圖例區域的右下角Wpf元素。

二、尋求解決方案
自己首先嘗試了各種WPF界面布局方式,Canvas,各種Panel等都試了一遍,結果仍然是Wpf元素被Winform控件遮蓋,遂去尋求網絡幫助,得到的答案基本如下:


三、最終解決方案
考慮如果是因為渲染機制問題,始終將winform控件渲染在最上層的話,能不能將Wpf元素也使用WindowsFormsHost容器進行一層包裹呢?理論上應該是可以得,於是進行嘗試,最外層使用WindosFormsHost,然后是Wpf元素的容器ElementHost,最后是我們需要的WPF界面元素:
<Window x:Class="WpfApplication3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wfi ="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration"
Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded">
<Grid>
<wfi:WindowsFormsHost x:Name="mapContainer">
</wfi:WindowsFormsHost>
<wfi:WindowsFormsHost >
<ElementHost>
<StackPanel VerticalAlignment="Bottom" HorizontalAlignment="Right" Background="Blue" Width="75" Height="45">
</StackPanel>
</ElementHost>
</wfi:WindowsFormsHost>
</Grid>
</Window>
運行程序問題解決:

