逐步解說:在 WPF 中排列 Windows Form 控制項
本逐步解說將示範如何使用 WPF 版面配置功能,來排列混合式應用程式中的 Windows Forms 控制項。
這個逐步解說中所述的工作包括:
- 建立專案。
- 使用預設的版面配置設定。
- 依內容調整大小。
- 使用絕對位置。
- 明確指定大小。
- 設定版面配置屬性。
- 了解疊置順序的限制。
- 停駐。
- 設定可見度。
- 裝載不會自動縮放的控制項。
- 調整大小。
- 旋轉。
- 設定邊框距離及邊界。
- 使用動態版面配置容器。
如需本逐步解說中所述工作的完整程式碼清單, 請參閱 在 WPF 中排列 Windows Form 控制項範例。
完成後,您將了解以 Windows Forms 為基礎之應用程式中的 WPF 版面配置功能。
必要條件
若要完成這個逐步解說,您必須具有 Visual Studio。
建立專案
要建立並設定專案,請遵循以下步驟:
建立名為
WpfLayoutHostingWf
的 WPF 應用程式專案。在方案總管中,添加以下組件的參考:
- WindowsFormsIntegration
- System.Windows.Forms
- System.Drawing
按兩下 MainWindow.xaml 以在 XAML 檢視中開啟。
在 Window 元素中,新增對該下列命名空間的對應。
xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
在 Grid 元素中,將 ShowGridLines 屬性設定為
true
,並定義五行三列。<Grid ShowGridLines="true"> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition/> <RowDefinition/> <RowDefinition/> <RowDefinition/> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition/> <ColumnDefinition/> </Grid.ColumnDefinitions>
使用預設的版面配置設定
根據預設, WindowsFormsHost 項目會處理託管 Windows Forms 控制項的配置。
如需使用預設的版面配置設定,請遵循下列步驟:
將下列 XAML 複製到 Grid 元素:
<!-- Default layout. --> <Canvas Grid.Row="0" Grid.Column="0"> <WindowsFormsHost Background="Yellow"> <wf:Button Text="Windows Forms control" FlatStyle="Flat"/> </WindowsFormsHost> </Canvas>
按 F5 以建置並執行應用程式。 Windows Forms System.Windows.Forms.Button 控制項會出現在 Canvas中。 裝載的控制項大小會根據其內容來調整,並調整 WindowsFormsHost 元素的大小以容納裝載的控制項。
依內容調整大小
WindowsFormsHost 元素確保託管控制項的大小能正確顯示其內容。
若要調整內容大小,請遵循下列步驟:
將下列 XAML 複製到 Grid 元素:
<!-- Sizing to content. --> <Canvas Grid.Row="1" Grid.Column="0"> <WindowsFormsHost Background="Orange"> <wf:Button Text="Windows Forms control with more content" FlatStyle="Flat"/> </WindowsFormsHost> </Canvas> <Canvas Grid.Row="2" Grid.Column="0"> <WindowsFormsHost FontSize="24" Background="Yellow"> <wf:Button Text="Windows Forms control" FlatStyle="Flat"/> </WindowsFormsHost> </Canvas>
按 F5 以建置並執行應用程式。 調整兩個新按鈕控制項的大小以顯示較長的文字字串,並適當地放大字型大小,以及調整 WindowsFormsHost 元素的大小來容納裝載的控制項。
使用絕對位置
您可以使用絕對定位將 WindowsFormsHost 元素放置在使用者介面(UI)的任何位置。
若要使用絕對定位,請遵循下列步驟:
將下列 XAML 複製到 Grid 元素:
<!-- Absolute positioning. --> <Canvas Grid.Row="3" Grid.Column="0"> <WindowsFormsHost Canvas.Top="20" Canvas.Left="20" Background="Yellow"> <wf:Button Text="Windows Forms control with absolute positioning" FlatStyle="Flat"/> </WindowsFormsHost> </Canvas>
按 F5 以建置並執行應用程式。 將 WindowsFormsHost 元素放置於從方格儲存格上方起算 20 個像素且從左邊起算 20 個像素的地方。
明確指定大小
您可以使用 Width 和 Height 屬性來指定 WindowsFormsHost 專案的大小。
若要明確指定大小,請遵循下列步驟:
將下列 XAML 複製到 Grid 元素:
<!-- Explicit sizing. --> <Canvas Grid.Row="4" Grid.Column="0"> <WindowsFormsHost Width="50" Height="70" Background="Yellow"> <wf:Button Text="Windows Forms control" FlatStyle="Flat"/> </WindowsFormsHost> </Canvas>
按 F5 以建置並執行應用程式。 將 WindowsFormsHost 元素設為 50 個像素寬且 70 個像素高的大小,此大小小於預設的版面配置設定。 據以重新排列 Windows Forms 控制項的內容。
設定版面配置屬性
一律使用 WindowsFormsHost 元素的屬性,在裝載的控制項上設定版面配置相關的屬性。 直接在裝載的控制項上設定版面配置屬性,將產生非預期的結果。
在 XAML 中裝載的控制項上設定版面配置相關屬性不會產生任何作用。
要查看在託管控制項上設定屬性的效果,請遵循以下步驟:
將下列 XAML 複製到 Grid 元素:
<!-- Setting hosted control properties directly. --> <Canvas Grid.Row="0" Grid.Column="1"> <WindowsFormsHost Width="160" Height="50" Background="Yellow"> <wf:Button Name="button1" Click="button1_Click" Text="Click me" FlatStyle="Flat" BackColor="Green"/> </WindowsFormsHost> </Canvas>
在 方案總管中按兩下 MainWindow.xaml.vb 或 MainWindow.xaml.cs,以在設計工具中開啟它。
將下列程式碼複製至
MainWindow
類別定義。private void button1_Click(object sender, EventArgs e ) { System.Windows.Forms.Button b = sender as System.Windows.Forms.Button; b.Top = 20; b.Left = 20; }
Private Sub button1_Click(ByVal sender As Object, ByVal e As EventArgs) Dim b As System.Windows.Forms.Button = sender b.Top = 20 b.Left = 20 End Sub
按 F5 以建置並執行應用程式。
按一下 Click me 按鈕。
button1_Click
事件處理程序設定託管控制項上的 Top 和 Left 屬性。 這會導致託管控制項在 WindowsFormsHost 元素中重新定位。 主機會維持相同的螢幕區域,但會裁剪裝載的控制項。 相反地,託管控制項應始終填滿 WindowsFormsHost 元素。
了解疊置順序的限制
可見 WindowsFormsHost 元素將一律繪製在其他 WPF 元素之上,且不受Z 軸順序的影響。 若要查看該 Z 軸順序行為,請執行下列步驟:
將下列 XAML 複製到 Grid 元素:
<!-- Z-order demonstration. --> <Canvas Grid.Row="1" Grid.Column="1"> <WindowsFormsHost Canvas.Top="20" Canvas.Left="20" Background="Yellow"> <wf:Button Text="Windows Forms control" FlatStyle="Flat"/> </WindowsFormsHost> <Label Content="A WPF label" FontSize="24"/> </Canvas>
按 F5 以建置並執行應用程式。 WindowsFormsHost 元素會繪製在標籤元素上。
銜接
WindowsFormsHost 元素支援 WPF 停駐。 將 Dock 附加屬性設定為將託管控制項停駐到 DockPanel 元素中。
若要停駐託管控制項,請遵循以下步驟:
將下列 XAML 複製到 Grid 元素:
<!-- Docking a WindowsFormsHost element. --> <DockPanel LastChildFill="false" Grid.Row="2" Grid.Column="1"> <WindowsFormsHost DockPanel.Dock="Right" Canvas.Top="20" Canvas.Left="20" Background="Yellow"> <wf:Button Text="Windows Forms control" FlatStyle="Flat"/> </WindowsFormsHost> </DockPanel>
按 F5 以建置並執行應用程式。 WindowsFormsHost 元素停駐在 DockPanel 元素的右側。
設定可見度
您可以透過在 WindowsFormsHost 元素上設定 Visibility 屬性,使 Windows Forms 控制項不可見或摺疊。 當控制項隱藏時,它不會顯示,但會佔據版面配置空間。 當控制項摺疊時,它不會顯示,也不會佔據配置空間。
如需設定託管控制項的可見度,請遵循以下步驟:
將下列 XAML 複製到 Grid 元素:
<!-- Setting Visibility to hidden and collapsed. --> <StackPanel Grid.Row="3" Grid.Column="1"> <Button Name="button2" Click="button2_Click" Content="Click to make invisible" Background="OrangeRed"/> <WindowsFormsHost Name="host1" Background="Yellow"> <wf:Button Text="Windows Forms control" FlatStyle="Flat"/> </WindowsFormsHost> <Button Name="button3" Click="button3_Click" Content="Click to collapse" Background="OrangeRed"/> </StackPanel>
在 MainWindow.xaml.vb 或 MainWindow.xaml.cs 中,將下列程式碼複製到類別定義中。
private void button2_Click(object sender, EventArgs e) { this.host1.Visibility = Visibility.Hidden; } private void button3_Click(object sender, EventArgs e) { this.host1.Visibility = Visibility.Collapsed; }
Private Sub button2_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) Me.host1.Visibility = Windows.Visibility.Hidden End Sub Private Sub button3_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) Me.host1.Visibility = Windows.Visibility.Collapsed End Sub
按 F5 以建置並執行應用程式。
點擊 按鈕使 按鈕不可見,以使 WindowsFormsHost 元素不可見。
點擊 按鈕折疊 按鈕,以使 WindowsFormsHost 元素完全隱藏在版面配置中。 摺疊 Windows Forms 控制項時,會重新排列周圍的元素以佔用它的空間。
裝載不會自動縮放的控制項
某些 Windows Forms 控制項具有固定的大小,因此不會進行自動縮放來填滿版面配置中的可用空間。 例如,MonthCalendar 控制項會在固定空間中顯示月份。
如需託管不會延展的控制項,請遵循以下步驟:
將下列 XAML 複製到 Grid 元素:
<!-- Hosting a control that does not stretch. --> <!-- The MonthCalendar has a discrete size. --> <StackPanel Grid.Row="4" Grid.Column="1"> <Label Content="A WPF element" Background="OrangeRed"/> <WindowsFormsHost Background="Yellow"> <wf:MonthCalendar/> </WindowsFormsHost> <Label Content="Another WPF element" Background="OrangeRed"/> </StackPanel>
按 F5 以建置並執行應用程式。 WindowsFormsHost 元素位於格線列的中心,但不會延展以填滿可用空間。 如果視窗夠大,您可能會看到託管的 MonthCalendar 控制項顯示了兩個以上的月份,但這些會放置於資料列中間。 WPF 版面配置引擎會將元素置中,而這些元素無法調整大小來填滿可用空間。
調整大小
不同於 WPF 元素,大部分的 Windows Forms 控制項都不會持續縮放。 要提供自定義縮放,您需要覆寫 WindowsFormsHost.ScaleChild 方法。
如需使用預設行為縮放裝載的控制項,請遵循下列步驟:
將下列 XAML 複製到 Grid 元素:
<!-- Scaling transformation. --> <StackPanel Grid.Row="0" Grid.Column="2"> <StackPanel.RenderTransform> <ScaleTransform CenterX="0" CenterY="0" ScaleX="0.5" ScaleY="0.5" /> </StackPanel.RenderTransform> <Label Content="A WPF UIElement" Background="OrangeRed"/> <WindowsFormsHost Background="Yellow"> <wf:Button Text="Windows Forms control" FlatStyle="Flat"/> </WindowsFormsHost> <Label Content="Another WPF UIElement" Background="OrangeRed"/> </StackPanel>
按 F5 以建置並執行應用程式。 裝載的控制項及其周圍元素會縮放 0.5 倍。 不過,裝載控制項的字型不會進行縮放。
旋轉
不同於 WPF 元素, Windows Forms 控制項不支援旋轉。 當套用旋轉變換時,WindowsFormsHost 元素不會與其他 WPF 元素一起旋轉。 180 度以外的任何旋轉值會觸發 LayoutError 事件。
如需查看混合式應用程式中的旋轉效果,請遵循下列步驟:
將下列 XAML 複製到 Grid 元素:
<!-- Rotation transformation. --> <StackPanel Grid.Row="1" Grid.Column="2"> <StackPanel.RenderTransform> <RotateTransform CenterX="200" CenterY="50" Angle="180" /> </StackPanel.RenderTransform> <Label Content="A WPF element" Background="OrangeRed"/> <WindowsFormsHost Background="Yellow"> <wf:Button Text="Windows Forms control" FlatStyle="Flat"/> </WindowsFormsHost> <Label Content="Another WPF element" Background="OrangeRed"/> </StackPanel>
按 F5 以建置並執行應用程式。 裝載的控制項不會旋轉,但其周圍元素會旋轉 180 度。 您可能必須調整視窗大小來查看元素。
設定邊框距離及邊界
WPF 版面配置中的邊框距離及邊界類似於 Windows Forms 中的邊框距離及邊界。 只要在 WindowsFormsHost 元素上設定 Padding 和 Margin 屬性即可。
如需設定託管控制項的邊框距離及邊界,請遵循下列步驟:
將下列 XAML 複製到 Grid 元素:
<!-- Padding. --> <Canvas Grid.Row="2" Grid.Column="2"> <WindowsFormsHost Padding="0, 20, 0, 0" Background="Yellow"> <wf:Button Text="Windows Forms control with padding" FlatStyle="Flat"/> </WindowsFormsHost> </Canvas>
<!-- Margin. --> <Canvas Grid.Row="3" Grid.Column="2"> <WindowsFormsHost Margin="20, 20, 0, 0" Background="Yellow"> <wf:Button Text="Windows Forms control with margin" FlatStyle="Flat"/> </WindowsFormsHost> </Canvas>
按 F5 以建置並執行應用程式。 邊框距離及邊界設定會以在 Windows Forms 中套用它們的相同方式,套用至託管的 Windows Forms 控制項。
使用動態版面配置容器
Windows Forms 提供兩個動態配置容器, FlowLayoutPanel 和 TableLayoutPanel。 您也可以在 WPF 版面配置中使用這些容器。
如需使用動態版面配置容器,請遵循下列步驟:
將下列 XAML 複製到 Grid 元素:
<!-- Flow layout. --> <DockPanel Grid.Row="4" Grid.Column="2"> <WindowsFormsHost Name="flowLayoutHost" Background="Yellow"> <wf:FlowLayoutPanel/> </WindowsFormsHost> </DockPanel>
在 MainWindow.xaml.vb 或 MainWindow.xaml.cs 中,將下列程式碼複製到類別定義中。
private void InitializeFlowLayoutPanel() { System.Windows.Forms.FlowLayoutPanel flp = this.flowLayoutHost.Child as System.Windows.Forms.FlowLayoutPanel; flp.WrapContents = true; const int numButtons = 6; for (int i = 0; i < numButtons; i++) { System.Windows.Forms.Button b = new System.Windows.Forms.Button(); b.Text = "Button"; b.BackColor = System.Drawing.Color.AliceBlue; b.FlatStyle = System.Windows.Forms.FlatStyle.Flat; flp.Controls.Add(b); } }
Private Sub InitializeFlowLayoutPanel() Dim flp As System.Windows.Forms.FlowLayoutPanel = Me.flowLayoutHost.Child flp.WrapContents = True Const numButtons As Integer = 6 Dim i As Integer For i = 0 To numButtons Dim b As New System.Windows.Forms.Button() b.Text = "Button" b.BackColor = System.Drawing.Color.AliceBlue b.FlatStyle = System.Windows.Forms.FlatStyle.Flat flp.Controls.Add(b) Next i End Sub
在建構函式中加入對
InitializeFlowLayoutPanel
方法的呼叫。public MainWindow() { InitializeComponent(); this.InitializeFlowLayoutPanel(); }
Public Sub New() InitializeComponent() Me.InitializeFlowLayoutPanel() End Sub
按 F5 以建置並執行應用程式。 WindowsFormsHost 專案會填滿 DockPanel, FlowLayoutPanel 在預設 FlowDirection中排列其子控制項。