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:

  • Criar o projeto.
  • Usando configurações de layout padrão.
  • Ajuste ao 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 preenchimento 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 Organizar controles do Windows Forms no 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 em MainWindow.xaml para abri-lo no modo de exibição XAML.

  4. Window No elemento, 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 configure 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 WindowsFormsHost elemento 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 Grid elemento:

    <!-- 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 Windows Forms System.Windows.Forms.Button aparece no Canvas. O controle hospedado é dimensionado com base em seu conteúdo e o WindowsFormsHost elemento é dimensionado para acomodar o controle hospedado.

Dimensionamento para conteúdo

O WindowsFormsHost elemento 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 Grid elemento:

    <!-- 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 WindowsFormsHost elementos são redimensionados para acomodar os controles hospedados.

Usando o posicionamento absoluto

Você pode usar o posicionamento absoluto para colocar o WindowsFormsHost elemento 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 Grid elemento:

    <!-- 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 WindowsFormsHost elemento é colocado a 20 pixels a partir do lado superior da célula de grade e a 20 pixels do lado esquerdo.

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 Grid elemento:

    <!-- 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 WindowsFormsHost elemento é 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 do Windows Forms é reorganizado de forma adequada.

Definindo propriedades de layout

Sempre defina propriedades relacionadas ao layout no controle hospedado usando as propriedades do WindowsFormsHost elemento. 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 Grid elemento:

    <!-- 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 abri-lo no Editor de Código.

  3. Copie o seguinte código para a definição de MainWindow classe:

    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 Clicar em mim . O button1_Click manipulador de eventos define as propriedades Top e Left no controle hospedado. Isso faz com que o controle hospedado seja reposicionado dentro do WindowsFormsHost elemento. O host mantém a mesma área de tela, mas o controle hospedado é recortado. Em vez disso, o controle hospedado deve sempre preencher o WindowsFormsHost elemento.

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

Elementos visíveis WindowsFormsHost 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 Grid elemento:

    <!-- 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 WindowsFormsHost elemento é pintado sobre o elemento de rótulo.

Atracação

WindowsFormsHost o elemento dá suporte ao encaixe do WPF. Configure 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 Grid elemento:

    <!-- 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 WindowsFormsHost elemento é encaixado no lado direito do DockPanel elemento.

Configurando visibilidade

Você pode tornar o controle 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 está colapsado, ele não é exibido nem ocupa espaço no layout.

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

  1. Copie o seguinte XAML para o Grid elemento:

    <!-- 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 o elemento WindowsFormsHost invisível.

  5. Clique no botão Clique 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 alonga

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 MonthCalendar controle exibe um mês em um espaço fixo.

Para hospedar um controle que não se alonga, siga estas etapas:

  1. Copie o seguinte XAML para o Grid elemento:

    <!-- 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 WindowsFormsHost elemento é 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 hospedado MonthCalendar , mas eles são centralizados na linha. 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 WindowsFormsHost.ScaleChild método.

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

  1. Copie o seguinte XAML para o Grid elemento:

    <!-- 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 WindowsFormsHost elemento 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 Grid elemento:

    <!-- 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 preenchimento 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 e Padding o MarginWindowsFormsHost elemento.

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

  1. Copie o seguinte XAML para o Grid elemento:

    <!-- 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 aplicados nos Windows Forms.

Usando contêineres de layout dinâmico

O Windows Forms fornece dois contêineres FlowLayoutPanel de layout dinâmico 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 Grid elemento:

    <!-- 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 InitializeFlowLayoutPanel método 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 WindowsFormsHost elemento preenche e DockPanelFlowLayoutPanel organiza seus controles filho no padrãoFlowDirection.

Consulte também