在開發WPF的專案時,有時候可能會礙於平台的限制或是使用的語言及類別庫的限制,部份功能還是得透過Windows Form來或是某些Windows Form控制項來實作,可是整個系統的外觀已經是既定的WPF了,那要怎麼把Windows Form整合進來呢??
在開發WPF的專案時,有時候可能會礙於平台的限制或是使用的語言及類別庫的限制,部份功能還是得透過Windows Form來或是某些Windows Form控制項來實作,可是整個系統的外觀已經是既定的WPF了,那要怎麼把Windows Form整合進來呢??
首先,得引用WindowsFormsIntegration.dll(若使用.Net Framework 4.0版的話,預設路徑在C:\Windows\Microsoft.NET\Framework\v4.0.30319\WPF),以及System.Windows.Forms,接著就可以在WPF中透過WindowsFormsHost這個元件來承載Windows Form的控制項了!!
來寫個小小的範例:
<Window x:Class="WPF_Winform.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:WinFormHost="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration"
xmlns:WinFormControls="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
mc:Ignorable="d"
Title="MainWindow"
d:DesignWidth="800" d:DesignHeight="600"
Width="Auto" Height="Auto">
<Grid>
<WinFormHost:WindowsFormsHost Name="winFormHost">
<WinFormControls:FlowLayoutPanel Name="floPanel" BackColor="Transparent">
<WinFormControls:FlowLayoutPanel.Controls>
<WinFormControls:Label Text="WinformLabel"/>
<WinFormControls:TextBox Width="200"/>
<WinFormControls:Button Text="WinformButton" Width="150"/>
</WinFormControls:FlowLayoutPanel.Controls>
</WinFormControls:FlowLayoutPanel>
</WinFormHost:WindowsFormsHost>
</Grid>
</Window>
那~能不能在這邊的Windows Form控制項裡面再放WPF控制項呢?答案是可以的!!透過ElementHost控制項就可以辦到囉,而且我們也可以直接在XAML中分別替Windows Form和WPF的按鈕元件加入Click的EventHandler喔!!
我們來修改一下MainWindow.xaml
<Window x:Class="WPF_Winform.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:WinFormHost="clr-namespace:System.Windows.Forms.Integration;assembly=WindowsFormsIntegration"
xmlns:WinFormControls="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
mc:Ignorable="d"
Title="MainWindow"
d:DesignWidth="800" d:DesignHeight="600"
Width="Auto" Height="Auto">
<Grid Background="Gray">
<WinFormHost:WindowsFormsHost Name="winFormHost" VerticalAlignment="Center" HorizontalAlignment="Center" Background="White">
<WinFormControls:FlowLayoutPanel Name="floPanel" BackColor="Transparent">
<WinFormControls:FlowLayoutPanel.Controls>
<WinFormControls:Label Text="WinformLabel"/>
<WinFormControls:TextBox Width="200"/>
<WinFormControls:Button Text="WinformButton" Width="150" Click="Button_Click"/>
<ElementHost Height="200" Width="200">
<Grid Height="200" Width="200" VerticalAlignment="Center" HorizontalAlignment="Center" Background="Yellow">
<Button Content="WPF Button" Width="150" Height="40" Click="Button_Click"/>
</Grid>
</ElementHost>
</WinFormControls:FlowLayoutPanel.Controls>
</WinFormControls:FlowLayoutPanel>
</WinFormHost:WindowsFormsHost>
</Grid>
</Window>
還有MainWindow.xaml.cs,Windows Form和WPF的Button產生出來的Click EventHandler長相不一樣喔!!
using System.Windows;
namespace WPF_Winform
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click( object sender , System.EventArgs e )
{
MessageBox.Show("你點了Winform的按鈕");
}
private void Button_Click( object sender , RoutedEventArgs e )
{
MessageBox.Show( "你點了WPF的按鈕" );
}
}
}
執行結果會變這樣:
很好玩吧~
不過要注意一點,尤於Render機制不同的關係,若是想要把WPF的控制項覆蓋在WindowsFormsHost控制項之上的話,是做不到的喔!!WindowsFormsHost原生就會具有類似AlwaysOnTop的效果~
最後,附上專案原始碼,請有興趣的人自行服用: