Compartilhar via


Passo a passo: organizando controles do Windows Forms no WPF

Este passo a passo mostra como usar recursos de layout do WPF para organizar controles do Windows Forms em um aplicativo híbrido.

As tarefas ilustradas neste passo a passo incluem:

  • Criando o projeto.
  • Usando configurações de layout padrão.
  • Dimensionamento para conteúdo.
  • Usando o posicionamento absoluto.
  • Especificando o tamanho explicitamente.
  • Definindo propriedades de layout.
  • Noções básicas sobre limitações de ordem z.
  • Acoplamento
  • Configurando a visibilidade.
  • Hospedando um controle que não se expande.
  • Dimensionamento.
  • Giratório.
  • Configurando o espaçamento e as margens.
  • Usando contêineres de layout dinâmico.

Para obter uma listagem de código completa das tarefas ilustradas neste passo a passo, consulte Organizando controles do Windows Forms node exemplo do WPF.

Quando terminar, você terá uma compreensão dos recursos de layout do Windows Forms em aplicativos baseados em WPF.

Pré-requisitos

Você precisa do Visual Studio para concluir este passo a passo.

Criando o projeto

Para criar e configurar o projeto, siga estas etapas:

  1. Criar um projeto de aplicativo WPF chamado WpfLayoutHostingWf.

  2. No Gerenciador de Soluções, adicione referências aos seguintes assemblies:

    • WindowsFormsIntegration
    • System.Windows.Forms
    • System.Drawing
  3. Clique duas vezes MainWindow.xaml para abri-lo no modo de exibição XAML.

  4. No elemento Window, adicione o seguinte mapeamento de namespace do Windows Forms.

    xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
    
  5. No elemento Grid, defina a propriedade ShowGridLines como true e defina cinco linhas e três colunas.

    <Grid ShowGridLines="true">
      <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition/>
        <RowDefinition/>
        <RowDefinition/>
        <RowDefinition/>
      </Grid.RowDefinitions>
    
      <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition/>
        <ColumnDefinition/>
      </Grid.ColumnDefinitions>
    

Usando configurações de layout padrão

Por padrão, o elemento WindowsFormsHost manipula o layout do controle hospedado do Windows Forms.

Para usar as configurações de layout padrão, siga estas etapas:

  1. Copie o seguinte XAML para o elemento Grid:

    <!-- Default layout. -->
    <Canvas Grid.Row="0" Grid.Column="0">
      <WindowsFormsHost Background="Yellow">
        <wf:Button Text="Windows Forms control" FlatStyle="Flat"/>
      </WindowsFormsHost>
    </Canvas>
    
  2. Pressione F5 para compilar e executar o aplicativo. O controle System.Windows.Forms.Button do Windows Forms aparece no Canvas. O controle hospedado é dimensionado com base em seu conteúdo e o elemento WindowsFormsHost é dimensionado para acomodar o controle hospedado.

Ajuste ao Conteúdo

O elemento WindowsFormsHost garante que o controle hospedado seja dimensionado para exibir seu conteúdo corretamente.

Para dimensionar o conteúdo, siga estas etapas:

  1. Copie o seguinte XAML para o elemento 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>
    
  2. Pressione F5 para compilar e executar o aplicativo. Os dois novos controles de botão são dimensionados para exibir a cadeia de caracteres de texto mais longa e o tamanho da fonte maior corretamente, e os elementos WindowsFormsHost são redimensionados para acomodar os controles hospedados.

Usando o posicionamento absoluto

Você pode usar o posicionamento absoluto para colocar o elemento WindowsFormsHost em qualquer lugar na interface do usuário (interface do usuário).

Para usar o posicionamento absoluto, siga estas etapas:

  1. Copie o seguinte XAML para o elemento 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>
    
  2. Pressione F5 para compilar e executar o aplicativo. O elemento WindowsFormsHost é colocado a 20 pixels do lado superior da célula da grade e a 20 pixels da esquerda.

Especificando o tamanho explicitamente

Você pode especificar o tamanho do elemento WindowsFormsHost usando as propriedades Width e Height.

Para especificar o tamanho explicitamente, siga estas etapas:

  1. Copie o seguinte XAML para o elemento 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>
    
  2. Pressione F5 para compilar e executar o aplicativo. O elemento WindowsFormsHost é definido como um tamanho de 50 pixels de largura por 70 pixels de altura, que é menor que as configurações de layout padrão. O conteúdo do controle de Windows Forms é reorganizado de forma adequada.

Definindo propriedades de layout

Sempre defina propriedades relacionadas ao layout no controle hospedado usando as propriedades do elemento WindowsFormsHost. Definir propriedades de layout diretamente no controle hospedado produzirá resultados não intencionais.

A configuração de propriedades relacionadas ao layout no controle hospedado no XAML não tem efeito.

Para ver os efeitos da configuração de propriedades no controle hospedado, siga estas etapas:

  1. Copie o seguinte XAML para o elemento 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>
    
  2. No Gerenciador de Soluções, clique duas vezes em MainWindow.xaml.vb ou MainWindow.xaml.cs para abrir no Editor de Código.

  3. Copie o seguinte código para a definição de classe 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
    
  4. Pressione F5 para compilar e executar o aplicativo.

  5. Clique no botão Clique aqui. O manipulador de eventos button1_Click define as propriedades Top e Left no controle hospedado. Isso faz com que o controle hospedado seja reposicionado dentro do elemento WindowsFormsHost. O host mantém a mesma área de tela, mas o controle hospedado é recortado. Em vez disso, o controle hospedado deve sempre preencher o elemento WindowsFormsHost.

Noções básicas sobre limitações de ordem Z

Elementos de WindowsFormsHost visíveis são sempre desenhados sobre outros elementos do WPF e não são afetados pela ordem z. Para ver esse comportamento de ordem z, faça o seguinte:

  1. Copie o seguinte XAML para o elemento 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>
    
  2. Pressione F5 para compilar e executar o aplicativo. O elemento WindowsFormsHost é pintado sobre o elemento de rótulo.

Acoplamento

O elemento WindowsFormsHost dá suporte ao encaixe em WPF. Defina a propriedade anexada Dock para encaixar o controle hospedado em um elemento DockPanel.

Para encaixar um controle hospedado, siga estas etapas:

  1. Copie o seguinte XAML para o elemento 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>
    
  2. Pressione F5 para compilar e executar o aplicativo. O elemento WindowsFormsHost é encaixado no lado direito do elemento DockPanel.

Configurando visibilidade

Você pode tornar o controle do Windows Forms invisível ou recolhê-lo definindo a propriedade Visibility no elemento WindowsFormsHost. Quando um controle é invisível, ele não é exibido, mas ocupa o espaço de layout. Quando um controle é recolhido, ele não é exibido, nem ocupa o espaço de layout.

Para definir a visibilidade de um controle hospedado, siga estas etapas:

  1. Copie o seguinte XAML para o elemento 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>
    
  2. Em MainWindow.xaml.vb ou MainWindow.xaml.cs, copie o seguinte código para a definição de classe:

    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
    
  3. Pressione F5 para compilar e executar o aplicativo.

  4. Clique no botão Clique para tornar invisível para tornar o elemento WindowsFormsHost invisível.

  5. Clique no botão para recolher para ocultar totalmente o elemento WindowsFormsHost do layout. Quando o controle Windows Forms é recolhido, os elementos ao redor são reorganizados para ocupar seu espaço.

Hospedando um controle que não se expande

Alguns controles do Windows Forms têm um tamanho fixo e não se estendem para preencher o espaço disponível no layout. Por exemplo, o controle MonthCalendar exibe um mês em um espaço fixo.

Para incorporar um controle que não se estende, siga estas etapas:

  1. Copie o seguinte XAML para o elemento 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>
    
  2. Pressione F5 para compilar e executar o aplicativo. O elemento WindowsFormsHost é centralizado na linha de grade, mas não é estendido para preencher o espaço disponível. Se a janela for grande o suficiente, você poderá ver dois ou mais meses exibidos pelo controle de MonthCalendar hospedado, mas eles estão centralizados na fileira. O mecanismo de layout do WPF centraliza elementos que não podem ser dimensionados para preencher o espaço disponível.

Escalonamento

Ao contrário dos elementos do WPF, a maioria dos controles do Windows Forms não são continuamente escalonáveis. Para fornecer dimensionamento personalizado, substitua o método WindowsFormsHost.ScaleChild.

Para dimensionar um controle hospedado usando o comportamento padrão, siga estas etapas:

  1. Copie o seguinte XAML para o elemento 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>
    
  2. Pressione F5 para compilar e executar o aplicativo. O controle hospedado e seus elementos ao redor são dimensionados por um fator de 0,5. No entanto, a fonte do controle hospedado não é dimensionada.

Giratório

Ao contrário dos elementos do WPF, os controles do Windows Forms não dão suporte à rotação. O elemento WindowsFormsHost não gira com outros elementos do WPF quando uma transformação de rotação é aplicada. Qualquer valor de rotação diferente de 180 graus gera o evento LayoutError.

Para ver o efeito da rotação em um aplicativo híbrido, siga estas etapas:

  1. Copie o seguinte XAML para o elemento 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>
    
  2. Pressione F5 para compilar e executar o aplicativo. O controle hospedado não é girado, mas seus elementos ao redor são girados por um ângulo de 180 graus. Talvez seja necessário redimensionar a janela para ver os elementos.

Configurando Espaçamento Interno e Margens

O preenchimento e as margens no layout do WPF são semelhantes ao preenchimento e às margens nos Windows Forms. Basta definir as propriedades Padding e Margin no elemento WindowsFormsHost.

Para definir o preenchimento e as margens de um controle hospedado, siga estas etapas:

  1. Copie o seguinte XAML para o elemento 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>
    
  2. Pressione F5 para compilar e executar o aplicativo. As configurações de preenchimento e margem são aplicadas aos controles hospedados do Windows Forms da mesma forma que seriam aplicadas no Windows Forms.

Usando contêineres de layout dinâmico

O Windows Forms fornece dois contêineres de layout dinâmico, FlowLayoutPanel e TableLayoutPanel. Você também pode usar esses contêineres em layouts do WPF.

Para usar um contêiner de layout dinâmico, siga estas etapas:

  1. Copie o seguinte XAML para o elemento Grid:

    <!-- Flow layout. -->
    <DockPanel Grid.Row="4" Grid.Column="2">
      <WindowsFormsHost Name="flowLayoutHost" Background="Yellow">
        <wf:FlowLayoutPanel/>
      </WindowsFormsHost>
    </DockPanel>
    
  2. Em MainWindow.xaml.vb ou MainWindow.xaml.cs, copie o seguinte código para a definição de classe:

    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
    
  3. Adicione uma chamada ao método InitializeFlowLayoutPanel no construtor:

    public MainWindow()
    {
        InitializeComponent();
    
        this.InitializeFlowLayoutPanel();
    }
    
    Public Sub New()
        InitializeComponent()
    
        Me.InitializeFlowLayoutPanel()
    
    End Sub
    
  4. Pressione F5 para compilar e executar o aplicativo. O elemento WindowsFormsHost preenche o DockPanel, e FlowLayoutPanel organiza seus controles-filho no FlowDirectionpadrão.

Consulte também