Controles

Windows Presentation Foundation (WPF) se incluye con muchos de los componentes comunes de la interfaz de usuario que se usan en casi todas las aplicaciones de Windows, como Button, Label, TextBox, Menuy ListBox. Históricamente, estos objetos se han denominado controles. Aunque el SDK de WPF sigue usando el término "control" para significar de forma flexible cualquier clase que represente un objeto visible en una aplicación, es importante tener en cuenta que una clase no necesita heredar de la Control clase para tener una presencia visible. Las clases que heredan de la clase Control contienen un objeto ControlTemplate, lo que permite al consumidor de un control cambiar radicalmente el aspecto de este sin tener que crear una nueva subclase. En este tema, se describen los usos más comunes de los controles (tanto los que se heredan de la clase Control como los que no) en WPF.

Creación de una instancia de un control

Puedes agregar un control a una aplicación mediante el lenguaje de marcado extensible de aplicaciones (XAML) o el código. En el ejemplo siguiente se muestra cómo crear una aplicación simple que pide al usuario su nombre y su apellido. En este ejemplo se crean seis controles: dos etiquetas, dos cuadros de texto y dos botones, en XAML. Todos los controles se pueden crear de igual forma.

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

  <Label>
    Enter your first name:
  </Label>
  <TextBox Grid.Row="0" Grid.Column="1" 
           Name="firstName" Margin="0,5,10,5"/>

  <Label Grid.Row="1" >
    Enter your last name:
  </Label>
  <TextBox Grid.Row="1" Grid.Column="1" 
           Name="lastName" Margin="0,5,10,5"/>

  <Button Grid.Row="2" Grid.Column="0" 
          Name="submit" Margin="2">
    View message
  </Button>

  <Button Grid.Row="2" Grid.Column="1" 
          Name="Clear" Margin="2">
    Clear Name
  </Button>
</Grid>

En el ejemplo siguiente se crea la misma aplicación mediante código. Para acelerar el proceso, la creación de Grid, grid1, se ha excluido del ejemplo. grid1 tiene las mismas definiciones de columnas y filas que en el ejemplo de XAML anterior.

Label firstNameLabel;
Label lastNameLabel;
TextBox firstName;
TextBox lastName;
Button submit;
Button clear;

void CreateControls()
{
    firstNameLabel = new Label();
    firstNameLabel.Content = "Enter your first name:";
    grid1.Children.Add(firstNameLabel);

    firstName = new TextBox();
    firstName.Margin = new Thickness(0, 5, 10, 5);
    Grid.SetColumn(firstName, 1);
    grid1.Children.Add(firstName);

    lastNameLabel = new Label();
    lastNameLabel.Content = "Enter your last name:";
    Grid.SetRow(lastNameLabel, 1);
    grid1.Children.Add(lastNameLabel);

    lastName = new TextBox();
    lastName.Margin = new Thickness(0, 5, 10, 5);
    Grid.SetColumn(lastName, 1);
    Grid.SetRow(lastName, 1);
    grid1.Children.Add(lastName);

    submit = new Button();
    submit.Content = "View message";
    Grid.SetRow(submit, 2);
    grid1.Children.Add(submit);

    clear = new Button();
    clear.Content = "Clear Name";
    Grid.SetRow(clear, 2);
    Grid.SetColumn(clear, 1);
    grid1.Children.Add(clear);
}
Private firstNameLabel As Label
Private lastNameLabel As Label
Private firstName As TextBox
Private lastName As TextBox
Private submit As Button
Private clear As Button

Sub CreateControls()
    firstNameLabel = New Label()
    firstNameLabel.Content = "Enter your first name:"
    grid1.Children.Add(firstNameLabel)

    firstName = New TextBox()
    firstName.Margin = New Thickness(0, 5, 10, 5)
    Grid.SetColumn(firstName, 1)
    grid1.Children.Add(firstName)

    lastNameLabel = New Label()
    lastNameLabel.Content = "Enter your last name:"
    Grid.SetRow(lastNameLabel, 1)
    grid1.Children.Add(lastNameLabel)

    lastName = New TextBox()
    lastName.Margin = New Thickness(0, 5, 10, 5)
    Grid.SetColumn(lastName, 1)
    Grid.SetRow(lastName, 1)
    grid1.Children.Add(lastName)

    submit = New Button()
    submit.Content = "View message"
    Grid.SetRow(submit, 2)
    grid1.Children.Add(submit)

    clear = New Button()
    clear.Content = "Clear Name"
    Grid.SetRow(clear, 2)
    Grid.SetColumn(clear, 1)
    grid1.Children.Add(clear)


End Sub

Cambio de la apariencia de un control

Es común cambiar la apariencia de un control para ajustarlo a la apariencia de la aplicación. Puede cambiar la apariencia de un control mediante una de las acciones siguientes, dependiendo de lo que desea realizar:

  • Cambiar el valor de una propiedad del control.

  • Cree una clase Style para el control.

  • Cree una clase ControlTemplate nueva para el control.

Cambiar el valor de propiedad de un control

Muchos controles tienen propiedades que permiten cambiar el aspecto del control, como la propiedad Background de una clase Button. Puede establecer las propiedades del valor tanto en XAML como con código. En el ejemplo siguiente, se establecen las propiedades Background, FontSize y FontWeight de una clase Button en XAML.

<Button FontSize="14" FontWeight="Bold">
  <!--Set the Background property of the Button to
    a LinearGradientBrush.-->
  <Button.Background>
    <LinearGradientBrush StartPoint="0,0.5" 
                            EndPoint="1,0.5">
      <GradientStop Color="Green" Offset="0.0" />
      <GradientStop Color="White" Offset="0.9" />
    </LinearGradientBrush>

  </Button.Background>
  View message
</Button>

En el ejemplo siguiente se establecen las mismas propiedades mediante código.

LinearGradientBrush buttonBrush = new LinearGradientBrush();
buttonBrush.StartPoint = new Point(0, 0.5);
buttonBrush.EndPoint = new Point(1, 0.5);
buttonBrush.GradientStops.Add(new GradientStop(Colors.Green, 0));
buttonBrush.GradientStops.Add(new GradientStop(Colors.White, 0.9));

submit.Background = buttonBrush;
submit.FontSize = 14;
submit.FontWeight = FontWeights.Bold;
Dim buttonBrush As New LinearGradientBrush()
buttonBrush.StartPoint = New Point(0, 0.5)
buttonBrush.EndPoint = New Point(1, 0.5)
buttonBrush.GradientStops.Add(New GradientStop(Colors.Green, 0))
buttonBrush.GradientStops.Add(New GradientStop(Colors.White, 0.9))

submit.Background = buttonBrush
submit.FontSize = 14
submit.FontWeight = FontWeights.Bold

Crear un estilo para un control

WPF permite especificar la apariencia de los controles de manera global en lugar de establecer las propiedades en cada instancia de la aplicación; para ello, debe crearse una clase Style. En el ejemplo siguiente, se crea un objeto Style y se aplica a cada clase Button de la aplicación. Las definiciones de la clase Style suelen incluirse en XAML en la clase ResourceDictionary, como la propiedad Resources de la clase FrameworkElement.

<Style TargetType="Button">
  <Setter Property="FontSize" Value="14"/>
  <Setter Property="FontWeight" Value="Bold"/>
  <Setter Property="Background">
    <Setter.Value>
      <LinearGradientBrush StartPoint="0,0.5" 
                              EndPoint="1,0.5">
        <GradientStop Color="Green" Offset="0.0" />
        <GradientStop Color="White" Offset="0.9" />
      </LinearGradientBrush>

    </Setter.Value>
  </Setter>
</Style>

También puede aplicar un estilo solo a determinados controles de un tipo específico; para ello, asigne una clave al estilo y especifíquela en la propiedad Style del control. Para más información acerca de los estilos, consulte Aplicar estilos y plantillas.

Crear una plantilla de control

Style permite establecer las propiedades en varios controles a la vez, pero en ocasiones puede ser conveniente personalizar la apariencia de un objeto Control más allá de lo que se puede hacer creando una clase Style. Las clases que se heredan de la clase Control tienen una clase ControlTemplate, que define la estructura y la apariencia de una clase Control. La propiedad Template de una clase Control es pública, por lo que puede proporcionar a Control una clase ControlTemplate que sea distinta de la predeterminada. A menudo, puede especificar una nueva clase ControlTemplate para una clase Control en lugar de heredarse de un control para personalizar la apariencia de una clase Control.

Considere la posibilidad de usar Button, un control muy común. El comportamiento primario de una clase Button es permitir que una aplicación realice una acción cuando el usuario haga clic en ella. De forma predeterminada, la clase Button de WPF aparece como un rectángulo elevado. Al desarrollar una aplicación, es posible que quiera aprovechar el comportamiento de una clase Button, es decir, controlar el evento de hacer clic en el botón, pero que quiera cambiar el aspecto del botón más allá de lo que es posible cambiando sus propiedades. En este caso, puede crear una nueva clase ControlTemplate.

En el ejemplo siguiente, se crea una clase ControlTemplate para una clase Button. La clase ControlTemplate crea una clase Button con esquinas redondeadas y un fondo degradado. La clase ControlTemplate contiene una clase Border cuya propiedad Background es una clase LinearGradientBrush con dos objetos GradientStop. La primera clase GradientStop usa el enlace de datos para enlazar la propiedad Color de la clase GradientStop al color del fondo del botón. Al establecer la propiedad Background de la clase Button, el color del valor se usará como la primera clase GradientStop. Para más información sobre el enlace de datos, consulte Información general sobre el enlace de datos. En el ejemplo, también se crea una clase Trigger que cambia el aspecto de la clase Button cuando la propiedad IsPressed es true.

<!--Define a template that creates a gradient-colored button.-->
<Style TargetType="Button">
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="Button">
        <Border 
          x:Name="Border"  
          CornerRadius="20" 
          BorderThickness="1"
          BorderBrush="Black">
          <Border.Background>
            <LinearGradientBrush StartPoint="0,0.5" 
                                 EndPoint="1,0.5">
              <GradientStop Color="{Binding Background.Color, 
                    RelativeSource={RelativeSource TemplatedParent}}" 
                            Offset="0.0" />
              <GradientStop Color="White" Offset="0.9" />
            </LinearGradientBrush>
          </Border.Background>
          <ContentPresenter 
            Margin="2"
            HorizontalAlignment="Center"
            VerticalAlignment="Center"
            RecognizesAccessKey="True"/>
        </Border>
        <ControlTemplate.Triggers>
          <!--Change the appearance of
          the button when the user clicks it.-->
          <Trigger Property="IsPressed" Value="true">
            <Setter TargetName="Border" Property="Background">
              <Setter.Value>
                <LinearGradientBrush StartPoint="0,0.5" 
                                     EndPoint="1,0.5">
                  <GradientStop Color="{Binding Background.Color, 
                    RelativeSource={RelativeSource TemplatedParent}}" 
                                Offset="0.0" />
                  <GradientStop Color="DarkSlateGray" Offset="0.9" />
                </LinearGradientBrush>
              </Setter.Value>
            </Setter>
          </Trigger>

        </ControlTemplate.Triggers>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>
<Button Grid.Row="2" Grid.ColumnSpan="2" Name="submitName"
        Background="Green">View message</Button>

Nota:

La propiedad Background de la clase Button debe establecerse en SolidColorBrush para que el ejemplo funcione correctamente.

Suscripción a eventos

Puede suscribirse a un evento de un control mediante XAML o código, pero los eventos únicamente se pueden controlar mediante código. En el ejemplo siguiente, se muestra cómo suscribirse al evento Click de una clase Button.

<Button Grid.Row="2" Grid.ColumnSpan="2" Name="submitName" Click="submit_Click"
  Background="Green">View message</Button>
submit.Click += new RoutedEventHandler(submit_Click);
AddHandler submit.Click, AddressOf submit_Click

En el ejemplo siguiente, se controla el evento Click de una clase Button.

void submit_Click(object sender, RoutedEventArgs e)
{
    MessageBox.Show("Hello, " + firstName.Text + " " + lastName.Text);
}
Private Sub submit_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
    MessageBox.Show("Hello, " + firstName.Text + " " + lastName.Text)

End Sub

Contenido enriquecido en los controles

La mayoría de las clases que se heredan de la clase Control tienen la capacidad de incluir contenido enriquecido. Por ejemplo, una clase Label puede contener cualquier objeto, como una cadena, una clase Image o una clase Panel. Las clases siguientes proporcionan compatibilidad con el contenido enriquecido y actúan como clases base para la mayoría de los controles de WPF.

Para obtener más información sobre estas clases base, consulte Modelo de contenido de WPF.

Consulte también