Información general sobre cuadros de diálogo

Las aplicaciones independientes tienen normalmente una ventana principal, que tanto muestra los datos principales sobre los que funciona la aplicación como expone la funcionalidad de procesamiento de datos a través de mecanismos de user interface (UI) tales como barras de menús, barras de herramientas y barras de estado. Una aplicación no trivial también puede mostrar ventanas adicionales para hacer lo siguiente:

  • Mostrar información específica a los usuarios

  • Recopilar información de los usuarios.

  • Tanto mostrar como recopilar información.

Estos tipos de ventanas se conocen como cuadros de diálogo y hay dos tipos: modales y no modales.

Los cuadros de diálogo modales los muestras las funciones cuando necesitan datos adicionales de los usuarios para continuar. Dado que la función depende del cuadro de diálogo modal para recopilar los datos, el cuadro de diálogo modal también impide que un usuario active otras ventanas de la aplicación mientras permanece abierto. En la mayoría de los casos, los cuadros de diálogo modales permiten a los usuarios señalar que han terminado con el cuadro de diálogo modal presionando un botón Aceptar o Cancelar. Al presionar el botón Aceptar se indica que el usuario ha introducido los datos y desea que la función continúe su proceso con esos datos. Presionar el botón Cancelar indica que el usuario desea detener la ejecución de la función. Los ejemplos más comunes de cuadros de diálogo modales se muestran para abrir, guardar e imprimir datos.

Un cuadro de diálogo no modal, por otra parte, no impide que el usuario active otras ventanas mientras está abierto. Por ejemplo, si un usuario desea buscar apariciones de una palabra determinada en un documento, una ventana principal abrirá habitualmente un cuadro de diálogo para preguntar al usuario qué palabra está buscando. Dado que la búsqueda de una palabra no impide que un usuario edite el documento, no obstante, no es necesario que el cuadro de diálogo sea modal. Un cuadro de diálogo no modal proporciona al menos un botón Cerrar para cerrar el cuadro de diálogo y puede proporcionar botones adicionales para ejecutar funciones concretas, como un botón Buscar siguiente para buscar la palabra siguiente que coincida con los criterios de una búsqueda de palabra.

Windows Presentation Foundation (WPF) permite crear varios tipos de cuadros de diálogo, incluidos cuadros de mensaje, cuadros de diálogo comunes y cuadros de diálogo personalizados. Este tema explica cada uno de ellos y Dialog Box Sample proporciona ejemplos relacionados.

Este tema contiene las secciones siguientes.

  • Cuadros de mensaje
  • Cuadros de diálogo comunes
  • Cuadros de diálogo personalizados
  • Temas relacionados

Cuadros de mensaje

Un cuadro de mensaje es un cuadro de diálogo que se puede utilizar para mostrar información textual y permitirles que los usuarios tomen decisiones con botones. La figura siguiente muestra un cuadro de mensaje que muestra información textual, hace una pregunta y proporciona al usuario tres botones para responder a la pregunta.

Cuadro de diálogo Procesador de textos

Para crear un cuadro de mensaje, utilice la clase MessageBox. MessageBox permite configurar el texto, el título, el icono y los botones del cuadro de mensaje, utilizando código como el siguiente.

' Configure the message box to be displayed
Dim messageBoxText As String = "Do you want to save changes?"
Dim caption As String = "Word Processor"
Dim button As MessageBoxButton = MessageBoxButton.YesNoCancel
Dim icon As MessageBoxImage = MessageBoxImage.Warning
// Configure the message box to be displayed
string messageBoxText = "Do you want to save changes?";
string caption = "Word Processor";
MessageBoxButton button = MessageBoxButton.YesNoCancel;
MessageBoxImage icon = MessageBoxImage.Warning;

Para mostrar un cuadro de mensaje, llame al método static Show, como se muestra en el código siguiente.

' Display message box
MessageBox.Show(messageBoxText, caption, button, icon)
// Display message box
MessageBox.Show(messageBoxText, caption, button, icon);

Cuando el código que muestra un cuadro de mensaje necesite detectar y procesar la decisión del usuario (qué botón se presionó), el código puede inspeccionar el resultado del cuadro de mensaje, como se muestra en el código siguiente.

' Display message box
Dim result As MessageBoxResult = MessageBox.Show(messageBoxText, caption, button, icon)

' Process message box results
Select Case result
    Case MessageBoxResult.Yes
        ' User pressed Yes button
        ' ...
    Case MessageBoxResult.No
        ' User pressed No button
        ' ...
    Case MessageBoxResult.Cancel
        ' User pressed Cancel button
        ' ...
End Select
// Display message box
MessageBoxResult result = MessageBox.Show(messageBoxText, caption, button, icon);

// Process message box results
switch (result)
{
    case MessageBoxResult.Yes:
        // User pressed Yes button
        // ...
        break;
    case MessageBoxResult.No:
        // User pressed No button
        // ...
        break;
    case MessageBoxResult.Cancel:
        // User pressed Cancel button
        // ...
        break;
}

Para obtener más información sobre cómo utilizar los cuadros de mensaje, vea MessageBox, MessageBox Sample y Dialog Box Sample.

Aunque MessageBox puede proporcionar una experiencia simple de usuario de cuadro de diálogo, la ventaja de utilizar MessageBox es que se trata del único tipo de ventana que pueden mostrar las aplicaciones que se ejecutan dentro de un recinto de seguridad confiable parcial (vea Seguridad (WPF)), tal como XAML browser applications (XBAPs).

La mayoría de los cuadros de diálogo muestran y recopilan datos más complejos que el resultado de un cuadro de mensaje, incluidos texto, selecciones (casillas), selecciones mutuamente excluyentes (botones de radio) y selecciones de lista (cuadros de lista, cuadros combinados, cuadros de lista desplegables). Para éstos, Windows Presentation Foundation (WPF) proporciona varios cuadros de diálogo comunes y permite crear cuadros de diálogo propios, aunque el uso de cualquiera de ellos se limita a aplicaciones que se ejecuten con plena confianza.

Cuadros de diálogo comunes

Windows implementa diversos cuadros de diálogo reutilizables que son comunes para todas las aplicaciones, incluidos cuadros de diálogo para abrir archivos, guardar archivos e imprimir. Puesto que es el sistema operativo el que implementa estos cuadros de diálogo, se pueden compartir entre todas las aplicaciones que se ejecutan en el sistema operativo, los que contribuye a la coherencia de la experiencia del usuario; cuando los usuarios están familiarizados con el uso de un cuadro de diálogo proporcionado por el sistema operativo en una aplicación, no necesitan obtener información sobre cómo utilizar ese cuadro de diálogo en otras aplicaciones. Dado que estos cuadros de diálogo están disponibles para todas las aplicaciones y que ayudan a proporcionar una experiencia de usuario coherente, se conocen como cuadros de diálogo comunes.

Windows Presentation Foundation (WPF) encapsula el archivo abierto, excepto el archivo, e imprime los cuadros de diálogo comunes y los expone como clases administradas para que los utilice en aplicaciones independientes. En este tema se proporciona una breve información general sobre:

La funcionalidad de apertura de archivos utiliza el cuadro de diálogo de apertura de archivos, que se muestra en la figura siguiente, para recuperar el nombre de un archivo a abrir.

Cuadro de diálogo Abrir

El cuadro de diálogo común de apertura de archivos se implementa como la clase OpenFileDialog y se encuentra en el espacio de nombres Microsoft.Win32. El código siguiente muestra cómo crear, configurar y mostrar uno, y cómo procesar el resultado.

' Configure open file dialog box
Dim dlg As New Microsoft.Win32.OpenFileDialog()
dlg.FileName = "Document" ' Default file name
dlg.DefaultExt = ".txt" ' Default file extension
dlg.Filter = "Text documents (.txt)|*.txt" ' Filter files by extension

' Show open file dialog box
Dim result? As Boolean = dlg.ShowDialog()

' Process open file dialog box results
If result = True Then
    ' Open document
    Dim filename As String = dlg.FileName
End If
// Configure open file dialog box
Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
dlg.FileName = "Document"; // Default file name
dlg.DefaultExt = ".txt"; // Default file extension
dlg.Filter = "Text documents (.txt)|*.txt"; // Filter files by extension

// Show open file dialog box
Nullable<bool> result = dlg.ShowDialog();

// Process open file dialog box results
if (result == true)
{
    // Open document
    string filename = dlg.FileName;
}

Para obtener más información sobre el cuadro de diálogo de apertura de archivos, vea Microsoft.Win32.OpenFileDialog.

NotaNota

OpenFileDialog se puede utilizar para recuperar sin ningún riesgo los nombres de archivo por aplicaciones que se ejecutan con confianza parcial (vea Seguridad (WPF)).

La funcionalidad de guardado de archivos utiliza el cuadro de diálogo de guardado de archivos, que se muestra en la figura siguiente, para recuperar el nombre de un archivo a guardar.

Cuadro de diálogo Guardar como

El cuadro de diálogo común de guardado de archivos se implementa como la clase SaveFileDialog y se encuentra en el espacio de nombres Microsoft.Win32. El código siguiente muestra cómo crear, configurar y mostrar uno, y cómo procesar el resultado.

' Configure save file dialog box
Dim dlg As New Microsoft.Win32.SaveFileDialog()
dlg.FileName = "Document" ' Default file name
dlg.DefaultExt = ".text" ' Default file extension
dlg.Filter = "Text documents (.txt)|*.txt" ' Filter files by extension

' Show save file dialog box
Dim result? As Boolean = dlg.ShowDialog()

' Process save file dialog box results
If result = True Then
    ' Save document
    Dim filename As String = dlg.FileName
End If
// Configure save file dialog box
Microsoft.Win32.SaveFileDialog dlg = new Microsoft.Win32.SaveFileDialog();
dlg.FileName = "Document"; // Default file name
dlg.DefaultExt = ".text"; // Default file extension
dlg.Filter = "Text documents (.txt)|*.txt"; // Filter files by extension

// Show save file dialog box
Nullable<bool> result = dlg.ShowDialog();

// Process save file dialog box results
if (result == true)
{
    // Save document
    string filename = dlg.FileName;
}

Para obtener más información sobre el cuadro de diálogo de guardado de archivos, vea Microsoft.Win32.SaveFileDialog.

La funcionalidad de impresión de archivos utiliza el cuadro de diálogo de impresión de archivos, que se muestra en la figura siguiente, para elegir y configurar la impresora en la que el usuario desea imprimir datos.

Cuadro de diálogo Imprimir

El cuadro de diálogo común de impresión de archivos se implementa como la clase PrintDialog y se encuentra en el espacio de nombres System.Windows.Controls. El código siguiente muestra cómo crear, configurar y mostrar uno.

' Configure printer dialog box
Dim dlg As New PrintDialog()
dlg.PageRangeSelection = PageRangeSelection.AllPages
dlg.UserPageRangeEnabled = True

' Show save file dialog box
Dim result? As Boolean = dlg.ShowDialog()

' Process save file dialog box results
If result = True Then
    ' Print document
End If
// Configure printer dialog box
System.Windows.Controls.PrintDialog dlg = new System.Windows.Controls.PrintDialog();
dlg.PageRangeSelection = PageRangeSelection.AllPages;
dlg.UserPageRangeEnabled = true;

// Show save file dialog box
Nullable<bool> result = dlg.ShowDialog();

// Process save file dialog box results
if (result == true)
{
    // Print document
}

Para obtener más información sobre el cuadro de diálogo de impresión de archivos, vea System.Windows.Controls.PrintDialog. Para ver una explicación detallada de la impresión en WPF, vea Información general sobre impresión.

Cuadros de diálogo personalizados

Aunque los cuadros de diálogo comunes son útiles, y se deben utilizar cuando sea posible, no satisfacen las necesidades de los cuadros de diálogo específicos de dominio. En estos casos, es necesario crear cuadros de diálogo propios. Como veremos, un cuadro de diálogo es una ventana con comportamientos especiales. Window implementa esos comportamientos y, por consiguiente, utiliza Window para crear cuadros de diálogo modales y no modales personalizados.

Crear un cuadro de diálogo personalizado modal

En este tema se muestra cómo utilizar Window para crear una implementación de un cuadro de diálogo modal típico, utilizando el cuadro de diálogo Margins como ejemplo (vea Dialog Box Sample). El cuadro de diálogo Margins se muestra en la figura siguiente.

Cuadro de diálogo Márgenes

Configurar un cuadro de diálogo modal

La interfaz de usuario de un cuadro de diálogo típico incluye lo siguiente:

  • Los diversos controles necesarios para recopilar los datos deseados.

  • Mostrar un botón Aceptar en el que los usuarios hacen clic para cerrar el cuadro de diálogo, volver a la función y continuar el proceso.

  • Mostrar un botón Cancelar en el que los usuarios hagan clic para cerrar el cuadro de diálogo y hacer que la función detenga el proceso.

  • Mostrar un botón Cerrar en la barra de título.

  • Mostrar un icono.

  • Mostrar botones Minimizar, Maximizary Restaurar.

  • Mostrar un menú Sistema para minimizar, maximizar, restaurar y cerrar el cuadro de diálogo.

  • Apertura encima y en el centro de la ventana que abrió el cuadro de diálogo.

  • Los cuadros de diálogo deben ser de tamaño variable cuando sea posible de modo que, para evitar que resulten ser demasiado pequeños y para proporcionar al usuario un tamaño predeterminado útil, deberá establecer tanto unas dimensiones predeterminadas como unas dimensiones mínimas.

  • Es recomendable configurar la acción de presionar la tecla ESC como un método abreviado de teclado que haga que se presione el botón Cancelar. Esto se logra estableciendo la propiedad IsCancel del botón Cancelar en true.

  • Es recomendable configurar la acción de presionar la tecla Entrar (o Retorno) como un método abreviado de teclado que provoca que se presione el botón Aceptar. Esto se logra estableciendo la propiedad IsDefault del botón Aceptar en true.

El código siguiente muestra esta configuración.


<Window 
    xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.MarginsDialogBox"
    xmlns:local="clr-namespace:SDKSample"
    Title="Margins"
    Height="190"
    Width="300"
    MinHeight="10"
    MinWidth="300"
    ResizeMode="CanResizeWithGrip"
    ShowInTaskbar="False"
    WindowStartupLocation="CenterOwner" 
    FocusManager.FocusedElement="{Binding ElementName=leftMarginTextBox}">

  <Grid>


...


    <!-- Accept or Cancel -->
    <StackPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="4">
      <Button Name="okButton" Click="okButton_Click" IsDefault="True">OK</Button>
      <Button Name="cancelButton" IsCancel="True">Cancel</Button>
    </StackPanel>

  </Grid >

</Window>
Imports System.Windows ' Window, RoutedEventArgs, IInputElement, DependencyObject
Imports System.Windows.Controls ' Validation
Imports System.Windows.Input ' Keyboard

Namespace SDKSample


Public Class MarginsDialogBox
    Inherits Window
    Public Sub New()
        Me.InitializeComponent()
    End Sub


...


End Class

End Namespace
using System.Windows; // Window, RoutedEventArgs, IInputElement, DependencyObject
using System.Windows.Controls; // Validation
using System.Windows.Input; // Keyboard

namespace SDKSample
{
    public partial class MarginsDialogBox : Window
    {
        public MarginsDialogBox()
        {
            InitializeComponent();
        }


...


    }
}

La experiencia del usuario en un cuadro de diálogo se extiende también a la barra de menús de la ventana que abre el cuadro de diálogo. Cuando un elemento de menú ejecuta una función que requiere interacción con el usuario a través de un cuadro de diálogo antes de que la función pueda continuar, el elemento de menú para la función tendrá puntos suspensivos en su encabezado, como se muestra aquí.

<!--Main Window-->


...


<MenuItem Name="formatMarginsMenuItem" Header="_Margins..." Click="formatMarginsMenuItem_Click" />

Cuando un elemento de menú ejecute una función que muestre un cuadro de diálogo que no requiera interacción con el usuario, como un cuadro de diálogo Acerca de, los puntos suspensivos no son necesarios.

Abrir un cuadro de diálogo modal

Un cuadro de diálogo se muestra normalmente como resultado de la selección de un elemento de menú, por parte de un usuario, para realizar una función específica del dominio, tal como establecer los márgenes de un documento en un procesador de textos. Mostrar una ventana como un cuadro de diálogo es similar a mostrar una ventana normal, aunque requiere la configuración adicional específica del cuadro de diálogo. El proceso completo de crear instancias, configurar y abrir un cuadro de diálogo se muestra en el código siguiente.


Imports System '  EventArgs
Imports System.ComponentModel '  CancelEventArgs
Imports System.Windows '  Window, MessageBoxXxx, RoutedEventArgs
Imports System.Windows.Controls '  TextChangedEventArgs
Imports Microsoft.Win32 '  OpenFileDialog

Namespace SDKSample

Public Class MainWindow
    Inherits Window


...


    Private Sub formatMarginsMenuItem_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
        ' Instantiate the dialog box
        Dim dlg As New MarginsDialogBox

        ' Configure the dialog box
        dlg.Owner = Me
        dlg.DocumentMargin = Me.documentTextBox.Margin

        ' Open the dialog box modally 
        dlg.ShowDialog()



...


End Sub


...


End Class

End Namespace
using System; // EventArgs
using System.ComponentModel; // CancelEventArgs
using System.Windows; // Window, MessageBoxXxx, RoutedEventArgs
using System.Windows.Controls; // TextChangedEventArgs
using Microsoft.Win32; // OpenFileDialog

namespace SDKSample
{
    public partial class MainWindow : Window
    {


...


        void formatMarginsMenuItem_Click(object sender, RoutedEventArgs e)
        {
            // Instantiate the dialog box
            MarginsDialogBox dlg = new MarginsDialogBox();

            // Configure the dialog box
            dlg.Owner = this;
            dlg.DocumentMargin = this.documentTextBox.Margin;

            // Open the dialog box modally 
            dlg.ShowDialog();



...


}


...


    }
}

Aquí, el código está pasando información predeterminada (los márgenes actuales) al cuadro de diálogo. También está estableciendo la propiedad Window.Owner con una referencia a la ventana que está mostrando el cuadro de diálogo. En general, siempre se debe establecer el propietario de un cuadro de diálogo para ofrecer comportamientos relacionados con el estado de la ventana que son comunes a todos los cuadros de diálogo (vea Información general sobre ventanas de WPF para obtener más información).

NotaNota

Para que sea posible la automatización user interface (UI) para cuadros de diálogo (vea Información general sobre UI Automation) debe proporcionar un propietario.

Una vez configurado el cuadro de diálogo, se mostrará modalmente llamando al método ShowDialog.

Validar datos proporcionados por el usuario

Cuando se abre un cuadro de diálogo y el usuario proporciona los datos necesarios, el cuadro de diálogo es responsable de asegurarse que los datos proporcionados sean válidos por las razones siguientes:

  • Desde la perspectiva de la seguridad, todas las entradas se deben validar.

  • Desde la perspectiva específica del dominio, la validación de datos impide que el código procese datos erróneos, lo que podría iniciar excepciones.

  • Desde la perspectiva de un usuario, un cuadro de diálogo puede ayudar a los usuarios mostrándoles qué datos de los introducidos no son válidos.

  • Desde la perspectiva del rendimiento, la validación de datos en una aplicación de varios niveles puede reducir el número de viajes de ida y vuelta entre los niveles de cliente y de aplicación, en particular cuando la aplicación se compone de servicios Web o bases de datos basadas en servidor.

Para validar un control enlazado en WPF, debe definir una regla de validación y asociarla al enlace. Una regla de validación es una clase personalizada derivada de ValidationRule. El ejemplo siguiente muestra una regla de validación, MarginValidationRule, que comprueba que un valor enlazado es Double y está dentro de un intervalo especificado.

Imports System.Globalization
Imports System.Windows.Controls

Namespace SDKSample

Public Class MarginValidationRule
    Inherits ValidationRule

    Private _maxMargin As Double
    Private _minMargin As Double

    Public Property MaxMargin() As Double
        Get
            Return Me._maxMargin
        End Get
        Set(ByVal value As Double)
            Me._maxMargin = value
        End Set
    End Property

    Public Property MinMargin() As Double
        Get
            Return Me._minMargin
        End Get
        Set(ByVal value As Double)
            Me._minMargin = value
        End Set
    End Property

    Public Overrides Function Validate(ByVal value As Object, ByVal cultureInfo As CultureInfo) As ValidationResult

        Dim margin As Double

        ' Is a number?
        If Not Double.TryParse(CStr(value), margin) Then
            Return New ValidationResult(False, "Not a number.")
        End If

        ' Is in range?
        If ((margin < Me.MinMargin) OrElse (margin > Me.MaxMargin)) Then
            Dim msg As String = String.Format("Margin must be between {0} and {1}.", Me.MinMargin, Me.MaxMargin)
            Return New ValidationResult(False, msg)
        End If

        ' Number is valid
        Return New ValidationResult(True, Nothing)

    End Function

End Class

End Namespace
using System.Globalization;
using System.Windows.Controls;

namespace SDKSample
{
    public class MarginValidationRule : ValidationRule
    {
        double minMargin;
        double maxMargin;

        public double MinMargin
        {
            get { return this.minMargin; }
            set { this.minMargin = value; }
        }

        public double MaxMargin
        {
            get { return this.maxMargin; }
            set { this.maxMargin = value; }
        }

        public override ValidationResult Validate(object value, CultureInfo cultureInfo)
        {
            double margin;

            // Is a number?
            if (!double.TryParse((string)value, out margin))
            {
                return new ValidationResult(false, "Not a number.");
            }

            // Is in range?
            if ((margin < this.minMargin) || (margin > this.maxMargin))
            {
                string msg = string.Format("Margin must be between {0} and {1}.", this.minMargin, this.maxMargin);
                return new ValidationResult(false, msg);
            }

            // Number is valid
            return new ValidationResult(true, null);
        }
    }
}

En este código, la lógica de validación de una regla de validación se implementa invalidando el método Validate, que valida los datos y devuelve el objeto ValidationResult correspondiente.

Para asociar la regla de validación al control enlazado, utilice el marcado siguiente.

<Window 
    xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.MarginsDialogBox"
    xmlns:local="clr-namespace:SDKSample"
    Title="Margins"
    Height="190"
    Width="300"
    MinHeight="10"
    MinWidth="300"
    ResizeMode="CanResizeWithGrip"
    ShowInTaskbar="False"
    WindowStartupLocation="CenterOwner" 
    FocusManager.FocusedElement="{Binding ElementName=leftMarginTextBox}">

  <Grid>
    


...


<Label Grid.Column="0" Grid.Row="0">Left Margin:</Label>
<TextBox Name="leftMarginTextBox" Grid.Column="1" Grid.Row="0">
  <TextBox.Text>
    <Binding Path="Left" UpdateSourceTrigger="PropertyChanged">
      <Binding.ValidationRules>
        <local:MarginValidationRule MinMargin="0" MaxMargin="10" />
      </Binding.ValidationRules>
    </Binding>
  </TextBox.Text>
</TextBox>


...


</Window>

Una vez asociada la regla de validación, WPF lo aplicará automáticamente cuando se introduzcan los datos en el control enlazado. Cuando un control contenga datos no válidos, WPF mostrará un borde rojo alrededor del control no válido, como se muestra en la figura siguiente.

Margen izquierdo no válido

WPF no restringe a un usuario al control no válido hasta que haya introducido datos válidos. Ésta es una buena práctica para un cuadro de diálogo; un usuario debe poder navegar libremente por los controles de un cuadro de diálogo tanto si los datos son válidos como si no. Sin embargo, esto significa que un usuario puede introducir datos no válidos y presionar el Aceptar botón. Por esta razón, el código necesita además validar todos los controles del cuadro de diálogo cuando se presione el botón Aceptar, controlando el evento Click.

Imports System.Windows ' Window, RoutedEventArgs, IInputElement, DependencyObject
Imports System.Windows.Controls ' Validation
Imports System.Windows.Input ' Keyboard

Namespace SDKSample


Public Class MarginsDialogBox
    Inherits Window


...


Private Sub okButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
    ' Don't accept the dialog box if there is invalid data
    If Not Me.IsValid(Me) Then Return


...


    End Sub

    ' Validate all dependency objects in a window
    Private Function IsValid(ByVal node As DependencyObject) As Boolean

        ' Check if dependency object was passed and if dependency object is valid.
        ' NOTE: Validation.GetHasError works for controls that have validation rules attached 
        If ((Not node Is Nothing) AndAlso Validation.GetHasError(node)) Then
            ' If the dependency object is invalid, and it can receive the focus,
            ' set the focus
            If TypeOf node Is IInputElement Then
                Keyboard.Focus(DirectCast(node, IInputElement))
            End If
            Return False
        End If

        ' If this dependency object is valid, check all child dependency objects
        Dim subnode As Object
        For Each subnode In LogicalTreeHelper.GetChildren(node)
            If (TypeOf subnode Is DependencyObject AndAlso Not Me.IsValid(DirectCast(subnode, DependencyObject))) Then
                ' If a child dependency object is invalid, return false immediately,
                ' otherwise keep checking
                Return False
            End If
        Next

        ' All dependency objects are valid
        Return True

    End Function

End Class

End Namespace
using System.Windows; // Window, RoutedEventArgs, IInputElement, DependencyObject
using System.Windows.Controls; // Validation
using System.Windows.Input; // Keyboard

namespace SDKSample
{
    public partial class MarginsDialogBox : Window
    {


...


void okButton_Click(object sender, RoutedEventArgs e)
{
    // Don't accept the dialog box if there is invalid data
    if (!IsValid(this)) return;


...


        }

        // Validate all dependency objects in a window
        bool IsValid(DependencyObject node)
        {
            // Check if dependency object was passed
            if (node != null)
            {
                // Check if dependency object is valid.
                // NOTE: Validation.GetHasError works for controls that have validation rules attached 
                bool isValid = !Validation.GetHasError(node);
                if (!isValid)
                {
                    // If the dependency object is invalid, and it can receive the focus,
                    // set the focus
                    if (node is IInputElement) Keyboard.Focus((IInputElement)node);
                    return false;
                }
            }

            // If this dependency object is valid, check all child dependency objects
            foreach (object subnode in LogicalTreeHelper.GetChildren(node))
            {
                if (subnode is DependencyObject)
                {   
                    // If a child dependency object is invalid, return false immediately,
                    // otherwise keep checking
                    if (IsValid((DependencyObject)subnode) == false) return false;
                }
            }

            // All dependency objects are valid
            return true;
        }
    }
}

Este código enumera todos los objetos de dependencia de una ventana y, si hay alguno que no es válido (si devuelve GetHasError, el control no válido obtiene el foco, el método IsValid devuelve false y la ventana se considera no válida.

Cuando un cuadro de diálogo es válido, se puede cerrar y devolver sin ningún riesgo. Como parte del proceso de retorno, debe devolver un resultado a la función que realiza la llamada.

Establecer el resultado del diálogo modal

Abrir un cuadro de diálogo mediante ShowDialog es fundamentalmente como llamar a un método: el código que abrió el cuadro de diálogo mediante ShowDialog espera hasta que vuelva ShowDialog. Cuando vuelve ShowDialog, el código que lo llamó debe decidir si continúa o detiene el procesamiento, según si el usuario presionó el botón Aceptar o el botón Cancelar. Para facilitar esta decisión, el cuadro de diálogo debe devolver la opción del usuario como un valor Boolean que se devuelve desde el método ShowDialog.

Cuando se hace clic en el botón Aceptar, ShowDialog debe devolver true. Esto se logra estableciendo la propiedad DialogResult del cuadro de diálogo al hacer clic en el botón Aceptar.

Tenga en cuenta que establecer la propiedad DialogResult también hace que la ventana se cierre automáticamente, los que elimina la necesidad de llamar explícitamente a Close.

Cuando se hace clic en el botón Cancelar, ShowDialog debe devolver false, que también requiere que se establezca la propiedad DialogResult.

Imports System.Windows ' Window, RoutedEventArgs, IInputElement, DependencyObject
Imports System.Windows.Controls ' Validation
Imports System.Windows.Input ' Keyboard

Namespace SDKSample


Public Class MarginsDialogBox
    Inherits Window


...


Private Sub cancelButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
    ' Dialog box canceled
    Me.DialogResult = False
End Sub


...


End Class

End Namespace
using System.Windows; // Window, RoutedEventArgs, IInputElement, DependencyObject
using System.Windows.Controls; // Validation
using System.Windows.Input; // Keyboard

namespace SDKSample
{
    public partial class MarginsDialogBox : Window
    {


...


void cancelButton_Click(object sender, RoutedEventArgs e)
{
    // Dialog box canceled
    this.DialogResult = false;
}


...


    }
}

Cuando la propiedad IsCancel de un botón se establece en true y el usuario presiona el botón Cancelar o la tecla ESC, DialogResult se establece automáticamente en false. El marcado siguiente tiene el mismo efecto que el código anterior, sin la necesidad de administrar el evento Click.

<Button Name="cancelButton" IsCancel="True">Cancel</Button>

Un cuadro de diálogo devuelve automáticamente false cuando un usuario presiona el botón Cerrar de la barra de título o elige el elemento de menú Cerrar en el menú Sistema.

Procesar datos devueltos desde un cuadro de diálogo modal

Cuando un cuadro de diálogo establece DialogResult, la función que lo abrió puede obtener el resultado del cuadro de diálogo inspeccionando la propiedad DialogResult cuando vuelve ShowDialog.


Imports System '  EventArgs
Imports System.ComponentModel '  CancelEventArgs
Imports System.Windows '  Window, MessageBoxXxx, RoutedEventArgs
Imports System.Windows.Controls '  TextChangedEventArgs
Imports Microsoft.Win32 '  OpenFileDialog

Namespace SDKSample

Public Class MainWindow
    Inherits Window


...


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


...


    ' Process data entered by user if dialog box is accepted
    If (dlg.DialogResult.GetValueOrDefault = True) Then
        Me.documentTextBox.Margin = dlg.DocumentMargin
    End If
End Sub


...


End Class

End Namespace
using System; // EventArgs
using System.ComponentModel; // CancelEventArgs
using System.Windows; // Window, MessageBoxXxx, RoutedEventArgs
using System.Windows.Controls; // TextChangedEventArgs
using Microsoft.Win32; // OpenFileDialog

namespace SDKSample
{
    public partial class MainWindow : Window
    {


...


void formatMarginsMenuItem_Click(object sender, RoutedEventArgs e)
{


...


    // Process data entered by user if dialog box is accepted
    if (dlg.DialogResult == true)
    {
        // Update fonts
        this.documentTextBox.Margin = dlg.DocumentMargin;
    }
}


...


    }
}

Si el resultado del diálogo es true, la función lo utiliza como indicación para recuperar y procesar los datos proporcionados por el usuario.

NotaNota

Una vez que vuelve ShowDialog, no se puede volver a abrir el cuadro de diálogo.En su lugar, debe crear una nueva instancia.

Si el resultado del diálogo es false, la función debe finalizar el procesamiento correctamente.

Crear un cuadro de diálogo personalizado no modal

Un cuadro de diálogo no modal, tal como el cuadro de diálogo Buscar que se muestra en la figura siguiente, tiene el mismo aspecto fundamental que un cuadro de diálogo modal.

Cuadro de diálogo Buscar

Sin embargo, su comportamiento es ligeramente diferente, como se describe en las secciones siguientes.

Abrir un cuadro de diálogo no modal

Un cuadro de diálogo no modal se abre llamando al método Show.

<!--Main Window-->

Imports System '  EventArgs
Imports System.ComponentModel '  CancelEventArgs
Imports System.Windows '  Window, MessageBoxXxx, RoutedEventArgs
Imports System.Windows.Controls '  TextChangedEventArgs
Imports Microsoft.Win32 '  OpenFileDialog

Namespace SDKSample

Public Class MainWindow
    Inherits Window


...


Private Sub editFindMenuItem_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
    Dim dlg As New FindDialogBox(Me.documentTextBox)
    dlg.Owner = Me
    AddHandler dlg.TextFound, New TextFoundEventHandler(AddressOf Me.dlg_TextFound)
    dlg.Show()
End Sub


...


End Class

End Namespace
using System; // EventArgs
using System.ComponentModel; // CancelEventArgs
using System.Windows; // Window, MessageBoxXxx, RoutedEventArgs
using System.Windows.Controls; // TextChangedEventArgs
using Microsoft.Win32; // OpenFileDialog

namespace SDKSample
{
    public partial class MainWindow : Window
    {


...


void editFindMenuItem_Click(object sender, RoutedEventArgs e)
{
    // Instantiate the dialog box
    FindDialogBox dlg = new FindDialogBox(this.documentTextBox);

    // Configure the dialog box
    dlg.Owner = this;
    dlg.TextFound += new TextFoundEventHandler(dlg_TextFound);

    // Open the dialog box modally
    dlg.Show();
}


...


    }
}

A diferencia de ShowDialog, Show vuelve inmediatamente. Por consiguiente, la ventana que realiza la llamada no puede distinguir cuándo se cierra el cuadro de diálogo no modal y, en consecuencia, no sabe cuándo comprobar los resultados del cuadro de diálogo o recibir los datos del cuadro de diálogo para continuar el procesamiento. En su lugar, el cuadro de diálogo debe crear una manera alternativa de devolver datos a la ventana que realiza la llamada para el procesamiento.

Procesar datos devueltos desde un cuadro de diálogo no modal

En este ejemplo, FindDialogBox puede devolver uno o más resultados de búsqueda a la ventana principal, según el texto que se esté buscando, sin ninguna frecuencia concreta. Como con un cuadro de diálogo modal, un cuadro de diálogo no modal puede devolver resultados mediante propiedades. Sin embargo, la ventana que posee el cuadro de diálogo necesita saber cuándo debe comprobar esas propiedades. Una manera de habilitar esto es que el cuadro de diálogo implemente un evento que se produzca siempre que se encuentre el texto. FindDialogBox implementa TextFoundEvent para este propósito, que requiere primero un delegado.

Namespace SDKSample
Public Delegate Sub TextFoundEventHandler(ByVal sender As Object, ByVal e As EventArgs)
End Namespace
using System;
namespace SDKSample
{
    public delegate void TextFoundEventHandler(object sender, EventArgs e);
}

Con el delegado TextFoundEventHandler, FindDialogBox implementa TextFoundEvent.

Imports System ' EventArgs
Imports System.Windows ' Window, MessageBoxXxx, RoutedEventArgs
Imports System.Windows.Controls ' TextBox, TextChangedEventArgs
Imports System.Text.RegularExpressions ' Regex

Namespace SDKSample

Public Class FindDialogBox
    Inherits Window
    Public Event TextFound As TextFoundEventHandler
    Protected Overridable Sub OnTextFound()
        RaiseEvent TextFound(Me, EventArgs.Empty)
    End Sub


...


End Class

End Namespace
using System; // EventArgs
using System.Windows; // Window, MessageBoxXxx, RoutedEventArgs
using System.Windows.Controls; // TextBox, TextChangedEventArgs
using System.Text.RegularExpressions; // Regex

namespace SDKSample
{
    public partial class FindDialogBox : Window
    {
        public event TextFoundEventHandler TextFound;
        protected virtual void OnTextFound()
        {
            TextFoundEventHandler textFound = this.TextFound;
            if (textFound != null) textFound(this, EventArgs.Empty);
        }


...


    }
}

Por consiguiente, Find puede provocar el evento cuando se encuentra un resultado de búsqueda.

Imports System ' EventArgs
Imports System.Windows ' Window, MessageBoxXxx, RoutedEventArgs
Imports System.Windows.Controls ' TextBox, TextChangedEventArgs
Imports System.Text.RegularExpressions ' Regex

Namespace SDKSample

Public Class FindDialogBox
    Inherits Window


...


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


...


Me.Index = match.Index
Me.Length = match.Length
RaiseEvent TextFound(Me, EventArgs.Empty)


...


End Sub


...


End Class

End Namespace
using System; // EventArgs
using System.Windows; // Window, MessageBoxXxx, RoutedEventArgs
using System.Windows.Controls; // TextBox, TextChangedEventArgs
using System.Text.RegularExpressions; // Regex

namespace SDKSample
{
    public partial class FindDialogBox : Window
    {


...


void findNextButton_Click(object sender, RoutedEventArgs e)
{


...


// Text found
this.index = match.Index;
this.length = match.Length;
OnTextFound();


...


}


...


    }
}

La ventana propietaria necesita entonces registrarse con este evento y administrarlo.


Imports System '  EventArgs
Imports System.ComponentModel '  CancelEventArgs
Imports System.Windows '  Window, MessageBoxXxx, RoutedEventArgs
Imports System.Windows.Controls '  TextChangedEventArgs
Imports Microsoft.Win32 '  OpenFileDialog

Namespace SDKSample

Public Class MainWindow
    Inherits Window


...


    Private Sub dlg_TextFound(ByVal sender As Object, ByVal e As EventArgs)
        Dim dlg As FindDialogBox = DirectCast(sender, FindDialogBox)
        Me.documentTextBox.Select(dlg.Index, dlg.Length)
        Me.documentTextBox.Focus()
    End Sub

End Class

End Namespace
using System; // EventArgs
using System.ComponentModel; // CancelEventArgs
using System.Windows; // Window, MessageBoxXxx, RoutedEventArgs
using System.Windows.Controls; // TextChangedEventArgs
using Microsoft.Win32; // OpenFileDialog

namespace SDKSample
{
    public partial class MainWindow : Window
    {


...


        void dlg_TextFound(object sender, EventArgs e)
        {
            // Get the find dialog box that raised the event
            FindDialogBox dlg = (FindDialogBox)sender;

            // Get find results and select found text
            this.documentTextBox.Select(dlg.Index, dlg.Length);
            this.documentTextBox.Focus();
        }
    }
}

Cerrar un cuadro de diálogo no modal

Dado que no es necesario establecer DialogResult, un diálogo no modal se puede cerrar utilizando los mecanismos proporcionados por el sistema, que incluyen los siguientes:

  • Hacer clic en el botón Cerrar en la barra de título.

  • Presionar ALT + F4.

  • Elegir Cerrar en el menú Sistema.

Como alternativa, el código puede llamar a Close cuando se haga clic en el botón Cerrar.

Imports System ' EventArgs
Imports System.Windows ' Window, MessageBoxXxx, RoutedEventArgs
Imports System.Windows.Controls ' TextBox, TextChangedEventArgs
Imports System.Text.RegularExpressions ' Regex

Namespace SDKSample

Public Class FindDialogBox
    Inherits Window


...


    Private Sub closeButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
        MyBase.Close()
    End Sub
End Class

End Namespace
using System; // EventArgs
using System.Windows; // Window, MessageBoxXxx, RoutedEventArgs
using System.Windows.Controls; // TextBox, TextChangedEventArgs
using System.Text.RegularExpressions; // Regex

namespace SDKSample
{
    public partial class FindDialogBox : Window
    {


...


        void closeButton_Click(object sender, RoutedEventArgs e)
        {
            // Close dialog box
            this.Close();
        }
    }
}

Vea también

Conceptos

Información general sobre el control Popup

Otros recursos

Dialog Box Sample

ColorPicker Custom Control Sample