Compartir a través de


Tutorial: Organizar controles de formularios Windows Forms en WPF

En este tutorial se muestra cómo usar las características de diseño de WPF para organizar controles de Windows Forms en una aplicación híbrida.

Las tareas ilustradas en este tutorial incluyen:

  • Crear el proyecto.
  • Usar la configuración de diseño predeterminada.
  • Ajustar el tamaño al contenido.
  • Usar el posicionamiento absoluto.
  • Especificar el tamaño explícitamente.
  • Establecer las propiedades de diseño.
  • Entender las limitaciones del orden Z.
  • Acoplar.
  • Establecer la visibilidad.
  • Hospedar un control que no se ajusta.
  • Ajustar la escala.
  • Girar.
  • Establecer el relleno y los márgenes.
  • Usar contenedores de diseño dinámico.

Para obtener una lista de código completa de las tareas mostradas en este tutorial, vea Arranging Windows Forms Controls in WPF Sample (Ejemplo de cómo organizar controles de Windows Forms en WPF).

Cuando acabe, entenderá mejor las características de diseño de Windows Forms en aplicaciones basadas en WPF.

Requisitos previos

Necesita Visual Studio para completar este tutorial.

Crear el proyecto

Para crear y configurar el proyecto, siga estos pasos:

  1. Cree un proyecto de aplicación WPF denominado WpfLayoutHostingWf.

  2. En el Explorador de soluciones, agregue referencias a los ensamblados siguientes:

    • WindowsFormsIntegration
    • System.Windows.Forms
    • System.Drawing
  3. Haga doble clic en MainWindow.xaml para abrirlo en la vista XAML.

  4. En el elemento Window, agregue la siguiente asignación de espacio de nombres de Windows Forms.

    xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms"
    
  5. En el elemento Grid, establezca la propiedad ShowGridLines en true y defina cinco filas y tres columnas.

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

Usar la configuración de diseño predeterminada

De manera predeterminada, el elemento WindowsFormsHost controla el diseño del control de Windows Forms hospedado.

Para usar la configuración de diseño predeterminada, siga estos pasos:

  1. Copie el siguiente XAML en el 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. Presione F5 para compilar y ejecutar la aplicación. El control System.Windows.Forms.Button de Windows Forms aparece en Canvas. El tamaño del control hospedado se ajusta en función de su contenido y el tamaño del elemento WindowsFormsHost se ajusta para contener el control hospedado.

Ajustar el tamaño al contenido

El elemento WindowsFormsHost garantiza que el tamaño del control hospedado se ajusta de modo que su contenido se muestre correctamente.

Para ajustar el tamaño al contenido, siga estos pasos:

  1. Copie el siguiente XAML en el 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. Presione F5 para compilar y ejecutar la aplicación. El tamaño de los dos nuevos controles de botón se ajusta para mostrar correctamente la cadena de texto más larga y el tamaño de fuente mayor, y el tamaño de los elementos WindowsFormsHost se cambia para que contengan los controles hospedados.

Usar el posicionamiento absoluto

Puede usar el posicionamiento absoluto para colocar el elemento WindowsFormsHost en cualquier parte de la interfaz de usuario.

Para usar el posicionamiento absoluto, siga estos pasos:

  1. Copie el siguiente XAML en el 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. Presione F5 para compilar y ejecutar la aplicación. El elemento WindowsFormsHost se coloca a 20 píxeles de la parte superior de la celda de la cuadrícula y a 20 píxeles de la izquierda.

Especificar el tamaño explícitamente

Puede especificar el tamaño del elemento WindowsFormsHost mediante las propiedades Width y Height.

Para especificar el tamaño explícitamente, siga estos pasos:

  1. Copie el siguiente XAML en el 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. Presione F5 para compilar y ejecutar la aplicación. El elemento WindowsFormsHost se establece en un tamaño de 50 píxeles de ancho por 70 píxeles de alto, que es menor que la configuración de diseño predeterminada. El contenido del control de Windows Forms se reorganiza en consecuencia.

Establecer las propiedades de diseño

Establezca siempre las propiedades relacionadas con el diseño en el control hospedado mediante las propiedades del elemento WindowsFormsHost. Si establece las propiedades de diseño directamente en el control hospedado se producirán resultados imprevistos.

El establecimiento de las propiedades relacionadas con el diseño en el control hospedado en XAML no tiene ningún efecto.

Para ver los efectos de establecer las propiedades en el control hospedado, siga estos pasos:

  1. Copie el siguiente XAML en el 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. En el Explorador de soluciones, haga doble clic en MainWindow.xaml.vb o MainWindow.xaml.cs para abrirlo en el Editor de código.

  3. Copie el código siguiente en la definición de clase 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. Presione F5 para compilar y ejecutar la aplicación.

  5. Haga clic en el botón Hacer clic aquí. El controlador de eventos button1_Click establece las propiedades Top y Left en el control hospedado. Esto hace que la posición del control hospedado cambie dentro del elemento WindowsFormsHost. El host conserva la misma área de la pantalla, pero el control hospedado se recorta. En vez de eso, el control hospedado siempre debe rellenar el elemento WindowsFormsHost.

Entender las limitaciones del orden Z

Los elementos WindowsFormsHost visibles siempre se dibujan encima de otros elementos de WPF y no se ven afectados por el orden Z. Para ver este comportamiento de orden Z, haga lo siguiente:

  1. Copie el siguiente XAML en el 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. Presione F5 para compilar y ejecutar la aplicación. El elemento WindowsFormsHost se pinta sobre el elemento de etiqueta.

Acoplamiento

El elemento WindowsFormsHost admite acoplamiento de WPF. Establezca la propiedad adjunta Dock para acoplar el control hospedado en un elemento DockPanel.

Para acoplar un control hospedado, siga estos pasos:

  1. Copie el siguiente XAML en el 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. Presione F5 para compilar y ejecutar la aplicación. El elemento WindowsFormsHost se acopla en el lado derecho del elemento DockPanel.

Establecer la visibilidad

Puede hacer que su control de Windows Forms sea invisible o contraerlo mediante el establecimiento de la propiedad Visibility en el elemento WindowsFormsHost. Cuando un control es invisible no se muestra, pero ocupa espacio de diseño. Cuando un control está contraído no se muestra ni ocupa espacio de diseño.

Para establecer la visibilidad de un control hospedado, siga estos pasos:

  1. Copie el siguiente XAML en el 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. En MainWindow.xaml.vb o MainWindow.xaml.cs, copie el código siguiente en la definición de clase:

    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. Presione F5 para compilar y ejecutar la aplicación.

  4. Haga clic en el botón Click to make invisible (Haga clic para hacer invisible) para que el elemento WindowsFormsHost sea invisible.

  5. Haga clic en el botón Haga clic para contraer para ocultar completamente en el diseño el elemento WindowsFormsHost. Cuando el control de Windows Forms está contraído, los elementos circundantes se reorganizan para ocupar su espacio.

Hospedar un control que no se ajusta

Algunos controles de Windows Forms tienen un tamaño fijo y no se ajustan para rellenar el espacio disponible en el diseño. Por ejemplo, el control MonthCalendar muestra un mes en un espacio fijo.

Para hospedar un control que no se ajusta, siga estos pasos:

  1. Copie el siguiente XAML en el 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. Presione F5 para compilar y ejecutar la aplicación. El elemento WindowsFormsHost se centra en la fila de la cuadrícula, pero no se ajusta para rellenar el espacio disponible. Si la ventana es lo bastante grande, es posible que vea que el control MonthCalendar hospedado muestra dos o más meses, pero están centrados en la fila. El motor de diseño de WPF centra los elementos cuyo tamaño no se puede ajustar para rellenar el espacio disponible.

Ampliación

A diferencia de los elementos de WPF, la mayoría de los controles de Windows Forms no son escalables continuamente. Para proporcionar escalado personalizado, invalide el método WindowsFormsHost.ScaleChild.

Para escalar un control hospedado mediante el comportamiento predeterminado, siga estos pasos:

  1. Copie el siguiente XAML en el 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. Presione F5 para compilar y ejecutar la aplicación. El control hospedado y sus elementos adyacentes se escalan por un factor de 0,5. A pesar de ello, la fuente del control hospedado no se escala.

Girar

A diferencia de los elementos de WPF, los controles de Windows Forms no admiten el giro. De forma predeterminada, el elemento WindowsFormsHost no se gira con los elementos de WPF cuando se aplica una transformación de giro. Cualquier valor de giro distinto de 180 grados provoca el evento LayoutError.

Para ver el efecto del giro en una aplicación híbrida, siga estos pasos:

  1. Copie el siguiente XAML en el 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. Presione F5 para compilar y ejecutar la aplicación. El control hospedado no se gira, pero sus elementos adyacentes se giran en un ángulo de 180 grados. Es posible que deba cambiar el tamaño de la ventana para ver los elementos.

Establecer el relleno y márgenes

El relleno y los márgenes en el diseño de WPF son similares al relleno y los márgenes en Windows Forms. Simplemente establezca las propiedades Padding y Margin en el elemento WindowsFormsHost.

Para establecer el relleno y los márgenes de un control hospedado, siga estos pasos:

  1. Copie el siguiente XAML en el 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. Presione F5 para compilar y ejecutar la aplicación. La configuración del relleno y los márgenes se aplica a los controles hospedados de Windows Forms de la misma manera que se aplicarían en Windows Forms.

Usar contenedores de diseño dinámico

Windows Forms proporciona dos contenedores de diseño dinámico, FlowLayoutPanel y TableLayoutPanel. También puede usar estos contenedores en diseños de WPF.

Para usar un contenedor de diseño dinámico, siga estos pasos:

  1. Copie el siguiente XAML en el elemento Grid:

    <!-- Flow layout. -->
    <DockPanel Grid.Row="4" Grid.Column="2">
      <WindowsFormsHost Name="flowLayoutHost" Background="Yellow">
        <wf:FlowLayoutPanel/>
      </WindowsFormsHost>
    </DockPanel>
    
  2. En MainWindow.xaml.vb o MainWindow.xaml.cs, copie el código siguiente en la definición de clase:

    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. Agregue una llamada al método InitializeFlowLayoutPanel en el constructor:

    public MainWindow()
    {
        InitializeComponent();
    
        this.InitializeFlowLayoutPanel();
    }
    
    Public Sub New()
        InitializeComponent()
    
        Me.InitializeFlowLayoutPanel()
    
    End Sub
    
  4. Presione F5 para compilar y ejecutar la aplicación. El elemento WindowsFormsHost rellena DockPanel y FlowLayoutPanel organiza sus controles secundarios en la FlowDirection predeterminada.

Vea también