[WPF][C#] 在WPF中內嵌WindowsForm控制項

  • 13736
  • 0
  • C#
  • 2013-07-14

在開發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的控制項了!!

 

來寫個小小的範例:

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>
        <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

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長相不一樣喔!!

MainWindow.xaml.cs

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的按鈕" );
        }
    }
}

 

執行結果會變這樣:

image

 

很好玩吧~

 

不過要注意一點,尤於Render機制不同的關係,若是想要把WPF的控制項覆蓋在WindowsFormsHost控制項之上的話,是做不到的喔!!WindowsFormsHost原生就會具有類似AlwaysOnTop的效果~

 

最後,附上專案原始碼,請有興趣的人自行服用: