Tutorial: Hospedar un control compuesto de WPF en formularios Windows FormsWalkthrough: Hosting a WPF Composite Control in Windows Forms

Windows Presentation Foundation (WPF)Windows Presentation Foundation (WPF) proporciona un entorno rico para crear aplicaciones.provides a rich environment for creating applications. Sin embargo, si tiene una inversión sustancial en Windows FormsWindows Forms código, puede ser más eficaz ampliar su aplicación de Windows FormsWindows Forms existente con WPFWPF en lugar de volver a escribirla desde el principio.However, when you have a substantial investment in Windows FormsWindows Forms code, it can be more effective to extend your existing Windows FormsWindows Forms application with WPFWPF rather than to rewrite it from scratch. Un escenario común es cuando desea incrustar uno o más controles implementados con WPFWPF dentro de la aplicación de Windows Forms.A common scenario is when you want to embed one or more controls implemented with WPFWPF within your Windows Forms application. Para obtener más información sobre cómo personalizar controles de WPF, vea Personalizaciónde controles.For more information about customizing WPF controls, see Control Customization.

Este tutorial le guía a través de una aplicación que hospeda un WPFWPF control compuesto para realizar la entrada de datos en una aplicación Windows Forms.This walkthrough steps you through an application that hosts a WPFWPF composite control to perform data-entry in a Windows Forms application. El control compuesto se empaqueta en un archivo DLL.The composite control is packaged in a DLL. Este procedimiento general se puede extender a aplicaciones y controles más complejos.This general procedure can be extended to more complex applications and controls. Este tutorial está diseñado para ser casi idéntico en aspecto y funcionalidad al Tutorial: hospedar un Windows Forms control compuesto en WPF.This walkthrough is designed to be nearly identical in appearance and functionality to Walkthrough: Hosting a Windows Forms Composite Control in WPF. La principal diferencia es que se invierte el escenario de hospedaje.The primary difference is that the hosting scenario is reversed.

Este tutorial está dividido en dos secciones.The walkthrough is divided into two sections. En la primera sección se describe brevemente la implementación de WPFWPF control compuesto.The first section briefly describes the implementation of the WPFWPF composite control. En la segunda sección se explica en detalle cómo hospedar el control compuesto en una aplicación Windows Forms, recibir eventos del control y tener acceso a algunas de las propiedades del control.The second section discusses in detail how to host the composite control in a Windows Forms application, receive events from the control, and access some of the control’s properties.

Las tareas ilustradas en este tutorial incluyen:Tasks illustrated in this walkthrough include:

  • Implementar el control compuesto de WPF.Implementing the WPF composite control.

  • Implementar la aplicación host de Windows Forms.Implementing the Windows Forms host application.

Para obtener una lista de código completa de las tareas ilustradas en este tutorial, vea hospedar un control compuesto de WPF en Windows Forms ejemplo.For a complete code listing of the tasks illustrated in this walkthrough, see Hosting a WPF Composite Control in Windows Forms Sample.

Requisitos previosPrerequisites

Necesita Visual Studio para completar este tutorial.You need Visual Studio to complete this walkthrough.

Implementar el control compuesto de WPFImplementing the WPF Composite Control

El WPFWPF control compuesto utilizado en este ejemplo es un formulario de entrada de datos simple que toma el nombre y la dirección del usuario.The WPFWPF composite control used in this example is a simple data-entry form that takes the user's name and address. Cuando el usuario hace clic en uno de los dos botones para indicar que la tarea ha finalizado, el control genera un evento personalizado para devolver esa información al host.When the user clicks one of two buttons to indicate that the task is finished, the control raises a custom event to return that information to the host. En la ilustración siguiente se muestra la representación del control.The following illustration shows the rendered control.

En la siguiente imagen se muestra un control compuesto de WPF:The following image shows a WPF composite control:

Captura de pantalla que muestra un control WPF sencillo.

Crear el proyectoCreating the Project

Para iniciar el proyecto:To start the project:

  1. Inicie Visual Studio y abra el cuadro de diálogo nuevo proyecto .Launch Visual Studio, and open the New Project dialog box.

  2. En la C# categoría visual y Windows, seleccione la plantilla biblioteca de controles de usuario de WPF .In Visual C# and the Windows category, select the WPF User Control Library template.

  3. Asigne al nuevo proyecto el nombre de MyControls.Name the new project MyControls.

  4. Para la ubicación, especifique una carpeta de nivel superior con un nombre adecuado, como WindowsFormsHostingWpfControl.For the location, specify a conveniently named top-level folder, such as WindowsFormsHostingWpfControl. Más tarde, colocará la aplicación host en esta carpeta.Later, you will put the host application in this folder.

  5. Haga clic en Aceptar para crear el proyecto.Click OK to create the project. El proyecto predeterminado contiene un solo control denominado UserControl1.The default project contains a single control named UserControl1.

  6. En Explorador de soluciones, cambie el nombre de UserControl1 a MyControl1.In Solution Explorer, rename UserControl1 to MyControl1.

El proyecto debe tener referencias a los siguientes archivos DLL del sistema.Your project should have references to the following system DLLs. Si alguno de estos archivos DLL no está incluido de forma predeterminada, agréguelos al proyecto.If any of these DLLs are not included by default, add them to your project.

  • PresentationCorePresentationCore

  • PresentationFrameworkPresentationFramework

  • SistemaSystem

  • WindowsBaseWindowsBase

Crear la interfaz de usuarioCreating the User Interface

El interfaz de usuario (UI)user interface (UI) para el control compuesto se implementa con Lenguaje XAML (Extensible Application Markup Language)Extensible Application Markup Language (XAML).The interfaz de usuario (UI)user interface (UI) for the composite control is implemented with Lenguaje XAML (Extensible Application Markup Language)Extensible Application Markup Language (XAML). El IUUI de control compuesto consta de cinco elementos TextBox.The composite control IUUI consists of five TextBox elements. Cada elemento TextBox tiene un elemento TextBlock asociado que actúa como etiqueta.Each TextBox element has an associated TextBlock element that serves as a label. Hay dos elementos Button en la parte inferior, Aceptar y Cancelar.There are two Button elements at the bottom, OK and Cancel. Cuando el usuario hace clic en cualquiera de los botones, el control genera un evento personalizado para devolver la información al host.When the user clicks either button, the control raises a custom event to return the information to the host.

Diseño básicoBasic Layout

Los distintos elementos IUUI se encuentran en un elemento Grid.The various IUUI elements are contained in a Grid element. Puede usar Grid para organizar el contenido del control compuesto de la misma manera que usaría un elemento Table en HTML.You can use Grid to arrange the contents of the composite control in much the same way you would use a Table element in HTML. WPFWPF también tiene un elemento Table, pero Grid es más ligero y adecuado para las tareas de diseño simples.also has a Table element, but Grid is more lightweight and better suited for simple layout tasks.

En el siguiente código XAML se muestra el diseño básico.The following XAML shows the basic layout. Este código XAML define la estructura global del control especificando el número de columnas y filas en el elemento Grid.This XAML defines the overall structure of the control by specifying the number of columns and rows in the Grid element.

En MyControl1.xaml, reemplace el código XAML existente por el siguiente código XAML.In MyControl1.xaml, replace the existing XAML with the following XAML.

<Grid xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      x:Class="MyControls.MyControl1"
      Background="#DCDCDC"
      Width="375"
      Height="250"
      Name="rootElement"
      Loaded="Init">

  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="Auto" />
    <ColumnDefinition Width="Auto" />
    <ColumnDefinition Width="Auto"/>
    <ColumnDefinition Width="Auto"/>
  </Grid.ColumnDefinitions>

  <Grid.RowDefinitions>
    <RowDefinition Height="Auto" />
    <RowDefinition Height="Auto" />
    <RowDefinition Height="Auto" />
    <RowDefinition Height="Auto" />
    <RowDefinition Height="Auto" />
    <RowDefinition Height="Auto" />
  </Grid.RowDefinitions>
</Grid>

Agregar elementos TextBlock y TextBox a la cuadrículaAdding TextBlock and TextBox Elements to the Grid

Para colocar un IUUI elemento en la cuadrícula, establezca los atributos RowProperty y ColumnProperty del elemento en el número de fila y columna adecuado.You place a IUUI element in the grid by setting the element's RowProperty and ColumnProperty attributes to the appropriate row and column number. Recuerde que la numeración de filas y columnas está basada en ceros.Remember that row and column numbering are zero-based. Puede tener un elemento que abarque varias columnas estableciendo su ColumnSpanProperty atributo.You can have an element span multiple columns by setting its ColumnSpanProperty attribute. Para obtener más información sobre los elementos de Grid, vea crear un elemento Grid.For more information about Grid elements, see Create a Grid Element.

En el siguiente código XAML se muestran los elementos TextBox y TextBlock del control compuesto con sus atributos RowProperty y ColumnProperty, que se establecen para colocar los elementos correctamente en la cuadrícula.The following XAML shows the composite control’s TextBox and TextBlock elements with their RowProperty and ColumnProperty attributes, which are set to place the elements properly in the grid.

En MyControl1. XAML, agregue el siguiente código XAML dentro del elemento Grid.In MyControl1.xaml, add the following XAML within the Grid element.

  <TextBlock Grid.Column="0"
        Grid.Row="0" 
        Grid.ColumnSpan="4"
        Margin="10,5,10,0"
        HorizontalAlignment="Center"
        Style="{StaticResource titleText}">Simple WPF Control</TextBlock>

  <TextBlock Grid.Column="0"
        Grid.Row="1"
        Style="{StaticResource inlineText}"
        Name="nameLabel">Name</TextBlock>
  <TextBox Grid.Column="1"
        Grid.Row="1"
        Grid.ColumnSpan="3"
        Name="txtName"/>

  <TextBlock Grid.Column="0"
        Grid.Row="2"
        Style="{StaticResource inlineText}"
        Name="addressLabel">Street Address</TextBlock>
  <TextBox Grid.Column="1"
        Grid.Row="2"
        Grid.ColumnSpan="3"
        Name="txtAddress"/>

  <TextBlock Grid.Column="0"
        Grid.Row="3"
        Style="{StaticResource inlineText}"
        Name="cityLabel">City</TextBlock>
  <TextBox Grid.Column="1"
        Grid.Row="3"
        Width="100"
        Name="txtCity"/>

  <TextBlock Grid.Column="2"
        Grid.Row="3"
        Style="{StaticResource inlineText}"
        Name="stateLabel">State</TextBlock>
  <TextBox Grid.Column="3"
        Grid.Row="3"
        Width="50"
        Name="txtState"/>

  <TextBlock Grid.Column="0"
        Grid.Row="4"
        Style="{StaticResource inlineText}"
        Name="zipLabel">Zip</TextBlock>
  <TextBox Grid.Column="1"
        Grid.Row="4"
        Width="100"
        Name="txtZip"/>

Aplicar estilos a los elementos de interfaz de usuarioStyling the UI Elements

Muchos de los elementos del formulario de entrada de datos tienen un aspecto similar, lo que significa que tienen valores idénticos para varias de sus propiedades.Many of the elements on the data-entry form have a similar appearance, which means that they have identical settings for several of their properties. En lugar de establecer los atributos de cada elemento por separado, el código XAML anterior utiliza Style elementos para definir los valores de propiedad estándar para las clases de elementos.Rather than setting each element's attributes separately, the previous XAML uses Style elements to define standard property settings for classes of elements. Este enfoque reduce la complejidad del control y le permite cambiar la apariencia de varios elementos mediante un solo atributo de estilo.This approach reduces the complexity of the control and enables you to change the appearance of multiple elements through a single style attribute.

Los elementos Style se incluyen en la propiedad Resources del elemento Grid, de modo que todos los elementos del control puedan utilizarlos.The Style elements are contained in the Grid element's Resources property, so they can be used by all elements in the control. Si un estilo se denomina, se aplica a un elemento agregando un conjunto de elementos Style al nombre del estilo.If a style is named, you apply it to an element by adding a Style element set to the style's name. Los estilos que no tienen nombre se convierten en el estilo predeterminado del elemento.Styles that are not named become the default style for the element. Para obtener más información sobre los estilos de WPFWPF, vea aplicar estilos y plantillas.For more information about WPFWPF styles, see Styling and Templating.

En el siguiente código XAML se muestran los elementos Style del control compuesto.The following XAML shows the Style elements for the composite control. Para ver cómo se aplican los estilos a los elementos, vea el código XAML anterior.To see how the styles are applied to elements, see the previous XAML. Por ejemplo, el último elemento TextBlock tiene el estilo inlineText y el último elemento TextBox usa el estilo predeterminado.For example, the last TextBlock element has the inlineText style, and the last TextBox element uses the default style.

En MyControl1. XAML, agregue el código XAML siguiente justo después del elemento de inicio Grid.In MyControl1.xaml, add the following XAML just after the Grid start element.

<Grid.Resources>
  <Style x:Key="inlineText" TargetType="{x:Type TextBlock}">
    <Setter Property="Margin" Value="10,5,10,0"/>
    <Setter Property="FontWeight" Value="Normal"/>
    <Setter Property="FontSize" Value="12"/>
  </Style>
  <Style x:Key="titleText" TargetType="{x:Type TextBlock}">
    <Setter Property="DockPanel.Dock" Value="Top"/>
    <Setter Property="FontWeight" Value="Bold"/>
    <Setter Property="FontSize" Value="14"/>
    <Setter Property="Margin" Value="10,5,10,0"/>
  </Style>
  <Style TargetType="{x:Type Button}">
    <Setter Property="Margin" Value="10,5,10,0"/>
    <Setter Property="Width" Value="60"/>
  </Style>
  <Style TargetType="{x:Type TextBox}">
    <Setter Property="Margin" Value="10,5,10,0"/>
  </Style>
</Grid.Resources>

Agregar los botones Aceptar y CancelarAdding the OK and Cancel Buttons

Los elementos finales del control compuesto son los elementos OK y CancelButton, que ocupan las dos primeras columnas de la última fila de la Grid.The final elements on the composite control are the OK and CancelButton elements, which occupy the first two columns of the last row of the Grid. Estos elementos usan un controlador de eventos común, ButtonClickedy el estilo de Button predeterminado definido en el código XAML anterior.These elements use a common event handler, ButtonClicked, and the default Button style defined in the previous XAML.

En MyControl1. XAML, agregue el siguiente código XAML después del último elemento TextBox.In MyControl1.xaml, add the following XAML after the last TextBox element. La parte XAMLXAML del control compuesto ahora está completa.The XAMLXAML part of the composite control is now complete.

<Button Grid.Row="5"
        Grid.Column="0"
        Name="btnOK"
        Click="ButtonClicked">OK</Button>
<Button Grid.Row="5"
        Grid.Column="1"
        Name="btnCancel"
        Click="ButtonClicked">Cancel</Button>

Implementar el archivo de código subyacenteImplementing the Code-Behind File

El archivo de código subyacente, MyControl1.xaml.cs, implementa tres tareas esenciales:The code-behind file, MyControl1.xaml.cs, implements three essential tasks:

  1. Controla el evento que se produce cuando el usuario hace clic en uno de los botones.Handles the event that occurs when the user clicks one of the buttons.

  2. Recupera los datos de la TextBox elementos y los empaqueta en un objeto de argumento de evento personalizado.Retrieves the data from the TextBox elements, and packages it in a custom event argument object.

  3. Genera el evento de OnButtonClick personalizado, que notifica al host que el usuario ha terminado y devuelve los datos al host.Raises the custom OnButtonClick event, which notifies the host that the user is finished and passes the data back to the host.

El control también expone una serie de propiedades de color y fuente con las que puede cambiar la apariencia.The control also exposes a number of color and font properties that enable you to change the appearance. A diferencia de la clase WindowsFormsHost, que se usa para hospedar un control Windows Forms, la clase ElementHost solo expone la propiedad Background del control.Unlike the WindowsFormsHost class, which is used to host a Windows Forms control, the ElementHost class exposes the control’s Background property only. Para mantener la similitud entre este ejemplo de código y el ejemplo que se describe en Tutorial: hospedar un control compuesto de Windows Forms en WPF, el control expone las propiedades restantes directamente.To maintain the similarity between this code example and the example discussed in Walkthrough: Hosting a Windows Forms Composite Control in WPF, the control exposes the remaining properties directly.

Estructura básica del archivo de código subyacenteThe Basic Structure of the Code-Behind File

El archivo de código subyacente está compuesto de un solo espacio de nombres, MyControls, que contendrá dos clases, MyControl1 y MyControlEventArgs.The code-behind file consists of a single namespace, MyControls, which will contain two classes, MyControl1 and MyControlEventArgs.

namespace MyControls  
{  
  public partial class MyControl1 : Grid  
  {  
    //...  
  }  
  public class MyControlEventArgs : EventArgs  
  {  
    //...  
  }  
}  

La primera clase, MyControl1, es una clase parcial que contiene el código que implementa la funcionalidad del IUUI definido en MyControl1. Xaml.The first class, MyControl1, is a partial class containing the code that implements the functionality of the IUUI defined in MyControl1.xaml. Cuando se analiza MyControl1. XAML, el XAMLXAML se convierte en la misma clase parcial y las dos clases parciales se combinan para formar el control compilado.When MyControl1.xaml is parsed, the XAMLXAML is converted to the same partial class, and the two partial classes are merged to form the compiled control. Por este motivo, el nombre de clase del archivo de código subyacente debe coincidir con el nombre de clase asignado a MyControl1.xaml y debe heredar del elemento raíz del control.For this reason, the class name in the code-behind file must match the class name assigned to MyControl1.xaml, and it must inherit from the root element of the control. La segunda clase, MyControlEventArgs, es una clase de argumentos de evento que se utiliza para devolver los datos al host.The second class, MyControlEventArgs, is an event arguments class that is used to send the data back to the host.

Abra MyControl1.xaml.cs.Open MyControl1.xaml.cs. Cambie la declaración de clase existente para que tenga el siguiente nombre y herede de Grid.Change the existing class declaration so that it has the following name and inherits from Grid.

public partial class MyControl1 : Grid

Inicializar el controlInitializing the Control

En el código siguiente se implementan varias tareas básicas:The following code implements several basic tasks:

  • Declara un evento privado, OnButtonClicky su delegado asociado, MyControlEventHandler.Declares a private event, OnButtonClick, and its associated delegate, MyControlEventHandler.

  • Crea distintas variables globales privadas que almacenan los datos del usuario.Creates several private global variables that store the user's data. Estos datos se exponen a través de las propiedades correspondientes.This data is exposed through corresponding properties.

  • Implementa un controlador, Init, para el evento de Loaded del control.Implements a handler, Init, for the control’s Loaded event. Este controlador inicializa las variables globales al asignarles los valores definidos en MyControl1.xaml.This handler initializes the global variables by assigning them the values defined in MyControl1.xaml. Para ello, utiliza el Name asignado a un elemento de TextBlock típico, nameLabel, para tener acceso a la configuración de la propiedad de ese elemento.To do this, it uses the Name assigned to a typical TextBlock element, nameLabel, to access that element's property settings.

Elimine el constructor existente y agregue el código siguiente a la clase MyControl1.Delete the existing constructor and add the following code to your MyControl1 class.

public delegate void MyControlEventHandler(object sender, MyControlEventArgs args);
public event MyControlEventHandler OnButtonClick;
private FontWeight _fontWeight;
private double _fontSize;
private FontFamily _fontFamily;
private FontStyle _fontStyle;
private SolidColorBrush _foreground;
private SolidColorBrush _background;

private void Init(object sender, EventArgs e)
{
    //They all have the same style, so use nameLabel to set initial values.
    _fontWeight = nameLabel.FontWeight;
    _fontSize = nameLabel.FontSize;
    _fontFamily = nameLabel.FontFamily;
    _fontStyle = nameLabel.FontStyle;
    _foreground = (SolidColorBrush)nameLabel.Foreground;
    _background = (SolidColorBrush)rootElement.Background;
}

Administrar los eventos de clic de los botonesHandling the Buttons' Click Events

El usuario indica que la tarea de entrada de datos ha finalizado haciendo clic en el botón Aceptar o en el botón Cancelar .The user indicates that the data-entry task is finished by clicking either the OK button or the Cancel button. Ambos botones usan el mismo Click controlador de eventos, ButtonClicked.Both buttons use the same Click event handler, ButtonClicked. Ambos botones tienen un nombre, btnOK o btnCancel, que permite al controlador determinar en qué botón se hizo clic examinando el valor del argumento sender.Both buttons have a name, btnOK or btnCancel, that enables the handler to determine which button was clicked by examining the value of the sender argument. El controlador hace lo siguiente:The handler does the following:

  • Crea un objeto MyControlEventArgs que contiene los datos de los elementos TextBox.Creates a MyControlEventArgs object that contains the data from the TextBox elements.

  • Si el usuario hizo clic en el botón Cancelar , establece la propiedad IsOK del objeto MyControlEventArgs en false.If the user clicked the Cancel button, sets the MyControlEventArgs object's IsOK property to false.

  • Genera el evento OnButtonClick para indicar al host que el usuario ha terminado y devuelve los datos recopilados.Raises the OnButtonClick event to indicate to the host that the user is finished, and passes back the collected data.

Agregue el código siguiente a la clase MyControl1, después del método Init.Add the following code to your MyControl1 class, after the Init method.

private void ButtonClicked(object sender, RoutedEventArgs e)
{
    MyControlEventArgs retvals = new MyControlEventArgs(true,
                                                        txtName.Text,
                                                        txtAddress.Text,
                                                        txtCity.Text,
                                                        txtState.Text,
                                                        txtZip.Text);
    if (sender == btnCancel)
    {
        retvals.IsOK = false;
    }
    if (OnButtonClick != null)
        OnButtonClick(this, retvals);
}

Crear propiedadesCreating Properties

El resto de la clase simplemente expone propiedades que corresponden a las variables globales que se han descrito anteriormente.The remainder of the class simply exposes properties that correspond to the global variables discussed previously. Cuando se cambia una propiedad, el descriptor de acceso set modifica el aspecto del control cambiando las propiedades de elemento correspondientes y actualizando las variables globales subyacentes.When a property changes, the set accessor modifies the appearance of the control by changing the corresponding element properties and updating the underlying global variables.

Agregue el código siguiente a la clase MyControl1.Add the following code to your MyControl1 class.

public FontWeight MyControl_FontWeight
{
    get { return _fontWeight; }
    set
    {
        _fontWeight = value;
        nameLabel.FontWeight = value;
        addressLabel.FontWeight = value;
        cityLabel.FontWeight = value;
        stateLabel.FontWeight = value;
        zipLabel.FontWeight = value;
    }
}
public double MyControl_FontSize
{
    get { return _fontSize; }
    set
    {
        _fontSize = value;
        nameLabel.FontSize = value;
        addressLabel.FontSize = value;
        cityLabel.FontSize = value;
        stateLabel.FontSize = value;
        zipLabel.FontSize = value;
    }
}
public FontStyle MyControl_FontStyle
{
    get { return _fontStyle; }
    set
    {
        _fontStyle = value;
        nameLabel.FontStyle = value;
        addressLabel.FontStyle = value;
        cityLabel.FontStyle = value;
        stateLabel.FontStyle = value;
        zipLabel.FontStyle = value;
    }
}
public FontFamily MyControl_FontFamily
{
    get { return _fontFamily; }
    set
    {
        _fontFamily = value;
        nameLabel.FontFamily = value;
        addressLabel.FontFamily = value;
        cityLabel.FontFamily = value;
        stateLabel.FontFamily = value;
        zipLabel.FontFamily = value;
    }
}

public SolidColorBrush MyControl_Background
{
    get { return _background; }
    set
    {
        _background = value;
        rootElement.Background = value;
    }
}
public SolidColorBrush MyControl_Foreground
{
    get { return _foreground; }
    set
    {
        _foreground = value;
        nameLabel.Foreground = value;
        addressLabel.Foreground = value;
        cityLabel.Foreground = value;
        stateLabel.Foreground = value;
        zipLabel.Foreground = value;
    }
}

Devolver los datos al hostSending the Data Back to the Host

El componente final del archivo es la clase MyControlEventArgs, que se usa para enviar los datos recopilados de nuevo al host.The final component in the file is the MyControlEventArgs class, which is used to send the collected data back to the host.

Agregue el código siguiente al espacio de nombres MyControls.Add the following code to your MyControls namespace. La implementación es sencilla, por lo que no se tratará más adelante.The implementation is straightforward, and is not discussed further.

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; }
    }
}

Compile la solución.Build the solution. La compilación generará un archivo DLL denominado MyControls.dll.The build will produce a DLL named MyControls.dll.

Implementar la aplicación host de Windows FormsImplementing the Windows Forms Host Application

La aplicación host de Windows Forms usa un objeto ElementHost para hospedar el control compuesto WPFWPF.The Windows Forms host application uses an ElementHost object to host the WPFWPF composite control. La aplicación controla el evento OnButtonClick para recibir los datos del control compuesto.The application handles the OnButtonClick event to receive the data from the composite control. La aplicación también tiene un conjunto de botones de opción que se pueden usar para modificar la apariencia del control.The application also has a set of option buttons that you can use to modify the control’s appearance. En la siguiente ilustración se muestra la aplicación.The following illustration shows the application.

La siguiente imagen muestra un control compuesto de WPF hospedado en una aplicación Windows Forms "The following image shows a WPF composite control hosted in a Windows Forms application"

Scteenshot que muestra un control Avalon de hospedaje de Windows Forms.

Crear el proyectoCreating the Project

Para iniciar el proyecto:To start the project:

  1. Inicie Visual Studio y abra el cuadro de diálogo nuevo proyecto .Launch Visual Studio, and open the New Project dialog box.

  2. En Visual C# y en la categoría de Windows, seleccione la plantilla de aplicación Windows Forms .In Visual C# and the Windows category, select the Windows Forms Application template.

  3. Asigne al nuevo proyecto el nombre de WFHost.Name the new project WFHost.

  4. Para la ubicación, especifique la misma carpeta de nivel superior que contiene el proyecto MyControls.For the location, specify the same top-level folder that contains the MyControls project.

  5. Haga clic en Aceptar para crear el proyecto.Click OK to create the project.

También debe agregar referencias al archivo DLL que contiene MyControl1 y otros ensamblados.You also need to add references to the DLL that contains MyControl1 and other assemblies.

  1. Haga clic con el botón derecho en el nombre del proyecto en Explorador de soluciones y seleccione Agregar referencia.Right-click the project name in Solution Explorer, and select Add Reference.

  2. Haga clic en la pestaña examinar y busque la carpeta que contiene DataControl. dll.Click the Browse tab, and browse to the folder that contains MyControls.dll. En este tutorial, esta carpeta es MyControls\bin\Debug.For this walkthrough, this folder is MyControls\bin\Debug.

  3. Seleccione Datacontrols. dll y, a continuación, haga clic en Aceptar.Select MyControls.dll, and then click OK.

  4. Agregue referencias a los ensamblados siguientes.Add references to the following assemblies.

    • PresentationCorePresentationCore

    • PresentationFrameworkPresentationFramework

    • System.XamlSystem.Xaml

    • WindowsBaseWindowsBase

    • WindowsFormsIntegrationWindowsFormsIntegration

Implementar la interfaz de usuario de la aplicaciónImplementing the User Interface for the Application

La interfaz de usuario de la aplicación de Windows Forms contiene varios controles para interactuar con el control compuesto de WPF.The UI for the Windows Form application contains several controls to interact with the WPF composite control.

  1. Abra Form1 en el Diseñador de Windows Forms.Open Form1 in the Windows Form Designer.

  2. Amplíe el formulario para que quepan los controles.Enlarge the form to accommodate the controls.

  3. En la esquina superior derecha del formulario, agregue un control System.Windows.Forms.Panel para que contenga el WPFWPF control compuesto.In the upper-right corner of the form, add a System.Windows.Forms.Panel control to hold the WPFWPF composite control.

  4. Agregue los siguientes controles de System.Windows.Forms.GroupBox al formulario.Add the following System.Windows.Forms.GroupBox controls to the form.

    NameName TextText
    groupBox1groupBox1 Color de fondoBackground Color
    groupBox2groupBox2 Color de primer planoForeground Color
    groupBox3groupBox3 Tamaño de fuenteFont Size
    groupBox4groupBox4 Familia de fuentesFont Family
    groupBox5groupBox5 Estilo de fuenteFont Style
    groupBox6groupBox6 Espesor de fuenteFont Weight
    groupBox7groupBox7 Datos del controlData from control
  5. Agregue los siguientes controles de System.Windows.Forms.RadioButton a los controles de System.Windows.Forms.GroupBox.Add the following System.Windows.Forms.RadioButton controls to the System.Windows.Forms.GroupBox controls.

    GroupBoxGroupBox NameName TextText
    groupBox1groupBox1 radioBackgroundOriginalradioBackgroundOriginal OriginalOriginal
    groupBox1groupBox1 radioBackgroundLightGreenradioBackgroundLightGreen LightGreenLightGreen
    groupBox1groupBox1 radioBackgroundLightSalmonradioBackgroundLightSalmon LightSalmonLightSalmon
    groupBox2groupBox2 radioForegroundOriginalradioForegroundOriginal OriginalOriginal
    groupBox2groupBox2 radioForegroundRedradioForegroundRed RojoRed
    groupBox2groupBox2 radioForegroundYellowradioForegroundYellow AmarilloYellow
    groupBox3groupBox3 radioSizeOriginalradioSizeOriginal OriginalOriginal
    groupBox3groupBox3 radioSizeTenradioSizeTen 1010
    groupBox3groupBox3 radioSizeTwelveradioSizeTwelve 1212
    groupBox4groupBox4 radioFamilyOriginalradioFamilyOriginal OriginalOriginal
    groupBox4groupBox4 radioFamilyTimesradioFamilyTimes Times New RomanTimes New Roman
    groupBox4groupBox4 radioFamilyWingDingsradioFamilyWingDings WingDingsWingDings
    groupBox5groupBox5 radioStyleOriginalradioStyleOriginal NormalNormal
    groupBox5groupBox5 radioStyleItalicradioStyleItalic CursivaItalic
    groupBox6groupBox6 radioWeightOriginalradioWeightOriginal OriginalOriginal
    groupBox6groupBox6 radioWeightBoldradioWeightBold NegritaBold
  6. Agregue los siguientes controles de System.Windows.Forms.Label al último System.Windows.Forms.GroupBox.Add the following System.Windows.Forms.Label controls to the last System.Windows.Forms.GroupBox. Estos controles muestran los datos devueltos por el WPFWPF control compuesto.These controls display the data returned by the WPFWPF composite control.

    GroupBoxGroupBox NameName TextText
    groupBox7groupBox7 lblNamelblName Nombre:Name:
    groupBox7groupBox7 lblAddresslblAddress Dirección postal:Street Address:
    groupBox7groupBox7 lblCitylblCity Ciudad:City:
    groupBox7groupBox7 lblStatelblState Estado:State:
    groupBox7groupBox7 lblZiplblZip Código postal:Zip:

Inicializar el formularioInitializing the Form

Normalmente, se implementa el código de hospedaje en el controlador de eventos Load del formulario.You generally implement the hosting code in the form's Load event handler. En el código siguiente se muestra el controlador de eventos Load, un controlador para el evento Loaded del control compuesto WPFWPF y declaraciones para varias variables globales que se usan más adelante.The following code shows the Load event handler, a handler for the WPFWPF composite control’s Loaded event, and declarations for several global variables that are used later.

En el Diseñador de Windows Forms, haga doble clic en el formulario para crear un controlador de eventos de Load.In the Windows Forms Designer, double-click the form to create a Load event handler. En la parte superior de Form1.cs, agregue las siguientes instrucciones de using.At the top of Form1.cs, add the following using statements.

using System.Windows;
using System.Windows.Forms.Integration;
using System.Windows.Media;

Reemplace el contenido de la clase de Form1 existente por el código siguiente.Replace the contents of the existing Form1 class with the following code.

private ElementHost ctrlHost;
private MyControls.MyControl1 wpfAddressCtrl;
System.Windows.FontWeight initFontWeight;
double initFontSize;
System.Windows.FontStyle initFontStyle;
System.Windows.Media.SolidColorBrush initBackBrush;
System.Windows.Media.SolidColorBrush initForeBrush;
System.Windows.Media.FontFamily initFontFamily;

public Form1()
{
    InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
    ctrlHost = new ElementHost();
    ctrlHost.Dock = DockStyle.Fill;
    panel1.Controls.Add(ctrlHost);
    wpfAddressCtrl = new MyControls.MyControl1();
    wpfAddressCtrl.InitializeComponent();
    ctrlHost.Child = wpfAddressCtrl;

    wpfAddressCtrl.OnButtonClick +=
        new MyControls.MyControl1.MyControlEventHandler(
        avAddressCtrl_OnButtonClick);
    wpfAddressCtrl.Loaded += new RoutedEventHandler(
        avAddressCtrl_Loaded);
}

void avAddressCtrl_Loaded(object sender, EventArgs e)
{
    initBackBrush = (SolidColorBrush)wpfAddressCtrl.MyControl_Background;
    initForeBrush = wpfAddressCtrl.MyControl_Foreground;
    initFontFamily = wpfAddressCtrl.MyControl_FontFamily;
    initFontSize = wpfAddressCtrl.MyControl_FontSize;
    initFontWeight = wpfAddressCtrl.MyControl_FontWeight;
    initFontStyle = wpfAddressCtrl.MyControl_FontStyle;
}

El método Form1_Load del código anterior muestra el procedimiento general para hospedar un control WPFWPF:The Form1_Load method in the preceding code shows the general procedure for hosting a WPFWPF control:

  1. Cree un nuevo objeto de ElementHost.Create a new ElementHost object.

  2. Establezca la propiedad Dock del control en DockStyle.Fill.Set the control's Dock property to DockStyle.Fill.

  3. Agregue el control ElementHost a la colección Controls del control Panel.Add the ElementHost control to the Panel control's Controls collection.

  4. Cree una instancia del control WPFWPF.Create an instance of the WPFWPF control.

  5. Hospede el control compuesto en el formulario asignando el control a la propiedad Child del control ElementHost.Host the composite control on the form by assigning the control to the ElementHost control's Child property.

Las dos líneas restantes del método Form1_Load adjuntan controladores a dos eventos de control:The remaining two lines in the Form1_Load method attach handlers to two control events:

  • OnButtonClick es un evento personalizado que el control compuesto desencadena cuando el usuario hace clic en el botón Aceptar o Cancelar .OnButtonClick is a custom event that is fired by the composite control when the user clicks the OK or Cancel button. El evento se controla para obtener la respuesta del usuario y recopilar los datos que este haya especificado.You handle the event to get the user's response and to collect any data that the user specified.

  • Loaded es un evento estándar generado por un control WPFWPF cuando se carga por completo.Loaded is a standard event that is raised by a WPFWPF control when it is fully loaded. El evento se usa aquí porque el ejemplo necesita inicializar distintas variables globales usando las propiedades del control.The event is used here because the example needs to initialize several global variables using properties from the control. En el momento del evento de Load del formulario, el control no se carga completamente y esos valores todavía se establecen en null.At the time of the form's Load event, the control is not fully loaded and those values are still set to null. Debe esperar hasta que se produzca el evento Loaded del control antes de poder tener acceso a esas propiedades.You need to wait until the control’s Loaded event occurs before you can access those properties.

El controlador de eventos Loaded se muestra en el código anterior.The Loaded event handler is shown in the preceding code. El controlador de OnButtonClick se describe en la sección siguiente.The OnButtonClick handler is discussed in the next section.

Administrar OnButtonClickHandling OnButtonClick

El evento OnButtonClick se produce cuando el usuario hace clic en el botón Aceptar o Cancelar .The OnButtonClick event occurs when the user clicks the OK or Cancel button.

El controlador de eventos comprueba el campo IsOK del argumento del evento para determinar en qué botón se hizo clic.The event handler checks the event argument's IsOK field to determine which button was clicked. Las variables de datos lblcorresponden a los controles de Label que se han explicado anteriormente.The lbldata variables correspond to the Label controls that were discussed earlier. Si el usuario hace clic en el botón Aceptar , los datos de los controles TextBox del control se asignan al control Label correspondiente.If the user clicks the OK button, the data from the control’s TextBox controls is assigned to the corresponding Label control. Si el usuario hace clic en Cancelar, los valores de Text se establecen en las cadenas predeterminadas.If the user clicks Cancel, the Text values are set to the default strings.

Agregue el siguiente código de controlador de eventos de clic de botón a la clase Form1.Add the following button click event handler code to the Form1 class.

void avAddressCtrl_OnButtonClick(
    object sender,
    MyControls.MyControl1.MyControlEventArgs args)
{
    if (args.IsOK)
    {
        lblAddress.Text = "Street Address: " + args.MyStreetAddress;
        lblCity.Text = "City: " + args.MyCity;
        lblName.Text = "Name: " + args.MyName;
        lblState.Text = "State: " + args.MyState;
        lblZip.Text = "Zip: " + args.MyZip;
    }
    else
    {
        lblAddress.Text = "Street Address: ";
        lblCity.Text = "City: ";
        lblName.Text = "Name: ";
        lblState.Text = "State: ";
        lblZip.Text = "Zip: ";
    }
}

Compile y ejecute la aplicación.Build and run the application. Agregue texto en el control compuesto de WPF y, a continuación, haga clic en Aceptar.Add some text in the WPF composite control and then click OK. El texto aparece en las etiquetas.The text appears in the labels. En este momento, no se ha agregado código para controlar los botones de radio.At this point, code has not been added to handle the radio buttons.

Modificar la apariencia del controlModifying the Appearance of the Control

Los controles RadioButton del formulario permitirán al usuario cambiar los colores de primer plano y de fondo del control compuesto WPFWPF, así como varias propiedades de fuente.The RadioButton controls on the form will enable the user to change the WPFWPF composite control’s foreground and background colors as well as several font properties. El objeto ElementHost expone el color de fondo.The background color is exposed by the ElementHost object. Las propiedades restantes se exponen como propiedades personalizadas del control.The remaining properties are exposed as custom properties of the control.

Haga doble clic en cada control de RadioButton en el formulario para crear CheckedChanged controladores de eventos.Double-click each RadioButton control on the form to create CheckedChanged event handlers. Reemplace los controladores de eventos CheckedChanged por el código siguiente.Replace the CheckedChanged event handlers with the following code.

private void radioBackgroundOriginal_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_Background = initBackBrush;
}

private void radioBackgroundLightGreen_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_Background = new SolidColorBrush(Colors.LightGreen);
}

private void radioBackgroundLightSalmon_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_Background = new SolidColorBrush(Colors.LightSalmon);
}

private void radioForegroundOriginal_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_Foreground = initForeBrush;
}

private void radioForegroundRed_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_Foreground = new System.Windows.Media.SolidColorBrush(Colors.Red);
}

private void radioForegroundYellow_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_Foreground = new System.Windows.Media.SolidColorBrush(Colors.Yellow);
}

private void radioFamilyOriginal_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontFamily = initFontFamily;
}

private void radioFamilyTimes_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontFamily = new System.Windows.Media.FontFamily("Times New Roman");
}

private void radioFamilyWingDings_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontFamily = new System.Windows.Media.FontFamily("WingDings");
}

private void radioSizeOriginal_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontSize = initFontSize;
}

private void radioSizeTen_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontSize = 10;
}

private void radioSizeTwelve_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontSize = 12;
}

private void radioStyleOriginal_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontStyle = initFontStyle;
}

private void radioStyleItalic_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontStyle = System.Windows.FontStyles.Italic;
}

private void radioWeightOriginal_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontWeight = initFontWeight;
}

private void radioWeightBold_CheckedChanged(object sender, EventArgs e)
{
    wpfAddressCtrl.MyControl_FontWeight = FontWeights.Bold;
}

Compile y ejecute la aplicación.Build and run the application. Haga clic en los diferentes botones de radio para ver el efecto en el control compuesto de WPF.Click the different radio buttons to see the effect on the WPF composite control.

Vea tambiénSee also