Tutorial: Hospedar un control compuesto de formularios Windows Forms en Windows Presentation Foundation

Actualización: noviembre 2007

Windows Presentation Foundation (WPF) proporciona un entorno enriquecido para crear aplicaciones. Sin embargo, cuando se tiene una inversión sustancial en código de formularios Windows Forms, puede resultar más efectivo reutilizar al menos parte de ese código en la aplicación de WPF en lugar de volver a escribirlo todo desde el principio. El escenario más común es el caso en que ya existen controles personalizados de formularios Windows Forms. En algunos casos, puede que ni siquiera tenga acceso al código fuente de estos controles. WPF proporciona un procedimiento sencillo para hospedar estos controles en una aplicación de WPF. Por ejemplo, puede utilizar WPF para realizar la mayoría de la programación al hospedar los controles System.Windows.Forms.DataGridView especializados.

En este tutorial se crea paso a paso una aplicación que hospeda un control de formularios Windows Forms compuesto en una página de WPF. Este procedimiento general se puede hacer extensivo a aplicaciones y controles más complejos.

El tutorial está dividido en dos secciones. La primera sección describe brevemente la implementación del control de formularios Windows Forms. La segunda sección explica en detalle cómo hospedar el control en una aplicación de WPF, recibir eventos del control y obtener acceso a algunas de las propiedades del control.

Entre las tareas ilustradas en este tutorial se incluyen:

  • Implementar el control de formularios Windows Forms.

  • Implementar la aplicación host con Windows Presentation Foundation.

Para ver una lista de código completa de las tareas ilustradas en este tutorial, vea Ejemplo Hosting a Windows Forms Composite Control in Windows Presentation Foundation.

Requisitos previos

Necesita los componentes siguientes para completar este tutorial:

  • Visual Studio 2008.

Implementar el control de formularios Windows Forms

El control de formularios Windows Forms utilizado en este ejemplo es un formulario de entrada de datos simple. Este formulario toma el nombre del usuario y su dirección y, a continuación, utiliza un evento personalizado para devolver esa información al host. En la siguiente ilustración se muestra el control representado.

Control de Windows Forms

Control simple de formularios Windows Forms

Crear el proyecto

Para iniciar el proyecto:

  1. Inicie Microsoft Visual Studio y abra el cuadro de diálogo Nuevo proyecto.

  2. Seleccione Proyectos de C# con la plantilla Biblioteca de controles de Windows Forms.

  3. Asigne al nuevo proyecto el nombre MyControls y haga clic en Aceptar para crear el proyecto. El proyecto predeterminado contiene un solo control cuyo nombre es UserControl1.

  4. Cambie el nombre de UserControl1 a MyControl1.

El proyecto debe tener referencias a las siguientes DLL del sistema. Si cualquiera de estas DLL no está incluida de forma predeterminada, agréguela al proyecto.

  • System

  • System.Data

  • System.Drawing

  • System.Windows.Forms

  • System.XML

Agregar controles al formulario

Para agregar controles al formulario:

  • Abra el diseñador de MyControl1.

Coloque en el formulario seis controles System.Windows.Forms.Label y sus controles System.Windows.Forms.TextBox correspondientes, con los tamaños y la organización indicados en la ilustración anterior. En el ejemplo, los controles TextBox tienen los nombres siguientes:

  • txtName

  • txtAddress

  • txtCity

  • txtState

  • txtZip

Agregue dos controles System.Windows.Forms.Button con las etiquetas Aceptar y Cancelar. En el ejemplo, los nombres de botón son btnOK y btnCancel, respectivamente.

Implementar el código de compatibilidad

Abra la vista de código del formulario. El control devuelve los datos recolectados al host provocando el evento OnButtonClick personalizado. Los datos están contenidos en el objeto de argumento de evento. En el siguiente código se muestra la declaración del evento y el delegado. Agregue este código al archivo de código, debajo del código generado por el diseñador.

Public Delegate Sub MyControlEventHandler(ByVal sender As Object, ByVal args As MyControlEventArgs)
Public Event OnButtonClick As MyControlEventHandler
public delegate void MyControlEventHandler(object sender, MyControlEventArgs args);
public event MyControlEventHandler OnButtonClick;

La clase MyControlEventArgs contiene la información que se devolverá al host. Agregue las clase siguiente al espacio de nombres del formulario.

Public Class MyControlEventArgs
    Inherits EventArgs
    Private _Name As String
    Private _StreetAddress As String
    Private _City As String
    Private _State As String
    Private _Zip As String
    Private _IsOK As Boolean


    Public Sub New(ByVal result As Boolean, ByVal name As String, ByVal address As String, ByVal city As String, ByVal state As String, ByVal zip As String) 
        _IsOK = result
        _Name = name
        _StreetAddress = address
        _City = city
        _State = state
        _Zip = zip

    End Sub


    Public Property MyName() As String 
        Get
            Return _Name
        End Get
        Set
            _Name = value
        End Set
    End Property

    Public Property MyStreetAddress() As String 
        Get
            Return _StreetAddress
        End Get
        Set
            _StreetAddress = value
        End Set
    End Property

    Public Property MyCity() As String 
        Get
            Return _City
        End Get
        Set
            _City = value
        End Set
    End Property

    Public Property MyState() As String 
        Get
            Return _State
        End Get
        Set
            _State = value
        End Set
    End Property

    Public Property MyZip() As String 
        Get
            Return _Zip
        End Get
        Set
            _Zip = value
        End Set
    End Property

    Public Property IsOK() As Boolean 
        Get
            Return _IsOK
        End Get
        Set
            _IsOK = value
        End Set
    End Property
End Class
public class MyControlEventArgs : EventArgs
{
    private string _Name;
    private string _StreetAddress;
    private string _City;
    private string _State;
    private string _Zip;
    private bool _IsOK;

    public MyControlEventArgs(bool result,
                                   string name,
                                   string address,
                                   string city,
                                   string state,
                                   string zip)
    {
        _IsOK = result;
        _Name = name;
        _StreetAddress = address;
        _City = city;
        _State = state;
        _Zip = zip;
    }

    public string MyName
    {
        get { return _Name; }
        set { _Name = value; }
    }
    public string MyStreetAddress
    {
        get { return _StreetAddress; }
        set { _StreetAddress = value; }
    }
    public string MyCity
    {
        get { return _City; }
        set { _City = value; }
    }
    public string MyState
    {
        get { return _State; }
        set { _State = value; }
    }
    public string MyZip
    {
        get { return _Zip; }
        set { _Zip = value; }
    }
    public bool IsOK
    {
        get { return _IsOK; }
        set { _IsOK = value; }
    }
}

Cuando el usuario hace clic en el botón Aceptar o Cancelar, los controladores del evento Control.Click crean un objeto MyControlEventArgs que contiene los datos y provoca el evento OnButtonClick. La única diferencia entre los dos controladores es la propiedad IsOK del argumento de evento. Esta propiedad permite al host determinar en qué botón se hizo clic. Se establece en true para el botón Aceptar y en false para el botón Cancelar. En el siguiente ejemplo de código se muestran los controladores de los dos botones. Agregue este código a la clase, debajo de la declaración de evento y de delegado mostrada en el primer ejemplo de código de esta sección.

    Private Sub OKButton_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnOK.Click

        Dim retvals As New MyControlEventArgs(True, txtName.Text, txtAddress.Text, txtCity.Text, txtState.Text, txtZip.Text)
        RaiseEvent OnButtonClick(Me, retvals)

    End Sub


    Private Sub CancelButton_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnCancel.Click
        Dim retvals As New MyControlEventArgs(False, txtName.Text, txtAddress.Text, txtCity.Text, txtState.Text, txtZip.Text)
        RaiseEvent OnButtonClick(Me, retvals)

    End Sub
End Class
private void OKButton_Click(object sender, System.EventArgs e)
{

    MyControlEventArgs retvals = new MyControlEventArgs(true,
                                                         txtName.Text,
                                                         txtAddress.Text,
                                                         txtCity.Text,
                                                         txtState.Text,
                                                         txtZip.Text);
    OnButtonClick(this, retvals);
}

private void CancelButton_Click(object sender, System.EventArgs e)
{
    MyControlEventArgs retvals = new MyControlEventArgs(false,
                                                         txtName.Text,
                                                         txtAddress.Text,
                                                         txtCity.Text,
                                                         txtState.Text,
                                                         txtZip.Text);
    OnButtonClick(this, retvals);
}

Dar un nombre seguro al ensamblado y generar el ensamblado

Para que una aplicación de WPF pueda hacer referencia a este ensamblado, debe tener un nombre seguro. Para crear un nombre seguro, cree un archivo de clave con Sn.exe y agréguelo al archivo AssemblyInfo.cs del proyecto.

  1. Abra un símbolo del sistema de Visual Studio. Para ello, haga clic en el menú Inicio y seleccione Todos los programas/Microsoft Visual Studio 2008/Visual Studio Tools/Símbolo del sistema de Visual Studio 2008. Se iniciará una ventana de consola con variables de entorno personalizadas.

  2. En el símbolo del sistema, utilice el comando "cd" para ir a la carpeta del proyecto.

  3. Genere un archivo de clave con el nombre MyControls.snk ejecutando el comando siguiente.

    Sn.exe -k MyControls.snk
    
  4. Para incluir el archivo de clave en el proyecto, haga clic con el botón secundario en el nombre del proyecto en el Explorador de soluciones y abra el cuadro de diálogo Propiedades. Seleccione la ficha Firma y escriba el nombre de su archivo de clave.

  5. Genere el ensamblado. La compilación generará una DLL denominada MyControls.dll.

Implementar la aplicación host con Windows Presentation Foundation

La aplicación host de WPF utiliza el control WindowsFormsHost para hospedar MyControl1. La aplicación controla el evento OnButtonClick para recibir los datos del control. También tiene una colección de botones de opción que permiten cambiar algunas de las propiedades del control desde la página de WPF. En la ilustración siguiente se muestra la aplicación acabada.

Aplicación completa, que muestra el control incrustado en la página de Windows Presentation Foundation

Control incrustado en una página de WPF

Crear el proyecto

Para iniciar el proyecto:

  1. Abra Visual Studio y seleccione Nuevo proyecto.

  2. Seleccione la plantilla Aplicación de explorador WPF.

  3. Dé al proyecto el nombre WpfHost y haga clic en Aceptar para abrirlo.

También necesitará agregar una referencia a la DLL que contiene MyControl1. La manera más simple de agregar la referencia es la siguiente.

  1. En el Explorador de soluciones, haga clic con el botón secundario en el nombre del proyecto y abra el cuadro de diálogo Agregar referencia.

  2. Haga clic en la ficha Examinar y vaya a la carpeta de salida del control de Windows Forms. Para este ejemplo, esta carpeta es MyControls\bin\Debug.

  3. Seleccione la DLL que contiene el control y haga clic en Aceptar para agregarlo a la lista de referencias. Para Ejemplo Hosting a Windows Forms Composite Control in Windows Presentation Foundation, esta DLL se denomina MyControls.dll.

  4. En el Explorador de soluciones, agregue una referencia al ensamblado WindowsFormsIntegration, denominado WindowsFormsIntegration.dll.

Implementar el diseño básico

La interfaz de usuario (UI) de la aplicación host se implementa en Page1.xaml. Este archivo contiene el marcado de Lenguaje de marcado de aplicaciones extensible (XAML) que define el diseño de página y hospeda el control de formularios Windows Forms. La página está dividida en tres áreas:

  • El panel Control Properties (Propiedades del control), que contiene una colección de botones de opción que puede utilizar para modificar varias propiedades del control hospedado.

  • El panel Data from Control (Datos del control) que contiene varios elementos TextBlock que muestran los datos devueltos del control hospedado.

  • El propio control hospedado.

El código de diseño básico se muestra en el ejemplo de código siguiente. El código de marcado que se necesita para hospedar MyControl1 se omite en este ejemplo, pero se explicará más adelante. Reemplace el código de Page1.xaml por lo siguiente.

<Page xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
      x:Class="Page1"
      xmlns:mcl="clr-namespace:MyControls;assembly=MyControls"
      Loaded="Init">
  <DockPanel>
    <DockPanel.Resources>
      <Style x:Key="inlineText" TargetType="{x:Type Inline}">
        <Setter Property="FontWeight" Value="Normal"/>
      </Style>
      <Style x:Key="titleText" TargetType="{x:Type TextBlock}">
        <Setter Property="DockPanel.Dock" Value="Top"/>
        <Setter Property="FontWeight" Value="Bold"/>
        <Setter Property="Margin" Value="10,5,10,0"/>
      </Style>
    </DockPanel.Resources>

    <StackPanel Orientation="Vertical"
                DockPanel.Dock="Left"
                Background="Bisque"
                Width="250">

      <TextBlock  Margin="10,10,10,10"
                  FontWeight="Bold"
                  FontSize="12">Control Properties</TextBlock>
      <TextBlock Style="{StaticResource titleText}">Background Color</TextBlock>
      <StackPanel Margin="10,10,10,10">
        <RadioButton Name="rdbtnOriginalBackColor"
                    IsChecked="True"
                    Click="BackColorChanged">Original</RadioButton>
        <RadioButton Name="rdbtnBackGreen"
                    Click="BackColorChanged">LightGreen</RadioButton>
        <RadioButton Name="rdbtnBackSalmon"
                    Click="BackColorChanged">LightSalmon</RadioButton>
      </StackPanel>

      <TextBlock Style="{StaticResource titleText}">Foreground Color</TextBlock>
      <StackPanel Margin="10,10,10,10">
        <RadioButton Name="rdbtnOriginalForeColor"
                    IsChecked="True"
                    Click="ForeColorChanged">Original</RadioButton>
        <RadioButton Name="rdbtnForeRed"
                    Click="ForeColorChanged">Red</RadioButton>
        <RadioButton Name="rdbtnForeYellow"
                    Click="ForeColorChanged">Yellow</RadioButton>
      </StackPanel>

      <TextBlock Style="{StaticResource titleText}">Font Family</TextBlock>
      <StackPanel Margin="10,10,10,10">
        <RadioButton Name="rdbtnOriginalFamily"
                     IsChecked="True"
                    Click="FontChanged">Original</RadioButton>
        <RadioButton Name="rdbtnTimes"
                    Click="FontChanged">Times New Roman</RadioButton>
        <RadioButton Name="rdbtnWingdings"
                    Click="FontChanged">Wingdings</RadioButton>
      </StackPanel>

      <TextBlock Style="{StaticResource titleText}">Font Size</TextBlock>
      <StackPanel Margin="10,10,10,10">
        <RadioButton Name="rdbtnOriginalSize"
                    IsChecked="True"
                    Click="FontSizeChanged">Original</RadioButton>
        <RadioButton Name="rdbtnTen"
                    Click="FontSizeChanged">10</RadioButton>
        <RadioButton Name="rdbtnTwelve"
                    Click="FontSizeChanged">12</RadioButton>
      </StackPanel>

      <TextBlock Style="{StaticResource titleText}">Font Style</TextBlock>
      <StackPanel Margin="10,10,10,10">
        <RadioButton Name="rdbtnNormalStyle"
                     IsChecked="True"
                     Click="StyleChanged">Original</RadioButton>
        <RadioButton Name="rdbtnItalic"
                     Click="StyleChanged">Italic</RadioButton>
      </StackPanel>

      <TextBlock Style="{StaticResource titleText}">Font Weight</TextBlock>
      <StackPanel Margin="10,10,10,10">
        <RadioButton Name="rdbtnOriginalWeight"
                     IsChecked="True"
                   Click="WeightChanged">
          Original
        </RadioButton>
        <RadioButton Name="rdbtnBold"
                   Click="WeightChanged">Bold</RadioButton>
      </StackPanel>
    </StackPanel>

    <WindowsFormsHost Name="wfh"
                     DockPanel.Dock="Top"
                     Height="300">
      <mcl:MyControl1 Name="mc"/>
    </WindowsFormsHost>

    <StackPanel Orientation="Vertical"
                Height="Auto"
                Background="LightBlue">
      <TextBlock Margin="10,10,10,10"
            FontWeight="Bold"
            FontSize="12">Data From Control</TextBlock>
      <TextBlock Style="{StaticResource titleText}">
        Name: <Span Name="txtName" Style="{StaticResource inlineText}"/>
      </TextBlock>
      <TextBlock Style="{StaticResource titleText}">
        Street Address: <Span Name="txtAddress" Style="{StaticResource inlineText}"/>
      </TextBlock>
      <TextBlock Style="{StaticResource titleText}">
        City: <Span Name="txtCity" Style="{StaticResource inlineText}"/>
      </TextBlock>
      <TextBlock Style="{StaticResource titleText}">
        State: <Span Name="txtState" Style="{StaticResource inlineText}"/>
      </TextBlock>
      <TextBlock Style="{StaticResource titleText}">
        Zip: <Span Name="txtZip" Style="{StaticResource inlineText}"/>
      </TextBlock>
    </StackPanel>
  </DockPanel>
</Page>
<Page xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
      x:Class="WpfHost.Page1"
      xmlns:mcl="clr-namespace:MyControls;assembly=MyControls"
      Loaded="Init">
  <DockPanel>
    <DockPanel.Resources>
      <Style x:Key="inlineText" TargetType="{x:Type Inline}">
        <Setter Property="FontWeight" Value="Normal"/>
      </Style>
      <Style x:Key="titleText" TargetType="{x:Type TextBlock}">
        <Setter Property="DockPanel.Dock" Value="Top"/>
        <Setter Property="FontWeight" Value="Bold"/>
        <Setter Property="Margin" Value="10,5,10,0"/>
      </Style>
    </DockPanel.Resources>

    <StackPanel Orientation="Vertical"
                DockPanel.Dock="Left"
                Background="Bisque"
                Width="250">

      <TextBlock  Margin="10,10,10,10"
                  FontWeight="Bold"
                  FontSize="12">Control Properties</TextBlock>
      <TextBlock Style="{StaticResource titleText}">Background Color</TextBlock>
      <StackPanel Margin="10,10,10,10">
        <RadioButton Name="rdbtnOriginalBackColor"
                    IsChecked="True"
                    Click="BackColorChanged">Original</RadioButton>
        <RadioButton Name="rdbtnBackGreen"
                    Click="BackColorChanged">LightGreen</RadioButton>
        <RadioButton Name="rdbtnBackSalmon"
                    Click="BackColorChanged">LightSalmon</RadioButton>
      </StackPanel>

      <TextBlock Style="{StaticResource titleText}">Foreground Color</TextBlock>
      <StackPanel Margin="10,10,10,10">
        <RadioButton Name="rdbtnOriginalForeColor"
                    IsChecked="True"
                    Click="ForeColorChanged">Original</RadioButton>
        <RadioButton Name="rdbtnForeRed"
                    Click="ForeColorChanged">Red</RadioButton>
        <RadioButton Name="rdbtnForeYellow"
                    Click="ForeColorChanged">Yellow</RadioButton>
      </StackPanel>

      <TextBlock Style="{StaticResource titleText}">Font Family</TextBlock>
      <StackPanel Margin="10,10,10,10">
        <RadioButton Name="rdbtnOriginalFamily"
                     IsChecked="True"
                    Click="FontChanged">Original</RadioButton>
        <RadioButton Name="rdbtnTimes"
                    Click="FontChanged">Times New Roman</RadioButton>
        <RadioButton Name="rdbtnWingdings"
                    Click="FontChanged">Wingdings</RadioButton>
      </StackPanel>

      <TextBlock Style="{StaticResource titleText}">Font Size</TextBlock>
      <StackPanel Margin="10,10,10,10">
        <RadioButton Name="rdbtnOriginalSize"
                    IsChecked="True"
                    Click="FontSizeChanged">Original</RadioButton>
        <RadioButton Name="rdbtnTen"
                    Click="FontSizeChanged">10</RadioButton>
        <RadioButton Name="rdbtnTwelve"
                    Click="FontSizeChanged">12</RadioButton>
      </StackPanel>

      <TextBlock Style="{StaticResource titleText}">Font Style</TextBlock>
      <StackPanel Margin="10,10,10,10">
        <RadioButton Name="rdbtnNormalStyle"
                     IsChecked="True"
                     Click="StyleChanged">Original</RadioButton>
        <RadioButton Name="rdbtnItalic"
                     Click="StyleChanged">Italic</RadioButton>
      </StackPanel>

      <TextBlock Style="{StaticResource titleText}">Font Weight</TextBlock>
      <StackPanel Margin="10,10,10,10">
        <RadioButton Name="rdbtnOriginalWeight"
                     IsChecked="True"
                   Click="WeightChanged">
          Original
        </RadioButton>
        <RadioButton Name="rdbtnBold"
                   Click="WeightChanged">Bold</RadioButton>
      </StackPanel>
    </StackPanel>

    <WindowsFormsHost Name="wfh"
                     DockPanel.Dock="Top"
                     Height="300">
      <mcl:MyControl1 Name="mc"/>
    </WindowsFormsHost>

    <StackPanel Orientation="Vertical"
                Height="Auto"
                Background="LightBlue">
      <TextBlock Margin="10,10,10,10"
            FontWeight="Bold"
            FontSize="12">Data From Control</TextBlock>
      <TextBlock Style="{StaticResource titleText}">
        Name: <Span Name="txtName" Style="{StaticResource inlineText}"/>
      </TextBlock>
      <TextBlock Style="{StaticResource titleText}">
        Street Address: <Span Name="txtAddress" Style="{StaticResource inlineText}"/>
      </TextBlock>
      <TextBlock Style="{StaticResource titleText}">
        City: <Span Name="txtCity" Style="{StaticResource inlineText}"/>
      </TextBlock>
      <TextBlock Style="{StaticResource titleText}">
        State: <Span Name="txtState" Style="{StaticResource inlineText}"/>
      </TextBlock>
      <TextBlock Style="{StaticResource titleText}">
        Zip: <Span Name="txtZip" Style="{StaticResource inlineText}"/>
      </TextBlock>
    </StackPanel>
  </DockPanel>
</Page>

El primer elemento StackPanel contiene varios conjuntos de controles RadioButton que permiten modificar diversas propiedades predeterminadas del control hospedado. A continuación, hay un elemento WindowsFormsHost en el que se hospeda MyControl1. El último elemento StackPanel contiene varios elementos TextBlock que muestran los datos devueltos por el control hospedado. El orden de los elementos y los valores de atributo de Dock y Height incrustan el control hospedado en la página sin dejar espacios en blanco ni provocar distorsión.

Hospedar el control

La versión editada siguiente del ejemplo de código anterior se centra en los elementos que se necesitan para hospedar MyControl1.

<Page xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
      x:Class="Page1"
      xmlns:mcl="clr-namespace:MyControls;assembly=MyControls"
      Loaded="Init">


...


<WindowsFormsHost Name="wfh"
                 DockPanel.Dock="Top"
                 Height="300">
  <mcl:MyControl1 Name="mc"/>
</WindowsFormsHost>
<Page xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
      x:Class="WpfHost.Page1"
      xmlns:mcl="clr-namespace:MyControls;assembly=MyControls"
      Loaded="Init">


...


<WindowsFormsHost Name="wfh"
                 DockPanel.Dock="Top"
                 Height="300">
  <mcl:MyControl1 Name="mc"/>
</WindowsFormsHost>

Los atributos de asignación del espacio de nombres xmlns crean una referencia al espacio de nombres MyControls que contiene el control hospedado. Esta asignación permite representar MyControl1 en XAML como <mcl:MyControl1>.

Dos elementos del ejemplo de código administran el hospedaje:

  • WindowsFormsHost representa el elemento WindowsFormsHost que permite hospedar un control de formularios Windows Forms en una página de WPF.

  • mcl:MyControl1, que representa a MyControl1, se agrega a la colección de elementos secundarios del elemento WindowsFormsHost. Como resultado, este control de formularios Windows Forms se representa como parte de la página de WPF y es posible comunicarse con el control desde la página.

Implementar el archivo de código subyacente

El archivo de código subyacente, Page1.xaml.cs, contiene el código de procedimiento que implementa la funcionalidad de la interfaz de usuario descrita en la sección anterior. Las principales tareas son:

  • Asociar un controlador al evento OnButtonClick de MyControl1.

  • Modificar diversas propiedades de MyControl1, basándose en cómo se establezca la colección de botones de opción.

  • Mostrar los datos recolectados por el control.

Inicializar la aplicación

El código de inicialización está contenido en un controlador para el evento Loaded de la página y asocia un controlador al evento OnButtonClick del control. Copie el código siguiente en la clase Page1 de Page1.xaml.cs.

Class Page1
    Inherits Page

    Private app As Application
    Private myWindow As NavigationWindow
    Private initFontWeight As FontWeight
    Private initFontSize As [Double]
    Private initFontStyle As FontStyle
    Private initBackBrush As SolidColorBrush
    Private initForeBrush As SolidColorBrush
    Private initFontFamily As FontFamily
    Private UIIsReady As Boolean = False


    Private Sub Init(ByVal sender As Object, ByVal e As RoutedEventArgs)
        app = System.Windows.Application.Current
        myWindow = CType(app.MainWindow, NavigationWindow)
        myWindow.SizeToContent = SizeToContent.WidthAndHeight
        wfh.TabIndex = 10
        initFontSize = wfh.FontSize
        initFontWeight = wfh.FontWeight
        initFontFamily = wfh.FontFamily
        initFontStyle = wfh.FontStyle
        initBackBrush = CType(wfh.Background, SolidColorBrush)
        initForeBrush = CType(wfh.Foreground, SolidColorBrush)

        Dim mc As MyControl1 = wfh.Child

        AddHandler mc.OnButtonClick, AddressOf Pane1_OnButtonClick 
        UIIsReady = True

    End Sub
public partial class Page1 : Page
{
    private Application app;
    private NavigationWindow myWindow;
    FontWeight initFontWeight;
    Double initFontSize;
    FontStyle initFontStyle;
    SolidColorBrush initBackBrush;
    SolidColorBrush initForeBrush;
    FontFamily initFontFamily;
    bool UIIsReady = false;

    private void Init(object sender, EventArgs e)
    {
        app = System.Windows.Application.Current;
        myWindow = (NavigationWindow)app.MainWindow;
        myWindow.SizeToContent = SizeToContent.WidthAndHeight;
        wfh.TabIndex = 10;
        initFontSize = wfh.FontSize;
        initFontWeight = wfh.FontWeight;
        initFontFamily = wfh.FontFamily;
        initFontStyle = wfh.FontStyle;
        initBackBrush = (SolidColorBrush)wfh.Background;
        initForeBrush = (SolidColorBrush)wfh.Foreground;
        (wfh.Child as MyControl1).OnButtonClick += new MyControl1.MyControlEventHandler(Pane1_OnButtonClick);
        UIIsReady = true;
    }

Dado que en el código XAML descrito anteriormente se ha agregado MyControl1 a la colección de elementos secundarios del elemento WindowsFormsHost, puede convertir la propiedad Child del elemento WindowsFormsHost para obtener la referencia a MyControl1. A continuación, puede utilizar esa referencia para asociar un controlador de eventos a OnButtonClick.

Además de proporcionar una referencia al propio control, WindowsFormsHost expone varias propiedades del control, que puede manipular desde la página. En el código de inicialización se asignan esos valores a las variables globales privadas para su uso posterior en la aplicación.

Controlar el evento OnButtonClick

MyControl1 provoca el evento OnButtonClick cuando el usuario hace clic en cualquiera de los botones del control. Agregue el código siguiente a la clase Page1.

    'Handle button clicks on the Windows Form control
    Private Sub Pane1_OnButtonClick(ByVal sender As Object, ByVal args As MyControlEventArgs) 
        txtName.Inlines.Clear()
        txtAddress.Inlines.Clear()
        txtCity.Inlines.Clear()
        txtState.Inlines.Clear()
        txtZip.Inlines.Clear()

        If args.IsOK Then
            txtName.Inlines.Add(" " + args.MyName)
            txtAddress.Inlines.Add(" " + args.MyStreetAddress)
            txtCity.Inlines.Add(" " + args.MyCity)
            txtState.Inlines.Add(" " + args.MyState)
            txtZip.Inlines.Add(" " + args.MyZip)
        End If

    End Sub
End Class
//Handle button clicks on the Windows Form control
private void Pane1_OnButtonClick(object sender, MyControlEventArgs args)
{
    txtName.Inlines.Clear();
    txtAddress.Inlines.Clear();
    txtCity.Inlines.Clear();
    txtState.Inlines.Clear();
    txtZip.Inlines.Clear();

    if (args.IsOK)
    {
        txtName.Inlines.Add( " " + args.MyName );
        txtAddress.Inlines.Add( " " + args.MyStreetAddress );
        txtCity.Inlines.Add( " " + args.MyCity );
        txtState.Inlines.Add( " " + args.MyState );
        txtZip.Inlines.Add( " " + args.MyZip );
    }
}

Los datos de los cuadros de texto se empaquetan en el objeto MyControlEventArgs. Si el usuario hace clic en el botón Aceptar botón, el controlador de eventos extrae los datos y los muestra en el panel situado debajo de MyControl1.

Modificar las propiedades del control

El elemento WindowsFormsHost expone algunas de las propiedades predeterminadas de control hospedado. Como resultado, puede cambiar el aspecto del control para adaptarlo mejor al estilo de la página. Los conjuntos de botones de opción del panel izquierdo permiten al usuario modificar varias propiedades de color y fuente. Cada conjunto de botones tiene un controlador para el evento Click, que detecta qué botón selecciona el usuario y cambia la propiedad correspondiente del control. Copie el código siguiente a la clase Page1. Ahora puede generar y ejecutar la aplicación.

Private Sub BackColorChanged(ByVal sender As Object, ByVal e As RoutedEventArgs)

    If sender.Equals(rdbtnBackGreen) Then
        wfh.Background = New SolidColorBrush(Colors.LightGreen)
    ElseIf sender.Equals(rdbtnBackSalmon) Then
        wfh.Background = New SolidColorBrush(Colors.LightSalmon)
    ElseIf UIIsReady = True Then
        wfh.Background = initBackBrush
    End If

End Sub

Private Sub ForeColorChanged(ByVal sender As Object, ByVal e As RoutedEventArgs) 
    If sender.Equals(rdbtnForeRed) Then
        wfh.Foreground = New SolidColorBrush(Colors.Red)
    ElseIf sender.Equals(rdbtnForeYellow) Then
        wfh.Foreground = New SolidColorBrush(Colors.Yellow)
    ElseIf UIIsReady = True Then
        wfh.Foreground = initForeBrush
    End If

End Sub

Private Sub FontChanged(ByVal sender As Object, ByVal e As RoutedEventArgs) 
    If sender.Equals(rdbtnTimes) Then
        wfh.FontFamily = New FontFamily("Times New Roman")
    ElseIf sender.Equals(rdbtnWingdings) Then
        wfh.FontFamily = New FontFamily("Wingdings")
    ElseIf UIIsReady = True Then
        wfh.FontFamily = initFontFamily
    End If

End Sub

Private Sub FontSizeChanged(ByVal sender As Object, ByVal e As RoutedEventArgs) 
    If sender.Equals(rdbtnTen) Then
        wfh.FontSize = 10
    ElseIf sender.Equals(rdbtnTwelve) Then
        wfh.FontSize = 12
    ElseIf UIIsReady = True Then
        wfh.FontSize = initFontSize
    End If

End Sub

Private Sub StyleChanged(ByVal sender As Object, ByVal e As RoutedEventArgs) 
    If sender.Equals(rdbtnItalic) Then
        wfh.FontStyle = FontStyles.Italic
    ElseIf UIIsReady = True Then
        wfh.FontStyle = initFontStyle
    End If

End Sub

Private Sub WeightChanged(ByVal sender As Object, ByVal e As RoutedEventArgs) 
    If sender.Equals(rdbtnBold) Then
        wfh.FontWeight = FontWeights.Bold
    ElseIf UIIsReady = True Then
        wfh.FontWeight = initFontWeight
    End If

End Sub
private void BackColorChanged(object sender, RoutedEventArgs e)
{
    if (sender == rdbtnBackGreen)
        wfh.Background = new SolidColorBrush(Colors.LightGreen);
    else if (sender == rdbtnBackSalmon)
        wfh.Background = new SolidColorBrush(Colors.LightSalmon);
    else if (UIIsReady == true)
        wfh.Background = initBackBrush;
}

private void ForeColorChanged(object sender, RoutedEventArgs e)
{
    if (sender == rdbtnForeRed)
        wfh.Foreground = new SolidColorBrush(Colors.Red);
    else if (sender == rdbtnForeYellow)
        wfh.Foreground = new SolidColorBrush(Colors.Yellow);
    else if (UIIsReady == true)
        wfh.Foreground = initForeBrush;
}

private void FontChanged(object sender, RoutedEventArgs e)
{
    if (sender == rdbtnTimes)
        wfh.FontFamily = new FontFamily("Times New Roman");
    else if (sender == rdbtnWingdings)
        wfh.FontFamily = new FontFamily("Wingdings");
    else if (UIIsReady == true)
        wfh.FontFamily = initFontFamily;
}
private void FontSizeChanged(object sender, RoutedEventArgs e)
{
    if (sender == rdbtnTen)
        wfh.FontSize = 10;
    else if (sender == rdbtnTwelve)
        wfh.FontSize = 12;
    else if (UIIsReady == true)
        wfh.FontSize = initFontSize;
}
private void StyleChanged(object sender, RoutedEventArgs e)
{
    if (sender == rdbtnItalic)
        wfh.FontStyle = FontStyles.Italic;
    else if (UIIsReady == true)
        wfh.FontStyle = initFontStyle;
}
private void WeightChanged(object sender, RoutedEventArgs e)
{
    if (sender == rdbtnBold)
        wfh.FontWeight = FontWeights.Bold;
    else if (UIIsReady == true)
        wfh.FontWeight = initFontWeight;
}

Vea también

Tareas

Tutorial: Hospedar un control de formularios Windows Forms en Windows Presentation Foundation

Conceptos

Tutorial: Hospedar un control de Windows Presentation Foundation en formularios Windows Forms

Referencia

ElementHost

WindowsFormsHost

Otros recursos

WPF Designer