Tutorial: Creación de su primera aplicación de WPF en Visual Studio 2019

En este artículo se muestra cómo desarrollar una aplicación de escritorio de Windows Presentation Foundation (WPF) que incluya los elementos comunes a la mayoría de las aplicaciones de WPF: marcado de lenguaje XAML, código subyacente, definiciones de aplicaciones, controles, diseño, enlace de datos y estilos. Para desarrollar la aplicación, usará Visual Studio.

Importante

Este artículo se escribió para .NET Framework. Para empezar a trabajar con .NET 7, consulte Tutorial: Creación de una nueva aplicación WPF con .NET.

En este tutorial aprenderá a:

  • Crear un proyecto de WPF.
  • Usar XAML para diseñar la apariencia de la interfaz de usuario (UI) de la aplicación.
  • Escribir código para crear el comportamiento de la aplicación.
  • Crear una definición de aplicación para administrar la aplicación.
  • Agregar controles y crear el diseño para crear la interfaz de usuario de la aplicación.
  • Crear estilos para una apariencia coherente en toda la interfaz de usuario de la aplicación.
  • Enlazar la interfaz de usuario a los datos, tanto para rellenar la interfaz de usuario de los datos como para mantener sincronizados los datos y la interfaz de usuario.

Al final del tutorial, habrá creado una aplicación Windows independiente que permite a los usuarios ver informes de gastos para personas seleccionadas. La aplicación consta de varias páginas de WPF hospedadas en una ventana de estilo de explorador.

Sugerencia

El código de ejemplo que se usa en este tutorial está disponible para Visual Basic y C# en este tutorial de código de ejemplo de aplicación WPF.

Puede alternar el lenguaje de código del código de ejemplo entre C# y Visual Basic mediante el selector de lenguaje en la parte superior de esta página.

Prerrequisitos

Creación del proyecto de aplicación

El primer paso es crear la infraestructura de la aplicación, que incluye una definición de aplicación, dos páginas y una imagen.

  1. Cree un proyecto de aplicación WPF en Visual Basic o Visual C# denominado ExpenseIt:

    1. Abra Visual Studio y seleccione Crear un nuevo proyecto en el menú Comenzar.

      Aparece el cuadro de diálogo Crear un proyecto nuevo.

    2. En la lista desplegable Lenguaje, seleccione C# o Visual Basic.

    3. Seleccione la plantilla Aplicación de WPF (.NET Framework) y luego Siguiente.

      Create a new project dialog

      Se abre el cuadro de diálogo Configurar el nuevo proyecto.

    4. Escriba ExpenseIt como nombre del proyecto y, después, seleccione Crear.

      Configure a new project dialog

      Visual Studio crea el proyecto y abre el diseñador de la ventana predeterminada de la aplicación llamada MainWindow.xaml.

  2. Abra Application.xaml (Visual Basic) o App.xaml (C#).

    El archivo XAML define una aplicación de WPF y los recursos de la aplicación. También se usa este archivo para especificar la interfaz de usuario que se muestra automáticamente cuando se inicia la aplicación; en este caso, MainWindow.xaml.

    El código XAML debe tener un aspecto similar al siguiente en Visual Basic:

    <Application x:Class="Application"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        StartupUri="MainWindow.xaml">
        <Application.Resources>
            
        </Application.Resources>
    </Application>
    

    Y como se muestra a continuación en C#:

    <Application x:Class="ExpenseIt.App"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         StartupUri="MainWindow.xaml">
        <Application.Resources>
             
        </Application.Resources>
    </Application>
    
  3. Abra MainWindow.xaml.

    Este archivo XAML es la ventana principal de la aplicación y muestra contenido creado en páginas. La clase Window define las propiedades de una ventana, como su título, tamaño o icono, y controla eventos, como cerrar u ocultar.

  4. Cambie el elemento Window a NavigationWindow, como se muestra en el código XAML siguiente:

    <NavigationWindow x:Class="ExpenseIt.MainWindow"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         ...
    </NavigationWindow>
    

    Esta aplicación navega a contenido diferente en función de la entrada de usuario. Este es el motivo por el que la Window principal debe cambiarse a NavigationWindow. NavigationWindow hereda todas las propiedades de Window. El elemento NavigationWindow del archivo XAML crea una instancia de la clase NavigationWindow. Para obtener más información, consulte Información general sobre navegación.

  5. Quite los elementos Grid de entre las etiquetas NavigationWindow.

  6. Cambie las siguientes propiedades en el código XAML para el elemento NavigationWindow:

    • Establezca la propiedad Title en "ExpenseIt".

    • Establece la propiedad Height en 350 píxeles.

    • Establece la propiedad Width en 500 píxeles.

    El código XAML debe tener un aspecto similar al siguiente en Visual Basic:

    <NavigationWindow x:Class="MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ExpenseIt" Height="350" Width="500">
     
    </NavigationWindow>
    

    Y como se muestra a continuación en C#:

    <NavigationWindow x:Class="ExpenseIt.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ExpenseIt" Height="350" Width="500">
        
    </NavigationWindow>
    
  7. Abra MainWindow.xaml.vb o MainWindow.xaml.cs.

    Este archivo es un archivo de código subyacente que contiene código para controlar los eventos declarados en MainWindow.xaml. Este archivo contiene una clase parcial para la ventana definida en código XAML.

  8. Si usa C#, cambie la clase MainWindow para derivar de NavigationWindow. (En Visual Basic, esto sucede automáticamente al cambiar la ventana en XAML). El código de C# debería tener ahora este aspecto:

    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    
    namespace ExpenseIt
    {
        /// <summary>
        /// Interaction logic for MainWindow.xaml
        /// </summary>
        public partial class MainWindow : NavigationWindow
        {
            public MainWindow()
            {
                InitializeComponent();
            }
        }
    }
    

Agregar archivos a la aplicación

En esta sección, agregará dos páginas y una imagen a la aplicación.

  1. Agregue una nueva página al proyecto y asígnele el nombre ExpenseItHome.xaml:

    1. En el Explorador de soluciones, haga clic con el botón derecho en el nodo de proyecto ExpenseIt y elija Agregar>Página.

    2. En el cuadro de diálogo Agregar nuevo elemento, la plantilla Página (WPF) ya está seleccionada. Escriba el nombre ExpenseItHome y, a continuación, seleccione Agregar.

    Esta página es la primera que se muestra cuando se inicia la aplicación. Mostrará una lista de personas entre las que puede seleccionar una para mostrar el informe de gastos.

  2. Abra ExpenseItHome.xaml.

  3. Establezca Title en "ExpenseIt - Home".

  4. Establezca DesignHeight en 350 píxeles y DesignWidth en 500 píxeles.

    El XAML ahora aparece de la siguiente manera para Visual Basic:

    <Page x:Class="ExpenseItHome"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      mc:Ignorable="d" 
      d:DesignHeight="350" d:DesignWidth="500"
      Title="ExpenseIt - Home">
        <Grid>
            
        </Grid>
    </Page>
    

    Y como se muestra a continuación en C#:

    <Page x:Class="ExpenseIt.ExpenseItHome"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
          xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
          mc:Ignorable="d" 
          d:DesignHeight="350" d:DesignWidth="500"
        Title="ExpenseIt - Home">
    
        <Grid>
            
        </Grid>
    </Page>
    
  5. Abra MainWindow.xaml.

  6. Agregue una propiedad Source al elemento NavigationWindow y establézcala en "ExpenseItHome.xaml".

    Esto establece que ExpenseItHome.xaml sea la primera página que se abre al iniciar la aplicación.

    Ejemplo de XAML en Visual Basic:

    <NavigationWindow x:Class="MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ExpenseIt" Height="350" Width="500" Source="ExpenseItHome.xaml">
        
    </NavigationWindow>
    

    Y en C#:

    <NavigationWindow x:Class="ExpenseIt.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ExpenseIt" Height="350" Width="500" Source="ExpenseItHome.xaml">
        
    </NavigationWindow>
    

    Sugerencia

    También puede establecer la propiedad Source en la categoría Varios de la ventana Propiedades.

    Source property in Properties window

  7. Agregue otra nueva página de WPF al proyecto y asígnele el nombre ExpenseReportPage.xaml:

    1. En el Explorador de soluciones, haga clic con el botón derecho en el nodo de proyecto ExpenseIt y elija Agregar>Página.

    2. En el cuadro de diálogo Agregar nuevo elemento, seleccione la plantilla Página (WPF). Escriba el nombre ExpenseReportPage y, a continuación, seleccione Agregar.

    Esta página mostrará el informe de gastos de la persona que se haya seleccionado en la página ExpenseItHome.

  8. Abra el archivo ExpenseReportPage.xaml.

  9. Establezca Title en "ExpenseIt - View Expense".

  10. Establezca DesignHeight en 350 píxeles y DesignWidth en 500 píxeles.

    ExpenseReportPage.xaml ahora tiene el siguiente aspecto en Visual Basic:

    <Page x:Class="ExpenseReportPage"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
          xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
          mc:Ignorable="d" 
          d:DesignHeight="350" d:DesignWidth="500"
          Title="ExpenseIt - View Expense">
        <Grid>
            
        </Grid>
    </Page>
    

    Y como se muestra a continuación en C#:

    <Page x:Class="ExpenseIt.ExpenseReportPage"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
          xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
          mc:Ignorable="d" 
          d:DesignHeight="350" d:DesignWidth="500"
        Title="ExpenseIt - View Expense">
    
        <Grid>
            
        </Grid>
    </Page>
    
  11. Abra ExpenseItHome.xaml.vb y ExpenseReportPage.xaml.vb o ExpenseItHome.xaml.cs y ExpenseReportPage.xaml.cs.

    Cuando se crea un archivo de página, Visual Studio crea automáticamente su archivo de código subyacente. Estos archivos de código subyacente controlan la lógica para responder a la entrada del usuario.

    El código debe tener un aspecto parecido al siguiente para ExpenseItHome:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    
    namespace ExpenseIt
    {
        /// <summary>
        /// Interaction logic for ExpenseItHome.xaml
        /// </summary>
        public partial class ExpenseItHome : Page
        {
            public ExpenseItHome()
            {
                InitializeComponent();
            }
        }
    }
    
    Class ExpenseItHome
    
    End Class
    

    Y como se muestra a continuación para ExpenseReportPage:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    
    namespace ExpenseIt
    {
        /// <summary>
        /// Interaction logic for ExpenseReportPage.xaml
        /// </summary>
        public partial class ExpenseReportPage : Page
        {
            public ExpenseReportPage()
            {
                InitializeComponent();
            }
        }
    }
    
    Class ExpenseReportPage
    
    End Class
    
  12. Agregue una imagen denominada watermark.png al proyecto. Puede crear su propia imagen, copiar el archivo desde el código de ejemplo u obtenerlo del repositorio microsoft/WPF-Samples de GitHub.

    1. Haga clic con el botón derecho en el nodo del proyecto y seleccione Agregar>Elemento existente o presione Mayús+Alt+A.

    2. En el cuadro de diálogo Agregar elemento existente, establezca el filtro de archivo en Todos los archivos o Archivos de imagen, vaya al archivo de imagen que desea usar y, a continuación, seleccione Agregar.

    3. Seleccione el archivo de imagen en Explorador de soluciones y, a continuación, en la ventana Propiedades, establezca Acción de compilación en Recurso.

Compilación y ejecución de la aplicación

  1. Para compilar y ejecutar la aplicación, presione F5 o seleccione Iniciar depuración en el menú Depurar.

    En la siguiente ilustración se muestra la aplicación con los botones NavigationWindow:

    Application after you build and run it.

  2. Cierre la aplicación para volver a Visual Studio.

Creación del diseño

Diseño permite colocar los elementos de la interfaz de usuario de forma ordenada y administrar el tamaño y la posición de dichos elementos cuando se cambia el tamaño de una interfaz de usuario. Normalmente, se crea un diseño con uno de los controles de diseño siguientes:

  • Canvas: define un área en la cual puede colocar elementos secundarios explícitamente mediante coordenadas relativas al área de Lienzo.
  • DockPanel: define un área en la que puede organizar elementos secundarios de forma horizontal o vertical, en relación unos con otros.
  • Grid: define un área de cuadrícula flexible que consta de columnas y filas.
  • StackPanel: organiza elementos secundarios en una sola línea que puede orientarse horizontal o verticalmente.
  • VirtualizingStackPanel: organiza y virtualiza contenido en una sola línea orientada horizontal o verticalmente.
  • WrapPanel: coloca los elementos secundarios en posición secuencial de izquierda a derecha y traslada el contenido a la línea siguiente en el borde del cuadro contenedor. La clasificación siguiente se realiza secuencialmente de arriba abajo o de izquierda a derecha, en función del valor de la propiedad Orientation.

Cada uno de estos controles de diseño admite un tipo particular de diseño para sus elementos secundarios. Puede cambiar el tamaño de las páginas de ExpenseIt, y cada página tiene elementos organizados en horizontal y vertical junto con otros elementos. En este ejemplo, Grid se usa como elemento de diseño para la aplicación.

Sugerencia

Para obtener más información sobre los elementos Panel, vea Información general sobre los paneles. Para obtener más información sobre el diseño, consulte Diseño.

En esta sección, va a crear una tabla con una columna de tres filas y un margen de 10 píxeles agregando definiciones de columna y fila al control Grid en ExpenseItHome.xaml.

  1. En ExpenseItHome.xaml, establezca la propiedad Margin del elemento Grid en "10,0,10,10", que corresponde a los márgenes izquierdo, superior, derecho e inferior:

    <Grid Margin="10,0,10,10">
    

    Sugerencia

    También puede establecer los valores Margin en la ventana Propiedades, en la categoría Diseño:

    Margin values in Properties window

  2. Agregue el siguiente código XAML entre las etiquetas Grid para crear las definiciones de fila y columna:

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

    La propiedad Height de dos filas se establece en Auto, lo que significa que el tamaño de las filas dependerá de lo que contengan. El valor predeterminado de Height es el cambio de tamaño Star, lo que significa que la fila será una proporción ponderada del espacio disponible. Por ejemplo, si dos filas tienen un Height de "*", ambas tienen un alto que es la mitad del espacio disponible.

    Grid ahora debe contener el siguiente XAML:

    <Grid Margin="10,0,10,10">
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition />
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
    </Grid>
    

Agregar controles

En esta sección, actualizará la interfaz de usuario de la página principal para mostrar una lista de personas en la que podrá seleccionar a una para mostrar su informe de gastos. Los controles son objetos de interfaz de usuario que permiten a los usuarios interactuar con su aplicación. Para obtener más información, consulte Controles.

Para crear esta interfaz de usuario, agregará los siguientes elementos a ExpenseItHome.xaml:

  • ListBox (para la lista de personas).
  • Label (para el encabezado de lista).
  • Button (para hacer clic para ver el informe de gastos de la persona seleccionada en la lista).

Cada control se sitúa en una fila de Grid estableciendo la propiedad adjunta Grid.Row. Para obtener más información sobre las propiedades adjuntas, consulte Introducción a las propiedades adjuntas.

  1. En ExpenseItHome.xaml, agregue el código XAML siguiente en algún lugar entre las etiquetas Grid:

    
    <!-- People list -->
    <Border Grid.Column="0" Grid.Row="0" Height="35" Padding="5" Background="#4E87D4">
        <Label VerticalAlignment="Center" Foreground="White">Names</Label>
    </Border>
    <ListBox Name="peopleListBox" Grid.Column="0" Grid.Row="1">
        <ListBoxItem>Mike</ListBoxItem>
        <ListBoxItem>Lisa</ListBoxItem>
        <ListBoxItem>John</ListBoxItem>
        <ListBoxItem>Mary</ListBoxItem>
    </ListBox>
    
    <!-- View report button -->
    <Button Grid.Column="0" Grid.Row="2" Margin="0,10,0,10" Width="125" Height="25" HorizontalAlignment="Right">View</Button>
    

    Sugerencia

    Puede también crear los controles arrastrándolos desde la ventana Cuadro de herramientas a la ventana de diseño y establecer luego sus propiedades en la ventana Propiedades.

  2. Compile y ejecute la aplicación.

    En la ilustración siguiente se muestran los controles que creó:

ExpenseIt sample screenshot displaying a list of names

Agregar una imagen y un título

En esta sección, actualizará la interfaz de usuario de la página principal con una imagen y un título de página.

  1. En ExpenseItHome.xaml, agregue otra columna a ColumnDefinitions con un valor fijo Width de 230 píxeles:

    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="230" />
        <ColumnDefinition />
    </Grid.ColumnDefinitions>
    
  2. Agregue otra fila a RowDefinitions, para obtener un total de cuatro filas:

    <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition Height="Auto"/>
        <RowDefinition />
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    
  3. Mueva los controles a la segunda columna estableciendo la propiedad Grid.Column en 1 en cada uno de los tres controles (Border, ListBox y Button).

  4. Mueva cada control hacia abajo una fila incrementando su valor de Grid.Row en 1 para cada uno de los tres controles (Border, ListBox y Button) y para el elemento Border.

    El XAML de los tres controles ahora tiene el siguiente aspecto:

      <Border Grid.Column="1" Grid.Row="1" Height="35" Padding="5" Background="#4E87D4">
          <Label VerticalAlignment="Center" Foreground="White">Names</Label>
      </Border>
      <ListBox Name="peopleListBox" Grid.Column="1" Grid.Row="2">
          <ListBoxItem>Mike</ListBoxItem>
          <ListBoxItem>Lisa</ListBoxItem>
          <ListBoxItem>John</ListBoxItem>
          <ListBoxItem>Mary</ListBoxItem>
      </ListBox>
    
      <!-- View report button -->
      <Button Grid.Column="1" Grid.Row="3" Margin="0,10,0,0" Width="125"
    Height="25" HorizontalAlignment="Right">View</Button>
    
  5. Establezca la propiedad Background en el archivo de imagen watermark.png agregando el siguiente XAML en cualquier lugar entre las etiquetas <Grid> y </Grid>:

    <Grid.Background>
        <ImageBrush ImageSource="watermark.png"/>
    </Grid.Background>
    
  6. Antes del elemento Border, agregue un elemento Label con el contenido "Ver informe de gastos". Esta etiqueta es el título de la página.

    <Label Grid.Column="1" VerticalAlignment="Center" FontFamily="Trebuchet MS" 
            FontWeight="Bold" FontSize="18" Foreground="#0066cc">
        View Expense Report
    </Label>
    
  7. Compile y ejecute la aplicación.

En la ilustración siguiente se muestran los resultados de lo que acaba de agregar:

ExpenseIt sample screenshot showing the new image background and page title

Agregar código para controlar eventos

  1. En ExpenseItHome.xaml, agregue un controlador de eventos Click al elemento Button. Para obtener más información, consulte Cómo: Crear controladores de eventos simples.

      <!-- View report button -->
      <Button Grid.Column="1" Grid.Row="3" Margin="0,10,0,0" Width="125"
    Height="25" HorizontalAlignment="Right" Click="Button_Click">View</Button>
    
  2. Abra ExpenseItHome.xaml.vb o ExpenseItHome.xaml.cs.

  3. Agregue el siguiente código a la clase ExpenseItHome para agregar un controlador de eventos de clic de botón. El controlador de eventos abre la página ExpenseReportPage.

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        // View Expense Report
        ExpenseReportPage expenseReportPage = new ExpenseReportPage();
        this.NavigationService.Navigate(expenseReportPage);
    }
    
    Private Sub Button_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
        ' View Expense Report
        Dim expenseReportPage As New ExpenseReportPage()
        Me.NavigationService.Navigate(expenseReportPage)
    
    End Sub
    

Crear la interfaz de usuario para ExpenseReportPage

ExpenseReportPage.xaml muestra el informe de gastos de la persona que se seleccionó en la página ExpenseItHome. En esta sección, creará la interfaz de usuario de ExpenseReportPage. También agregará colores de fondo y relleno a los diversos elementos de la interfaz de usuario.

  1. Abra el archivo ExpenseReportPage.xaml.

  2. Agregue el código XAML siguiente entre las etiquetasGrid:

     <Grid.Background>
         <ImageBrush ImageSource="watermark.png" />
     </Grid.Background>
     <Grid.ColumnDefinitions>
         <ColumnDefinition Width="230" />
         <ColumnDefinition />
     </Grid.ColumnDefinitions>
     <Grid.RowDefinitions>
         <RowDefinition Height="Auto" />
         <RowDefinition />
     </Grid.RowDefinitions>
    
    
     <Label Grid.Column="1" VerticalAlignment="Center" FontFamily="Trebuchet MS" 
     FontWeight="Bold" FontSize="18" Foreground="#0066cc">
         Expense Report For:
     </Label>
     <Grid Margin="10" Grid.Column="1" Grid.Row="1">
    
         <Grid.ColumnDefinitions>
             <ColumnDefinition />
             <ColumnDefinition />
         </Grid.ColumnDefinitions>
         <Grid.RowDefinitions>
             <RowDefinition Height="Auto" />
             <RowDefinition Height="Auto" />
             <RowDefinition />
         </Grid.RowDefinitions>
    
         <!-- Name -->
         <StackPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="0" Orientation="Horizontal">
             <Label Margin="0,0,0,5" FontWeight="Bold">Name:</Label>
             <Label Margin="0,0,0,5" FontWeight="Bold"></Label>
         </StackPanel>
    
         <!-- Department -->
         <StackPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="1" Orientation="Horizontal">
             <Label Margin="0,0,0,5" FontWeight="Bold">Department:</Label>
             <Label Margin="0,0,0,5" FontWeight="Bold"></Label>
         </StackPanel>
    
         <Grid Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="2" VerticalAlignment="Top" 
               HorizontalAlignment="Left">
             <!-- Expense type and Amount table -->
             <DataGrid  AutoGenerateColumns="False" RowHeaderWidth="0" >
                 <DataGrid.ColumnHeaderStyle>
                     <Style TargetType="{x:Type DataGridColumnHeader}">
                         <Setter Property="Height" Value="35" />
                         <Setter Property="Padding" Value="5" />
                         <Setter Property="Background" Value="#4E87D4" />
                         <Setter Property="Foreground" Value="White" />
                     </Style>
                 </DataGrid.ColumnHeaderStyle>
                 <DataGrid.Columns>
                     <DataGridTextColumn Header="ExpenseType" />
                     <DataGridTextColumn Header="Amount"  />
                 </DataGrid.Columns>
             </DataGrid>
         </Grid>
     </Grid>
    

    Esta interfaz de usuario es similar a la de ExpenseItHome.xaml, excepto porque los datos del informe se muestran en un DataGrid.

  3. Compile y ejecute la aplicación.

  4. Seleccione el botón Ver.

    Se mostrará la página de informe de gastos Observe también que el botón de navegación hacia atrás está habilitado.

En la siguiente ilustración se muestran los elementos de interfaz de usuario agregados a ExpenseReportPage.xaml.

ExpenseIt sample screenshot showing the UI just created for the ExpenseReportPage.

Aplicar estilo a los controles

La apariencia de los diversos elementos a menudo es igual para todos aquellos del mismo tipo en una interfaz de usuario. La interfaz de usuario utiliza estilos para permitir que las apariencias sean reutilizables en varios elementos. La reusabilidad de los estilos ayuda a simplificar la creación y administración de XAML. En esta sección se reemplazan los atributos de cada elemento que se definieron en pasos anteriores por estilos.

  1. Abra Application.xaml o App.xaml.

  2. Agregue el código XAML siguiente entre las etiquetasApplication.Resources:

    
    <!-- Header text style -->
    <Style x:Key="headerTextStyle">
        <Setter Property="Label.VerticalAlignment" Value="Center"></Setter>
        <Setter Property="Label.FontFamily" Value="Trebuchet MS"></Setter>
        <Setter Property="Label.FontWeight" Value="Bold"></Setter>
        <Setter Property="Label.FontSize" Value="18"></Setter>
        <Setter Property="Label.Foreground" Value="#0066cc"></Setter>
    </Style>
    
    <!-- Label style -->
    <Style x:Key="labelStyle" TargetType="{x:Type Label}">
        <Setter Property="VerticalAlignment" Value="Top" />
        <Setter Property="HorizontalAlignment" Value="Left" />
        <Setter Property="FontWeight" Value="Bold" />
        <Setter Property="Margin" Value="0,0,0,5" />
    </Style>
    
    <!-- DataGrid header style -->
    <Style x:Key="columnHeaderStyle" TargetType="{x:Type DataGridColumnHeader}">
        <Setter Property="Height" Value="35" />
        <Setter Property="Padding" Value="5" />
        <Setter Property="Background" Value="#4E87D4" />
        <Setter Property="Foreground" Value="White" />
    </Style>
    
    <!-- List header style -->
    <Style x:Key="listHeaderStyle" TargetType="{x:Type Border}">
        <Setter Property="Height" Value="35" />
        <Setter Property="Padding" Value="5" />
        <Setter Property="Background" Value="#4E87D4" />
    </Style>
    
    <!-- List header text style -->
    <Style x:Key="listHeaderTextStyle" TargetType="{x:Type Label}">
        <Setter Property="Foreground" Value="White" />
        <Setter Property="VerticalAlignment" Value="Center" />
        <Setter Property="HorizontalAlignment" Value="Left" />
    </Style>
    
    <!-- Button style -->
    <Style x:Key="buttonStyle" TargetType="{x:Type Button}">
        <Setter Property="Width" Value="125" />
        <Setter Property="Height" Value="25" />
        <Setter Property="Margin" Value="0,10,0,0" />
        <Setter Property="HorizontalAlignment" Value="Right" />
    </Style>
    

    Este código XAML agrega los estilos siguientes:

    • headerTextStyle: para dar formato al título de la página Label.

    • labelStyle: para dar formato a los controles Label .

    • columnHeaderStyle: para dar formato a DataGridColumnHeader.

    • listHeaderStyle: para dar formato a los controles del encabezado de lista Border .

    • listHeaderTextStyle: para dar formato al encabezado de lista Label.

    • buttonStyle: para dar formato a Button en ExpenseItHome.xaml.

    Observe que los estilos son recursos y elementos secundarios del elemento de propiedad Application.Resources. En esta ubicación, los estilos se aplican a todos los elementos de una aplicación. Para ver un ejemplo del uso de recursos en una aplicación .NET, consulte Cómo: Usar recursos de aplicaciones.

  3. En ExpenseItHome.xaml, reemplace todo lo que haya entre los elementos Grid con el código XAML siguiente:

       <Grid.Background>
           <ImageBrush ImageSource="watermark.png"  />
       </Grid.Background>
      
       <Grid.ColumnDefinitions>
           <ColumnDefinition Width="230" />
           <ColumnDefinition />
       </Grid.ColumnDefinitions>
       
       <Grid.RowDefinitions>
           <RowDefinition/>
           <RowDefinition Height="Auto"/>
           <RowDefinition />
           <RowDefinition Height="Auto"/>
       </Grid.RowDefinitions>
    
       <!-- People list -->
      
       <Label Grid.Column="1" Style="{StaticResource headerTextStyle}" >
           View Expense Report
       </Label>
       
       <Border Grid.Column="1" Grid.Row="1" Style="{StaticResource listHeaderStyle}">
           <Label Style="{StaticResource listHeaderTextStyle}">Names</Label>
       </Border>
       <ListBox Name="peopleListBox" Grid.Column="1" Grid.Row="2">
           <ListBoxItem>Mike</ListBoxItem>
           <ListBoxItem>Lisa</ListBoxItem>
           <ListBoxItem>John</ListBoxItem>
           <ListBoxItem>Mary</ListBoxItem>
       </ListBox>
    
       <!-- View report button -->
       <Button Grid.Column="1" Grid.Row="3" Click="Button_Click" Style="{StaticResource buttonStyle}">View</Button>
    

    Las propiedades como VerticalAlignment y FontFamily que definen la apariencia de cada control se quitan y reemplazan aplicando los estilos. Por ejemplo, se aplica headerTextStyle a la Label "View Expense Report".

  4. Abra el archivo ExpenseReportPage.xaml.

  5. Reemplace todo lo que haya entre los elementos Grid con el código XAML siguiente:

      <Grid.Background>
          <ImageBrush ImageSource="watermark.png" />
      </Grid.Background>
      <Grid.ColumnDefinitions>
          <ColumnDefinition Width="230" />
          <ColumnDefinition />
      </Grid.ColumnDefinitions>
      <Grid.RowDefinitions>
          <RowDefinition Height="Auto" />
          <RowDefinition />
      </Grid.RowDefinitions>
    
    
      <Label Grid.Column="1" Style="{StaticResource headerTextStyle}">
          Expense Report For:
      </Label>
      <Grid Margin="10" Grid.Column="1" Grid.Row="1">
    
          <Grid.ColumnDefinitions>
              <ColumnDefinition />
              <ColumnDefinition />
          </Grid.ColumnDefinitions>
          <Grid.RowDefinitions>
              <RowDefinition Height="Auto" />
              <RowDefinition Height="Auto" />
              <RowDefinition />
          </Grid.RowDefinitions>
    
          <!-- Name -->
          <StackPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="0" Orientation="Horizontal">
              <Label Style="{StaticResource labelStyle}">Name:</Label>
              <Label Style="{StaticResource labelStyle}"></Label>
          </StackPanel>
    
          <!-- Department -->
          <StackPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="1" 
      Orientation="Horizontal">
              <Label Style="{StaticResource labelStyle}">Department:</Label>
              <Label Style="{StaticResource labelStyle}"></Label>
          </StackPanel>
    
          <Grid Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="2" VerticalAlignment="Top" 
                HorizontalAlignment="Left">
              <!-- Expense type and Amount table -->
              <DataGrid ColumnHeaderStyle="{StaticResource columnHeaderStyle}" 
                        AutoGenerateColumns="False" RowHeaderWidth="0" >
                  <DataGrid.Columns>
                      <DataGridTextColumn Header="ExpenseType" />
                      <DataGridTextColumn Header="Amount"  />
                  </DataGrid.Columns>
              </DataGrid>
          </Grid>
      </Grid>
    

    Este XAML agrega estilos a los elementos Label y Border.

  6. Compile y ejecute la aplicación. La apariencia de la ventana es la misma que antes.

    ExpenseIt sample screenshot with the same appearance as in the last section.

  7. Cierre la aplicación para volver a Visual Studio.

Enlazar datos a un control

En esta sección, va a crear los datos XML que se enlazan a diversos controles.

  1. En ExpenseItHome.xaml, después de abrir el elemento Grid, agregue el siguiente código XAML para crear un elemento XmlDataProvider que contenga los datos de cada persona:

    <Grid.Resources>
        <!-- Expense Report Data -->
        <XmlDataProvider x:Key="ExpenseDataSource" XPath="Expenses">
            <x:XData>
                <Expenses xmlns="">
                    <Person Name="Mike" Department="Legal">
                        <Expense ExpenseType="Lunch" ExpenseAmount="50" />
                        <Expense ExpenseType="Transportation" ExpenseAmount="50" />
                    </Person>
                    <Person Name="Lisa" Department="Marketing">
                        <Expense ExpenseType="Document printing"
              ExpenseAmount="50"/>
                        <Expense ExpenseType="Gift" ExpenseAmount="125" />
                    </Person>
                    <Person Name="John" Department="Engineering">
                        <Expense ExpenseType="Magazine subscription" 
             ExpenseAmount="50"/>
                        <Expense ExpenseType="New machine" ExpenseAmount="600" />
                        <Expense ExpenseType="Software" ExpenseAmount="500" />
                    </Person>
                    <Person Name="Mary" Department="Finance">
                        <Expense ExpenseType="Dinner" ExpenseAmount="100" />
                    </Person>
                </Expenses>
            </x:XData>
        </XmlDataProvider>
    </Grid.Resources>
    

    Los datos se crean como un recurso Grid. Normalmente estos datos se cargarían como archivo, pero se agregan en línea para simplificar.

  2. En el elemento<Grid.Resources>, agregue el elemento <xref:System.Windows.DataTemplate> siguiente, que define cómo mostrar los datos en ListBox, después del elemento <XmlDataProvider>:

    <Grid.Resources>
        <!-- Name item template -->
        <DataTemplate x:Key="nameItemTemplate">
            <Label Content="{Binding XPath=@Name}"/>
        </DataTemplate>
    </Grid.Resources>
    

    Para obtener más información sobre las plantillas de datos, consulte Información general sobre plantillas de datos.

  3. Reemplace el ListBox existente por el siguiente XAML:

    <ListBox Name="peopleListBox" Grid.Column="1" Grid.Row="2" 
             ItemsSource="{Binding Source={StaticResource ExpenseDataSource}, XPath=Person}"
             ItemTemplate="{StaticResource nameItemTemplate}">
    </ListBox>
    

    Este XAML enlaza la propiedad ItemsSource de ListBox al origen de datos y aplica la plantilla de datos como ItemTemplate.

Conectar datos a controles

A continuación, agregará código para recuperar el nombre seleccionado en la página ExpenseItHome y pasarlo al constructor de ExpenseReportPage. ExpenseReportPage establece el contexto de datos con el elemento pasado, que es a lo que los controles definidos en ExpenseReportPage.xaml se enlazarán.

  1. Abra ExpenseReportPage.xaml.vb o ExpenseReportPage.xaml.cs.

  2. Agregue un constructor que acepte un objeto, para que pueda pasar los datos del informe de gastos de la persona seleccionada.

    public partial class ExpenseReportPage : Page
    {
        public ExpenseReportPage()
        {
            InitializeComponent();
        }
    
        // Custom constructor to pass expense report data
        public ExpenseReportPage(object data):this()
        {
            // Bind to expense report data.
            this.DataContext = data;
        }
    }
    
    Partial Public Class ExpenseReportPage
        Inherits Page
        Public Sub New()
            InitializeComponent()
        End Sub
    
        ' Custom constructor to pass expense report data
        Public Sub New(ByVal data As Object)
            Me.New()
            ' Bind to expense report data.
            Me.DataContext = data
        End Sub
    
    End Class
    
  3. Abra ExpenseItHome.xaml.vb o ExpenseItHome.xaml.cs.

  4. Cambie el controlador de eventos Click para que llame al nuevo constructor y pase los datos del informe de gastos de la persona seleccionada.

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        // View Expense Report
        ExpenseReportPage expenseReportPage = new ExpenseReportPage(this.peopleListBox.SelectedItem);
        this.NavigationService.Navigate(expenseReportPage);
    }
    
    Private Sub Button_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
        ' View Expense Report
        Dim expenseReportPage As New ExpenseReportPage(Me.peopleListBox.SelectedItem)
        Me.NavigationService.Navigate(expenseReportPage)
    
    End Sub
    

Aplicar estilos a datos con plantillas de datos

En esta sección, va a actualizar la interfaz de usuario de cada elemento en las listas de datos enlazados mediante plantillas de datos.

  1. Abra el archivo ExpenseReportPage.xaml.

  2. Enlace el contenido de los elementos Label "Name" y "Department" a la propiedad de origen de datos adecuada. Para obtener más información sobre el enlace de datos, vea Información general sobre el enlace de datos.

    <!-- Name -->
    <StackPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="0" Orientation="Horizontal">
        <Label Style="{StaticResource labelStyle}">Name:</Label>
        <Label Style="{StaticResource labelStyle}" Content="{Binding XPath=@Name}"></Label>
    </StackPanel>
    
    <!-- Department -->
    <StackPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="1" Orientation="Horizontal">
        <Label Style="{StaticResource labelStyle}">Department:</Label>
        <Label Style="{StaticResource labelStyle}" Content="{Binding XPath=@Department}"></Label>
    </StackPanel>
    
  3. Después de abrir el elemento Grid, agregue las siguientes plantillas de datos, que definen cómo mostrar los datos del informe de gastos:

    <!--Templates to display expense report data-->
    <Grid.Resources>
        <!-- Reason item template -->
        <DataTemplate x:Key="typeItemTemplate">
            <Label Content="{Binding XPath=@ExpenseType}"/>
        </DataTemplate>
        <!-- Amount item template -->
        <DataTemplate x:Key="amountItemTemplate">
            <Label Content="{Binding XPath=@ExpenseAmount}"/>
        </DataTemplate>
    </Grid.Resources>
    
  4. Reemplace los elementos DataGridTextColumn con DataGridTemplateColumn por debajo del elemento DataGrid y aplíqueles las plantillas. Además, especifique el atributo ItemsSource con su valor en el elemento DataGrid.

    <!-- Expense type and Amount table -->
    <DataGrid ItemsSource="{Binding XPath=Expense}" ColumnHeaderStyle="{StaticResource columnHeaderStyle}" AutoGenerateColumns="False" RowHeaderWidth="0" >
       
        <DataGrid.Columns>
            <DataGridTemplateColumn Header="ExpenseType" CellTemplate="{StaticResource typeItemTemplate}" />
            <DataGridTemplateColumn Header="Amount" CellTemplate="{StaticResource amountItemTemplate}" />
        </DataGrid.Columns>
        
    </DataGrid>
    
  5. Compile y ejecute la aplicación.

  6. Seleccione una persona y luego seleccione el botón Ver.

La ilustración siguiente muestra ambas páginas de la aplicación ExpenseIt con los controles, el diseño, los estilos, el enlace de datos y las plantillas de datos aplicadas:

Both pages of the app showing the names list and an expense report.

Nota:

En este ejemplo se muestra una característica específica de WPF y no se siguen todos los procedimientos recomendados para aspectos como la seguridad, la localización y la accesibilidad. Para ver información completa sobre los procedimientos recomendados para el desarrollo de aplicaciones de WPF y .NET, consulte los temas siguientes:

Pasos siguientes

En este tutorial ha aprendido varias técnicas para crear una interfaz de usuario mediante Windows Presentation Foundation (WPF). Ya dispone de conocimientos básicos de los bloques de creación de aplicaciones de .NET enlazados a datos. Para más información sobre los modelos de programación y arquitectura de WPF, vea los temas siguientes:

Para más información sobre la creación de aplicaciones, vea los temas siguientes:

Vea también