Información general sobre las ventanas de WPF (WPF .NET)

Los usuarios interactúan con las aplicaciones Windows Presentation Foundation (WPF) por medio de ventanas. El propósito principal de una ventana es hospedar contenido que permita visualizar datos y que permita a los usuarios interactuar con estos. Las aplicaciones WPF proporcionan sus propias ventanas mediante la clase Window. En este artículo se presenta Window antes de describir los aspectos básicos de la creación y administración de ventanas en aplicaciones.

Importante

En este artículo se usa XAML generado a partir de un proyecto de C#. Si usa Visual Basic, es posible que el código XAML tenga un aspecto ligeramente diferente. Estas diferencias suelen estar presentes en los valores del atributo x:Class. C# incluye el espacio de nombres raíz del proyecto, mientras que Visual Basic no.

Las plantillas del proyecto para C# crean un tipo App incluido en el archivo app.xaml. En Visual Basic, el tipo se denomina Application y el archivo Application.xaml.

La clase Window

En WPF, una ventana está encapsulada por la clase Window que se usa para lo siguiente:

  • Mostrar una ventana.
  • Configurar el tamaño, posición y aspecto de una ventana.
  • Hospedar contenido específico de la aplicación.
  • Administrar la duración de una ventana.

En la figura siguiente se muestran los elementos que componen una ventana:

Captura de pantalla en la que se muestran los elementos de una ventana de WPF.

Una ventana se divide en dos áreas: el área distinta del cliente y el área cliente.

WPF implementa el área no cliente de una ventana e incluye los elementos que son comunes a la mayoría de las ventanas, incluidos los siguientes:

  • Barra de título (1-5).
  • Icono (1).
  • Título (2).
  • Botones Minimizar (3), Maximizar (4) y Cerrar (5).
  • Menú Sistema (6) con elementos de menú. Aparece al hacer clic en el icono (1).
  • Borde (7).

El área cliente de una ventana es el área dentro de su área no de cliente que utilizan los desarrolladores para agregar contenido específico de la aplicación, como barras de menús, barras de herramientas y controles.

  • Área cliente (8).
  • Control de cambio de tamaño (9). Es un control agregado al área cliente (8).

Implementar una ventana

La implementación de una ventana típica incluye apariencia y comportamiento, donde la apariencia define el aspecto de una ventana para los usuarios y el comportamiento la forma en que funciona una ventana cuando los usuarios interactúan con ella. En WPF, puede implementar la apariencia y el comportamiento de una ventana mediante código o marcado XAML.

Pero en general, la apariencia de una ventana se implementa mediante marcado XAML y su comportamiento se implementa mediante código subyacente, como se muestra en el ejemplo siguiente.

<Window x:Class="WindowsOverview.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WindowsOverview"
        >

    <!-- Client area containing the content of the window -->
    
</Window>

El código siguiente es el código subyacente para el marcado XAML.

using System.Windows;

namespace WindowsOverview
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }
    }
}
Public Class Window1

End Class

Para que un archivo de marcado XAML y uno de código subyacente funcionen de manera conjunta, se necesita lo siguiente:

  • En el marcado, el elemento Window debe incluir el atributo x:Class. Cuando se compila la aplicación, la existencia del atributo x:Class hace que el motor de compilación de Microsoft (MSBuild) genere una clase partial derivada de Window con el nombre especificado por el atributo x:Class. Para esto es necesario agregar una declaración de espacio de nombres XML para el esquema XAML (xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"). La clase partial generada implementa el método InitializeComponent, que se llama para registrar los eventos y establecer las propiedades que se implementan en el marcado.

  • En el código subyacente, la clase debe ser una instancia de partial con el mismo nombre especificado mediante el atributo x:Class en el marcado, y debe derivarse de Window. Esto permite que el archivo de código subyacente se asocie a la clase partial que se genera para el archivo de marcado al compilar la aplicación; para obtener más información, vea Compilación de una aplicación WPF.

  • En el código subyacente, la clase Window debe implementar un constructor que llame al método InitializeComponent. InitializeComponent se implementa mediante la clase partial generada por el archivo de marcado para registrar eventos y establecer las propiedades que se definen en el marcado.

Nota

Cuando se agrega una nueva instancia de Window al proyecto con Visual Studio, se implementa Windowmediante el marcado y el código subyacente, y se incluye la configuración necesaria para crear la asociación entre los archivos de marcado y código subyacente, como se describe aquí.

Después de agregar esta configuración, puede centrarse en definir el aspecto de la ventana en el marcado XAML e implementar su comportamiento en el código subyacente. En el ejemplo siguiente se muestra una ventana con un botón que define un controlador de eventos para el evento Click. Esto se implementa en XAML y el controlador en el código subyacente.

<Window x:Class="WindowsOverview.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WindowsOverview"
        >

    <!-- Client area containing the content of the window -->

    <Button Click="Button_Click">Click This Button</Button>
    
</Window>

El código siguiente es el código subyacente para el marcado XAML.

using System.Windows;

namespace WindowsOverview
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("Button was clicked.");
        }
    }
}
Public Class Window1

    Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
        MessageBox.Show("Button was clicked.")
    End Sub

End Class

Configuración de una ventana para MSBuild

La forma de implementar la ventana determina cómo se configura para MSBuild. Para una ventana que se define mediante marcado XAML y código subyacente:

  • Los archivos de marcado XAML se configuran como elementos Page de MSBuild.
  • Los archivos de código subyacente se configuran como elementos Compile de MSBuild.

Los proyectos del SDK de .NET importan automáticamente los elementos Page y Compile correctos, y no es necesario declararlos. Cuando el proyecto está configurado para WPF, los archivos de marcado XAML se importan automáticamente como elementos Page y el archivo de código subyacente correspondiente se importa como Compile.

Los proyectos de MSBuild no importarán automáticamente los tipos, que tendrá que declarar personalmente:

<Project>
    ...
    <Page Include="MarkupAndCodeBehindWindow.xaml" />
    <Compile Include=" MarkupAndCodeBehindWindow.xaml.cs" />
    ...
</Project>

Para obtener información sobre la compilación de aplicaciones WPF, vea Compilación de una aplicación WPF.

Vigencia de una ventana

Como sucede con cualquier clase, una ventana tiene una vigencia que comienza cuando se crea una instancia por primera vez y después se abre, se activa o desactiva, y finalmente se cierra.

Apertura de una ventana

Para abrir una ventana, primero hay que crear una instancia de ella, como se muestra en el ejemplo siguiente:

using System.Windows;

namespace WindowsOverview
{
    public partial class App : Application
    {
        private void Application_Startup(object sender, StartupEventArgs e)
        {
            // Create the window
            Window1 window = new Window1();

            // Open the window
            window.Show();
        }
    }
}
Class Application

    Private Sub Application_Startup(sender As Object, e As StartupEventArgs)
        ' Create the window
        Dim window As New Window1

        ' Open the window
        window.Show()
    End Sub

End Class

En este ejemplo, se crea la instancia de Window1 cuando se inicia la aplicación, lo que se produce cuando se genera el evento Startup. Para obtener más información sobre la ventana de inicio, vea Procedimiento para obtener o establecer la ventana de aplicación principal.

Cuando se crea una instancia de una ventana, de forma automática se agrega una referencia a ella a una lista de ventanas administrada por el objeto Application. La primera ventana de la que se va a crear una instancia la establece Application automáticamente como la ventana principal de la aplicación.

Por último, la ventana se abre mediante una llamada al método Show, como se muestra en la imagen siguiente:

Ventana de WPF con un solo botón en el interior.

Una ventana que se abre mediante una llamada a Show es una ventana sin modo y la aplicación no impide que los usuarios interactúen con otras ventanas de la aplicación. Al abrir una ventana con ShowDialog, se abre como ventana modal y la interacción del usuario se limita a esa ventana específica. Para obtener más información, vea Información general sobre cuadros de diálogo.

Cuando se llama a Show, una ventana realiza el trabajo de inicialización antes de mostrarse para establecer la infraestructura que le permite recibir entrada de usuario. Cuando la ventana se inicializa, se genera el evento SourceInitialized y se muestra la ventana.

Para obtener más información, vea Procedimiento para abrir una ventana o un cuadro de diálogo.

Ventana de inicio

En el ejemplo anterior se ha usado el evento Startup para ejecutar código que muestra la ventana inicial de la aplicación. Como acceso directo, use StartupUri en su lugar para especificar la ruta de acceso a un archivo XAML en la aplicación. La aplicación crea y muestra automáticamente la ventana especificada por esa propiedad.

<Application x:Class="WindowsOverview.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:WindowsOverview"
             StartupUri="ClippedWindow.xaml">
    <Application.Resources>
         
    </Application.Resources>
</Application>

Propiedad de la ventana

Una ventana que se abre mediante el método Show no tiene una relación implícita con la ventana que la ha creado. Los usuarios pueden interactuar de forma independiente con cualquiera de las ventanas, lo que significa que cualquiera de ellas puede hacer lo siguiente:

  • Superponerse a la otra (a menos que en una de las ventanas la propiedad Topmost esté establecida en true).
  • Minimizarse, maximizarse y restaurarse sin que afecte a las demás.

Algunas ventanas requieren una relación con la ventana que las abre. Por ejemplo, una aplicación de entorno de desarrollo integrado (IDE) puede abrir ventanas de propiedades y de herramientas cuyo comportamiento típico es superponerse sobre la ventana que las crea. Además, dichas ventanas se deben siempre cerrar, minimizar, maximizar y restaurar de acuerdo con la ventana que las creó. Este tipo de relación se puede establecer haciendo que una ventana posea otra, lo que se logra al establecer la propiedad Owner de la ventana poseída con una referencia a la ventana propietaria. Esto se muestra en el ejemplo siguiente.

private void Button_Click(object sender, RoutedEventArgs e)
{
    // Create a window and make the current window its owner
    var ownedWindow = new ChildWindow1();
    ownedWindow.Owner = this;
    ownedWindow.Show();
}
Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
    ' Create a window and make the current window its owner
    Dim ownedWindow As New ChildWindow1
    ownedWindow.Owner = Me
    ownedWindow.Show()
End Sub

Una vez establecida la propiedad:

  • La ventana poseída puede hacer referencia a la ventana propietaria mediante la inspección del valor de su propiedad Owner.
  • La ventana propietaria puede descubrir todas las ventanas que posee mediante la inspección del valor de su propiedad OwnedWindows.

Activación de ventanas

Cuando se abre una ventana por primera vez, se convierte en la ventana activa. La ventana activa es la que captura actualmente la entrada de usuario, como, por ejemplo, pulsaciones de teclas y clics del mouse. Cuando una ventana se convierte en la activa, genera el evento Activated.

Nota

Cuando se abre una ventana por primera vez, los eventos Loaded y ContentRendered solo se generan después de que se genere el evento Activated. Teniendo esto en cuenta, una ventana se puede considerar efectivamente abierta cuando se genera ContentRendered.

Después de que se activa una ventana, un usuario puede activar otra ventana de la misma aplicación o activar otra aplicación. Cuando esto ocurre, la ventana activa actualmente se desactiva y genera el evento Deactivated. Igualmente, cuando el usuario selecciona una ventana actualmente desactivada, la ventana se volverá a activar y se genera Activated.

Un motivo habitual de controlar Activated y Deactivated es para habilitar y deshabilitar funciones que solo se pueden ejecutar cuando una ventana está activa. Por ejemplo, algunas ventanas muestran contenido interactivo que requiere la entrada o atención del usuario constante, incluidos los reproductores de vídeo y los juegos. El ejemplo siguiente es un reproductor de vídeo simplificado que muestra cómo controlar Activated y Deactivated para implementar este comportamiento.

<Window x:Class="WindowsOverview.CustomMediaPlayerWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Activated="Window_Activated"
        Deactivated="Window_Deactivated"
        Title="CustomMediaPlayerWindow" Height="450" Width="800">
    <Grid>
        <MediaElement x:Name="mediaElement" Stretch="Fill"
                      LoadedBehavior="Manual" Source="numbers.mp4" />
    </Grid>
</Window>

El código siguiente es el código subyacente para el marcado XAML.

using System;
using System.Windows;

namespace WindowsOverview
{
    public partial class CustomMediaPlayerWindow : Window
    {
        public CustomMediaPlayerWindow() =>
            InitializeComponent();

        private void Window_Activated(object sender, EventArgs e)
        {
            // Continue playing media if window is activated
            mediaElement.Play();
        }

        private void Window_Deactivated(object sender, EventArgs e)
        {
            // Pause playing if media is being played and window is deactivated
            mediaElement.Pause();
        }
    }
}
Public Class CustomMediaPlayerWindow
    Private Sub Window_Activated(sender As Object, e As EventArgs)
        ' Continue playing media if window Is activated
        mediaElement.Play()
    End Sub

    Private Sub Window_Deactivated(sender As Object, e As EventArgs)
        ' Pause playing if media is being played and window is deactivated
        mediaElement.Pause()
    End Sub
End Class

Cuando se desactiva una ventana, otros tipos de aplicaciones pueden ejecutar código en segundo plano. Por ejemplo, un cliente de correo puede continuar sondeando el servidor de correo electrónico mientras el usuario está utilizando otras aplicaciones. Las aplicaciones como estas suelen ofrecer un comportamiento diferente o adicional mientras la ventana principal está desactivada. Para un programa de correo electrónico, esto puede significar agregar el nuevo elemento de correo a la bandeja de entrada, o bien un icono de notificación a la bandeja del sistema. Solo es necesario mostrar un icono de notificación cuando la ventana de correo electrónico no está activa, lo que se determina mediante la inspección de la propiedad IsActive.

Si se completa una tarea en segundo plano, es posible que una ventana quiera notificar al usuario de manera más urgente mediante una llamada al método Activate. Si el usuario interactúa con otra aplicación activada cuando se llama a Activate, el botón de la barra de tareas de la ventana parpadeará. Pero si un usuario interactúa con la aplicación actual, la llamada a Activate llevará la ventana al primer plano.

Nota:

Puede controlar la activación con ámbito de aplicación por medio de los eventos Application.Activated y Application.Deactivated.

Prevención de la activación de ventanas

Hay escenarios en los que las ventanas no se deben activar cuando se muestran, por ejemplo, las ventanas de conversación de una aplicación de chat o las de una aplicación de correo electrónico.

Si la aplicación tiene una ventana que no se debería activar cuando se muestra, puede establecer su propiedad ShowActivated en false antes de llamar al método Show por primera vez. Como resultado:

  • La ventana no se activa.
  • No se genera el evento Activated de la ventana.
  • La ventana actualmente activada permanece activada.

Sin embargo, la ventana se activará tan pronto como el usuario la active haciendo clic en el área de cliente o en el área distinta del cliente. En este caso:

  • La ventana se activa.
  • Se genera el evento Activated de la ventana.
  • La ventana activada previamente se desactiva.
  • Después, como respuesta a las acciones del usuario, se generan los eventos Deactivated y Activated de la ventana como se espera.

Cerrar una ventana

La vigencia de una ventana llega a su fin cuando un usuario la cierra. Una vez que se ha cerrado una ventana, no se puede volver a abrir. Se puede cerrar una ventana mediante elementos del área distinta del cliente, entre los que cabe incluir los siguientes:

  • El elemento Cerrar del menú Sistema.
  • Presionar ALT + F4.
  • Presionar el botón Cerrar.
  • Presionar ESC cuando un botón tiene la propiedad establecida IsCancel en true en una ventana modal.

Puede proporcionar mecanismos adicionales al área cliente para cerrar una ventana. Entre los más habituales se incluyen los siguientes:

  • Un elemento Salir en el menú Archivo, normalmente para las ventanas de la aplicación principal.
  • Un elemento Cerrar en el menú Archivo, normalmente para las ventanas de una aplicación secundaria.
  • Un botón Cancelar, normalmente en un cuadro de diálogo modal.
  • Un botón Cerrar, normalmente en un cuadro de diálogo sin modo.

Para cerrar una ventana en respuesta a uno de estos mecanismos personalizados, debe llamar al método Close. En el ejemplo siguiente se implementa la capacidad de cerrar una ventana mediante la elección del elemento Salir de un menú Archivo.

<Window x:Class="WindowsOverview.ClosingWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ClosingWindow" Height="450" Width="800">
    <StackPanel>
        <Menu>
            <MenuItem Header="_File">
                <MenuItem Header="E_xit" Click="fileExitMenuItem_Click" />
            </MenuItem>
        </Menu>
    </StackPanel>
</Window>

El código siguiente es el código subyacente para el marcado XAML.

using System.Windows;

namespace WindowsOverview
{
    public partial class ClosingWindow : Window
    {
        public ClosingWindow() =>
            InitializeComponent();

        private void fileExitMenuItem_Click(object sender, RoutedEventArgs e)
        {
            // Close the current window
            this.Close();
        }
    }
}
Public Class ClosingWindow
    Private Sub fileExitMenuItem_Click(sender As Object, e As RoutedEventArgs)
        ' Close the current window
        Me.Close()
    End Sub
End Class

Nota:

Se puede configurar una aplicación para que se cierre automáticamente cuando se cierra la ventana de la aplicación principal (vea MainWindow) o cuando se cierre la última ventana. Para obtener más información, vea ShutdownMode.

Aunque una ventana se puede cerrar de forma explícita mediante los mecanismos proporcionados en las áreas cliente y no cliente, también se puede cerrar de forma implícita como resultado de un comportamiento en otras partes de la aplicación o Windows, incluido lo siguiente:

Importante

No se puede volver a abrir una ventana cuando se ha cerrado.

Cancelación del cierre de la ventana

Cuando se cierra una ventana, genera dos eventos: Closing y Closed.

Closing se genera antes de que se cierre la ventana y proporciona un mecanismo por el que se puede impedir el cierre de la ventana. Una razón común para evitar el cierre de la ventana se produce en caso de que el contenido de la ventana contenga datos modificados. En esta situación, el evento Closing se puede controlar para determinar si los datos se han modificado y, en ese caso, preguntar al usuario si quiere continuar con el cierre de la ventana sin guardar los datos o cancelar el cierre. En el ejemplo siguiente se muestran los aspectos clave del control de Closing.

<Window x:Class="WindowsOverview.DataWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="DataWindow" Height="450" Width="800"
        Closing="Window_Closing">
    <Grid>
        <TextBox x:Name="documentTextBox" TextChanged="documentTextBox_TextChanged" />
    </Grid>
</Window>

El código siguiente es el código subyacente para el marcado XAML.

using System.Windows;
using System.Windows.Controls;

namespace WindowsOverview
{
    public partial class DataWindow : Window
    {
        private bool _isDataDirty;

        public DataWindow() =>
            InitializeComponent();

        private void documentTextBox_TextChanged(object sender, TextChangedEventArgs e) =>
            _isDataDirty = true;

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            // If data is dirty, prompt user and ask for a response
            if (_isDataDirty)
            {
                var result = MessageBox.Show("Document has changed. Close without saving?",
                                             "Question",
                                             MessageBoxButton.YesNo);

                // User doesn't want to close, cancel closure
                if (result == MessageBoxResult.No)
                    e.Cancel = true;
            }
        }
    }
}
Public Class DataWindow

    Private _isDataDirty As Boolean

    Private Sub documentTextBox_TextChanged(sender As Object, e As TextChangedEventArgs)
        _isDataDirty = True
    End Sub

    Private Sub Window_Closing(sender As Object, e As ComponentModel.CancelEventArgs)

        ' If data is dirty, prompt user and ask for a response
        If _isDataDirty Then
            Dim result = MessageBox.Show("Document has changed. Close without saving?",
                                         "Question",
                                         MessageBoxButton.YesNo)

            ' User doesn't want to close, cancel closure
            If result = MessageBoxResult.No Then
                e.Cancel = True
            End If
        End If

    End Sub
End Class

Al controlador de eventos Closing se le pasa un objeto CancelEventArgs, que implementa la propiedad Cancel establecida en true para evitar que se cierre una ventana.

Si no se controla Closing, o bien se controla, pero no se cancela, la ventana se cerrará. Justo antes de que se cierre una ventana, se genera Closed. En este momento, ya no se puede impedir el cierre de la ventana.

Eventos de vigencia de ventanas

En la ilustración siguiente se muestra la secuencia de eventos principales en la vigencia de una ventana:

Diagrama en el que se muestran los eventos de la vigencia de una ventana.

En la ilustración siguiente se muestra la secuencia de eventos principales de la vigencia de una ventana que aparece sin activación (ShowActivated se establece en false antes de mostrar la ventana):

Diagrama en el que se muestran los eventos de la vigencia de una ventana sin activación.

Ubicación de la ventana

Mientras una ventana está abierta, tiene una ubicación en las dimensiones x e y en relación con el escritorio. Esta ubicación se puede determinar mediante la inspección de las propiedades Left y Top, respectivamente. Establezca estas propiedades para cambiar la ubicación de la ventana.

También puede especificar la ubicación inicial de una instancia de Window cuando aparezca por primera vez si establece la propiedad WindowStartupLocation con uno de los valores siguientes de la enumeración WindowStartupLocation:

Si la ubicación de inicio se especifica como Manual, y las propiedades Left y Top no se han establecido, Window solicitará al sistema operativo una ubicación en la que mostrarse.

Ventanas de nivel superior y orden z

Además de tener una ubicación x e y, una ventana también tiene una ubicación en la dimensión z, que determina su posición vertical con respecto a otras ventanas. Esto se conoce como el orden z de la ventana y hay dos tipos: orden z normal y orden z superior. La ubicación de una ventana en el orden z normal depende de si está actualmente activa o no. De forma predeterminada, una ventana se encuentra en el orden z normal. La ubicación de una ventana en el orden z superior también depende de si está actualmente activa o no. Además, las ventanas del orden z superior siempre se encuentran por encima de aquellas del orden z normal. Una ventana se ubica en el orden z superior si se establece su propiedad Topmost en true.

Dentro de cada tipo de orden z, la ventana actualmente activa aparece encima de las demás ventanas del mismo orden z.

Tamaño de la ventana

Además de tener una ubicación en el escritorio, una ventana tiene un tamaño determinado por varias propiedades, entre las que se incluyen las diversas propiedades de ancho y alto, y SizeToContent.

MinWidth, Width y MaxWidth se usan para administrar el intervalo de anchos que puede tener una ventana durante su vigencia.

<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    MinWidth="300" Width="400" MaxWidth="500">
</Window>

El alto de la ventana se administra mediante MinHeight, Height y MaxHeight.

<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    MinHeight="300" Height="400" MaxHeight="500">
</Window>

Como los distintos valores de ancho y alto especifican un intervalo, es posible que el ancho y el alto de una ventana de tamaño ajustable se encuentre dentro del intervalo especificado para la dimensión correspondiente. Para detectar su ancho y alto actuales, inspeccione ActualWidth y ActualHeight, respectivamente.

Si prefiere que el ancho y el alto de la ventana tengan un tamaño que se ajuste al de su contenido, puede usar la propiedad SizeToContent, que tiene los valores siguientes:

En el ejemplo siguiente se muestra una ventana que se redimensiona automáticamente para ajustarse al contenido, tanto vertical como horizontalmente, cuando se muestra por primera vez.

<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    SizeToContent="WidthAndHeight">
</Window>

En el ejemplo siguiente se muestra cómo establecer la propiedad SizeToContent en el código para especificar cómo se cambia de tamaño una ventana para ajustarse al contenido.

// Manually alter window height and width
this.SizeToContent = SizeToContent.Manual;

// Automatically resize width relative to content
this.SizeToContent = SizeToContent.Width;

// Automatically resize height relative to content
this.SizeToContent = SizeToContent.Height;

// Automatically resize height and width relative to content
this.SizeToContent = SizeToContent.WidthAndHeight;
' Manually alter window height and width
Me.SizeToContent = SizeToContent.Manual

' Automatically resize width relative to content
Me.SizeToContent = SizeToContent.Width

' Automatically resize height relative to content
Me.SizeToContent = SizeToContent.Height

' Automatically resize height and width relative to content
Me.SizeToContent = SizeToContent.WidthAndHeight

Orden de prioridad de las propiedades de cambio de tamaño

Esencialmente, las diversas propiedades de tamaño de una ventana se combinan para definir el intervalo de anchura y altura de una ventana de tamaño ajustable. Para asegurarse de que se mantiene un intervalo válido, Window evalúa los valores de las propiedades de tamaño mediante los siguientes órdenes de prioridad.

Para las propiedades de altura:

  1. FrameworkElement.MinHeight
  2. FrameworkElement.MaxHeight
  3. SizeToContent.Height / SizeToContent.WidthAndHeight
  4. FrameworkElement.Height

Para las propiedades de anchura:

  1. FrameworkElement.MinWidth
  2. FrameworkElement.MaxWidth
  3. SizeToContent.Width / SizeToContent.WidthAndHeight
  4. FrameworkElement.Width

El orden de prioridad también puede determinar el tamaño de una ventana cuando se maximiza, lo que se puede administrar con la propiedad WindowState.

Window state

Durante la vigencia de una ventana de tamaño ajustable, esta puede tener tres estados: normal, minimizado y maximizado. Una ventana con un estado normal es el estado predeterminado. Una ventana con este estado permite al usuario moverla y cambiarla de tamaño mediante los controles de cambio de tamaño o el borde, si es de tamaño ajustable.

Una ventana con un estado minimizado se contrae a su botón de la barra de tareas si ShowInTaskbar se establece en true; de lo contrario, se contrae al tamaño más pequeño posible y se desplaza a la esquina inferior izquierda del escritorio. Ningún tipo de ventana minimizada puede cambiar de tamaño mediante el borde ni mediante los controles de cambio de tamaño, aunque si no aparece en la barra de tareas se podrá arrastrar a cualquier parte del escritorio.

Una ventana con un estado maximizado se expande hasta el tamaño máximo posible, en función del que determinen las propiedades MaxWidth, MaxHeight y SizeToContent. Al igual que una ventana minimizada, no se puede cambiar el tamaño de una ventana maximizada mediante un control de cambio de tamaño ni arrastrando el borde.

Nota:

Los valores de las propiedades Top, Left, Width y Height de una ventana siempre representan los valores para el estado normal, incluso cuando la ventana está maximizada o minimizada actualmente.

El estado de una ventana se puede configurar si se establece su propiedad WindowState, que puede tener uno de los valores siguientes de la enumeración WindowState:

En el ejemplo siguiente se muestra cómo crear una ventana que se muestra como maximizada cuando se abre.

<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    WindowState="Maximized">
</Window>

En general, debe establecer WindowState para configurar el estado inicial de una ventana. Cuando se muestra una ventana de tamaño ajustable, los usuarios pueden presionar los botones para minimizar, maximizar y restaurar situados en la barra de título de la ventana para cambiar su estado.

Aspecto de la ventana

Puede cambiar el aspecto del área cliente de una ventana mediante la adición de contenido específico, como botones, etiquetas y cuadros de texto. Para configurar el área no cliente, Window proporciona varias propiedades, entre las que se incluyen Icon para establecer el icono de una ventana y Title para establecer su título.

También puede cambiar el aspecto y comportamiento del borde del área distinta del cliente configurando el modo de cambio de tamaño de la ventana, el estilo de esta y si aparece como un botón en la barra de tareas del escritorio.

Modo de cambio de tamaño

En función de la propiedad WindowStyle, puede controlar si los usuarios cambian el tamaño de la ventana y cómo. El estilo de ventana afecta a lo siguiente:

  • Permitir o no permitir el cambio de tamaño arrastrando el borde de la ventana con el mouse.
  • Si los botones Minimizar, Maximizar y Cerrar aparecen en el área no cliente.
  • Si los botones Minimizar, Maximizar y Cerrar están habilitados.

Puede configurar cómo cambia el tamaño de una ventana si establece su propiedad ResizeMode, que puede ser uno de los valores siguientes de la enumeración ResizeMode:

Como sucede con WindowStyle, no es probable que el modo de cambio de tamaño de una ventana varíe durante su vigencia, lo que significa que probablemente lo establecerá desde el marcado XAML.

<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    ResizeMode="CanResizeWithGrip">
</Window>

Tenga en cuenta que puede inspeccionar la propiedad WindowState para detectar si una ventana está maximizada, minimizada o restaurada.

Window style

El borde que se expone desde el área distinta del cliente de una ventana es adecuado para la mayoría de las aplicaciones. Sin embargo, hay circunstancias donde se necesitan tipos diferentes de borde o no se necesita ningún borde en absoluto, dependiendo del tipo de ventana.

Para controlar qué tipo de borde obtiene una ventana, establezca su propiedad WindowStyle con uno de los valores siguientes de la enumeración WindowStyle:

El efecto de aplicar un estilo de ventana se muestra en la imagen siguiente:

Captura de pantalla en la que se muestra cómo afecta WindowStyle a una ventana en WPF.

Observe que en la imagen anterior no se muestra ninguna diferencia apreciable entre SingleBorderWindow y ThreeDBorderWindow. En Windows XP, ThreeDBorderWindow sí afectaba a cómo se dibujaba la ventana, y se agregaba un borde 3D al área cliente. A partir de Windows 7, las diferencias entre los dos estilos son mínimas.

Puede establecer WindowStyle mediante código o marcado XAML. Como es improbable que cambie durante la vigencia de una ventana, lo más probable es que la configure mediante marcado XAML.

<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    WindowStyle="ToolWindow">
</Window>

Estilo de ventana no rectangular

También hay situaciones en las que los estilos de borde que permite WindowStyle no son suficientes. Por ejemplo, es posible que quiera crear una aplicación con un borde no rectangular, similar a la del Reproductor de Windows Media de Microsoft.

Considere, por ejemplo, la ventana de globo que se muestra en la imagen siguiente:

Captura de pantalla de una ventana de WPF con un área recortada y una forma personalizada.

Este tipo de ventana se puede crear si se establece la propiedad WindowStyle en None y se usa la compatibilidad especial que tiene Window para la transparencia.

<Window x:Class="WindowsOverview.ClippedWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="ClippedWindow" SizeToContent="WidthAndHeight"
        WindowStyle="None" AllowsTransparency="True" Background="Transparent">
    <Grid Margin="20">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="20"/>
        </Grid.RowDefinitions>

        <Rectangle Stroke="#FF000000" RadiusX="10" RadiusY="10"/>
        <Path Fill="White" Stretch="Fill" Stroke="#FF000000" HorizontalAlignment="Left" Margin="15,-5.597,0,-0.003" Width="30" Grid.Row="1" Data="M22.166642,154.45381 L29.999666,187.66699 40.791059,154.54395"/>
        <Rectangle Fill="White" RadiusX="10" RadiusY="10" Margin="1"/>
        
        <TextBlock HorizontalAlignment="Left" VerticalAlignment="Center" FontSize="25" Text="Greetings!" TextWrapping="Wrap" Margin="5,5,50,5"/>
        <Button HorizontalAlignment="Right" VerticalAlignment="Top" Background="Transparent" BorderBrush="{x:Null}" Foreground="Red" Content="❌" FontSize="15" />

        <Grid.Effect>
            <DropShadowEffect BlurRadius="10" ShadowDepth="3" Color="LightBlue"/>
        </Grid.Effect>
    </Grid>
</Window>

Esta combinación de valores indica a la ventana que se represente de forma totalmente. En este estado, no se pueden usar los botones de adorno del área no cliente de la ventana y debe proporcionar los suyos propios.

Presencia de la barra de tareas

La apariencia predeterminada de una ventana incluye un botón de la barra de tareas. Algunos tipos de ventanas no tienen un botón de barra de tareas, como los cuadros de mensaje, los cuadros de diálogo o las ventanas con la propiedad WindowStyle establecida en ToolWindow. Puede controlar si se muestra el botón de barra de tareas de una ventana si establece la propiedad ShowInTaskbar, cuyo valor predeterminado es true.

<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    ShowInTaskbar="False">
</Window>

Otros tipos de ventanas

NavigationWindow es una ventana diseñada para hospedar contenido navegable.

Los cuadros de diálogo son ventanas que se suelen utilizar para recopilar información de un usuario para completar una función. Por ejemplo, cuando un usuario quiere abrir un archivo, una aplicación muestra el cuadro de diálogo Abrir archivo para obtener el nombre de archivo del usuario. Para obtener más información, vea Información general sobre cuadros de diálogo.

Consulte también