Visão geral das caixas de diálogo

Os aplicativos autônomos geralmente têm uma janela principal que exibe os dados principais sobre os quais o aplicativo opera e expõe a funcionalidade para processar esses dados por meio de mecanismos de interface do usuário (UI), como barras de menu, barras de ferramentas e barras de status. Um aplicativo não trivial também pode exibir janelas adicionais para fazer o seguinte:

  • Exibir informações específicas aos usuários.

  • Coletar informações de usuários.

  • Exibir e coletar informações.

Esses tipos de janelas são conhecidos como caixas de diálogo, e há dois tipos: restrita e sem janela restrita.

Uma caixa de diálogo modal é exibida por uma função quando a função precisa de dados adicionais de um usuário para continuar. Como a função depende da caixa de diálogo modal para coletar dados, a caixa de diálogo modal também impede que um usuário ative outras janelas no aplicativo enquanto ele está aberto. Na maioria dos casos, uma caixa de diálogo modal permite que o usuário sinalize quando ele conclui as instruções da caixa de diálogo modal pressionando um botão OK ou Cancelar. Pressionar o botão OK indica que um usuário inseriu dados e deseja que a função continue o processamento com esses dados. Pressionar o botão Cancelar indica que um usuário deseja parar a execução completa da função. Os exemplos de caixas de diálogo modais mais comuns são mostrados para abrir, salvar e imprimir dados.

Por outro lado, uma caixa de diálogo sem janela restrita não impede que um usuário ative outras janelas enquanto ela está aberta. Por exemplo, se um usuário desejar localizar ocorrências de uma palavra específica em um documento, uma janela principal geralmente abrirá uma caixa de diálogo para solicitar a um usuário qual palavra ele está procurando. No entanto, como a localização de uma palavra não impede que um usuário edite o documento, a caixa de diálogo não precisa ser restrita. Uma caixa de diálogo sem janela restrita fornece, pelo menos, um botão Fechar para fechá-la e pode fornecer outros botões para executar funções específicas, como um botão Localizar Próxima para localizar a próxima palavra que corresponde aos critérios de localização de uma pesquisa de palavra.

Windows Presentation Foundation (WPF) permite que você crie vários tipos de caixas de diálogo, incluindo caixas de mensagem, caixas de diálogo comuns e caixas de diálogo personalizadas. Este tópico aborda cada uma delas e a Amostra de caixa de diálogo fornece as amostras correspondentes.

Caixas de mensagens

Uma caixa de mensagem é uma caixa de diálogo que pode ser usada para exibir informações textuais e permitir que os usuários tomem decisões com os botões. A figura a seguir mostra uma caixa de mensagem que exibe informações textuais, faz uma pergunta e fornece ao usuário três botões para responder à pergunta.

A Word Processor dialog box asking if you want to save the changes to the document before the application closes.

Para criar uma caixa de mensagem, use a MessageBox classe. MessageBox Permite configurar o texto, o título, o ícone e os botões da caixa de mensagem, usando um código como o seguinte.

// 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;
' 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

Para mostrar uma caixa de mensagem, chame o staticShow método, conforme demonstrado no código a seguir.

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

Quando o código que mostra uma caixa de mensagem precisa detectar e processar a decisão do usuário (qual botão foi pressionado), o código pode inspecionar o resultado da caixa de mensagem, conforme mostrado no código a seguir.

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

Para obter mais informações sobre como usar caixas de mensagem, consulte MessageBox, MessageBox Sample e Dialog Box Sample.

Embora MessageBox possa oferecer uma experiência de usuário de caixa de diálogo simples, a vantagem de usar MessageBox é que é o único tipo de janela que pode ser mostrado por aplicativos que são executados em uma área restrita de segurança de confiança parcial (consulte Segurança), como aplicativos de navegador XAML (XBAPs).

A maioria das caixas de diálogo exibe e coleta dados mais complexos que o resultado de uma caixa de mensagem, incluindo texto, seleção (caixas de seleção), seleção mutuamente exclusiva (botões de opção) e seleção de lista (caixas de listagem, caixas de combinação, caixas de listagem suspensas). Para estes, o Windows Presentation Foundation (WPF) fornece várias caixas de diálogo comuns e permite que você crie suas próprias caixas de diálogo, embora o uso de qualquer uma delas seja limitado a aplicativos executados com confiança total.

Caixas de diálogo comuns

O Windows implementa uma variedade de caixas de diálogo reutilizáveis que são comuns a todos os aplicativos, incluindo caixas de diálogo para abrir arquivos, salvar arquivos e imprimir. Como essas caixas de diálogo são implementadas pelo sistema operacional, elas podem ser compartilhadas entre todos os aplicativos executados no sistema operacional, o que ajuda na consistência da experiência do usuário. Quando os usuários estiverem familiarizados com o uso de uma caixa de diálogo fornecida pelo sistema operacional em um aplicativo, eles não precisarão aprender a usar a caixa de diálogo em outros aplicativos. Devido a essas caixas de diálogo estarem disponíveis para todos os aplicativos e ajudarem a fornecer uma experiência do usuário consistente, elas são conhecidas como caixas de diálogo comuns.

O Windows Presentation Foundation (WPF) encapsula o arquivo aberto, o arquivo de salvamento e a impressão de caixas de diálogo comuns e as expõe como classes gerenciadas para você usar em aplicativos autônomos. Este tópico fornece uma visão geral breve de cada uma delas.

Caixa de diálogo Abrir arquivo

A caixa de diálogo Abrir Arquivo, mostrada na figura a seguir, é usada pela funcionalidade de abertura de arquivo para recuperar o nome de um arquivo a ser aberto.

An Open dialog box showing the location to retrieve the file.

A caixa de diálogo de arquivo aberto comum é implementada como a OpenFileDialog classe e está localizada no Microsoft.Win32 namespace. O código a seguir mostra como criar, configurar e mostrar uma e como processar o resultado.

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

Para obter mais informações sobre a caixa de diálogo Abrir arquivo, consulte Microsoft.Win32.OpenFileDialog.

Observação

OpenFileDialog pode ser usado para recuperar nomes de arquivos com segurança por aplicativos executados com confiança parcial (consulte Segurança).

caixa de diálogo Salvar Arquivo

A caixa de diálogo Salvar Arquivo, mostrada na figura a seguir, é usada pela funcionalidade de salvamento de arquivo para recuperar o nome de um arquivo a ser salvo.

A Save As dialog box showing the location to save the file.

A caixa de diálogo comum salvar arquivo é implementada como a SaveFileDialog classe e está localizada no Microsoft.Win32 namespace. O código a seguir mostra como criar, configurar e mostrar uma e como processar o resultado.

// Configure save file dialog box
Microsoft.Win32.SaveFileDialog dlg = new Microsoft.Win32.SaveFileDialog();
dlg.FileName = "Document"; // Default file name
dlg.DefaultExt = ".txt"; // 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;
}
' Configure save file dialog box
Dim dlg As New Microsoft.Win32.SaveFileDialog()
dlg.FileName = "Document" ' Default file name
dlg.DefaultExt = ".txt" ' 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

Para obter mais informações sobre a caixa de diálogo Salvar arquivo, consulte Microsoft.Win32.SaveFileDialog.

A caixa de diálogo Imprimir, mostrada na figura a seguir, é usada pela funcionalidade de impressão para escolher e configurar a impressora na qual um usuário deseja imprimir os dados.

Screenshot that shows a Print dialog box.

A caixa de diálogo de impressão comum é implementada como a PrintDialog classe e está localizada no System.Windows.Controls namespace. O código a seguir mostra como criar, configurar e mostrar uma.

// 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
}
' 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

Para obter mais informações sobre a caixa de diálogo de impressão, consulte System.Windows.Controls.PrintDialog. Para obter uma discussão detalhada sobre a impressão no WPF, consulte Visão geral da impressão.

Caixas de diálogo personalizadas

Embora as caixas de diálogo comuns sejam úteis e devam ser usadas quando possível, elas não dão suporte aos requisitos de caixas de diálogo específicas ao domínio. Nesses casos, você precisa criar suas próprias caixas de diálogo. Como veremos, uma caixa de diálogo é uma janela com comportamentos especiais. Window implementa esses comportamentos e, consequentemente, você usa Window para criar caixas de diálogo modais e sem moderação personalizadas.

Criando uma caixa de diálogo personalizada modal

Este tópico mostra como usar Window para criar uma implementação de caixa de diálogo modal típica, usando a Margins caixa de diálogo como exemplo (consulte Exemplo de caixa de diálogo). A Margins caixa de diálogo é mostrada na figura a seguir.

A Margins dialog box with fields to define left margin, top margin, right margin, and bottom margin.

Configurando uma caixa de diálogo modal

A interface do usuário de uma caixa de diálogo típica inclui o seguinte:

  • Os vários controles que são necessários para coletar os dados desejados.

  • Um botão OK no qual os usuários clicam para fechar a caixa de diálogo, retornar à função e continuar o processamento.

  • Um botão Cancelar no qual os usuários clicam para fechar a caixa de diálogo e interromper o processamento da função.

  • Um botão Fechar na barra de título.

  • Um ícone.

  • Botões Minimizar, Maximizar e Restaurar.

  • Um menu Sistema para minimizar, maximizar, restaurar e fechar a caixa de diálogo.

  • Uma posição acima e no centro da janela que abriu a caixa de diálogo.

  • A capacidade de ser redimensionado sempre que possível para evitar que a caixa de diálogo seja muito pequena e para fornecer ao usuário um tamanho padrão útil. Isso requer que você defina as dimensões padrão e mínima.

  • A tecla ESC como um atalho de teclado que faz com que o botão Cancelar seja pressionado. Para fazer isso, defina a IsCancelpropriedade do botão Cancelar como true.

  • A tecla ENTER (ou RETURN) como um atalho de teclado que faz com que o botão OK seja pressionado. Para fazer isso, defina a IsDefaultpropriedade do botão trueOK .

O código a seguir demonstra essa configuração.

<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://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>
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace SDKSample
{
    public partial class MarginsDialogBox : Window
    {
        public MarginsDialogBox()
        {
            InitializeComponent();
        }
    }
}
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Input

Namespace SDKSample
    Public Class MarginsDialogBox
        Inherits Window

        Public Sub New()
            Me.InitializeComponent()
        End Sub
    End Class
End Namespace

A experiência do usuário em uma caixa de diálogo também se estende à barra de menus da janela que abre a caixa de diálogo. Quando um item de menu executar uma função que exige a interação do usuário por meio de uma caixa de diálogo antes que a função possa continuar, o item de menu da função terá reticências em seu cabeçalho, conforme mostrado aqui.

<!--Main Window-->
<MenuItem Name="formatMarginsMenuItem" Header="_Margins..." Click="formatMarginsMenuItem_Click" />

Quando um item de menu executar uma função que exibe uma caixa de diálogo que não exige a interação do usuário, como uma caixa de diálogo Sobre, as reticências não serão necessárias.

Abrindo uma caixa de diálogo modal

Normalmente, uma caixa de diálogo é mostrada como resultado da seleção por um usuário de um item de menu para executar uma função específica ao domínio, como definição das margens de um documento em um processador de texto. A exibição de uma janela como uma caixa de diálogo é semelhante à exibição de uma janela normal, embora ela exija uma configuração adicional específica à caixa de diálogo. O processo completo de criar uma instância, configurar e abrir uma caixa de diálogo é mostrado no código a seguir.

using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Win32;

namespace SDKSample
{
    public partial class MainWindow : Window
    {
        bool needsToBeSaved;
        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();
        }
    }
}
Imports System.ComponentModel
Imports System.Windows
Imports System.Windows.Controls
Imports Microsoft.Win32

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

Aqui, o código passa informações padrão (as margens atuais) para a caixa de diálogo. Ele também define a propriedade com uma referência à janela que está mostrando a Window.Owner caixa de diálogo. Em geral, você deve sempre definir o proprietário de uma caixa de diálogo para fornecer comportamentos relacionados ao estado da janela que são comuns a todas as caixas de diálogo (consulte Visão geral das janelas do WPF para obter mais informações).

Observação

Você deve fornecer um proprietário para oferecer suporte à automação da interface do usuário (UI) para caixas de diálogo (consulte Visão geral da automação da interface do usuário).

Depois que a caixa de diálogo é configurada, ela é mostrada modalmente chamando o ShowDialog método.

Validando dados fornecidos pelo usuário

Quando uma caixa de diálogo é aberta e o usuário fornece os dados necessários, uma caixa de diálogo é responsável por garantir que os dados fornecidos são válidos pelos seguintes motivos:

  • De uma perspectiva de segurança, todas as informações devem ser validadas.

  • De uma perspectiva específica ao domínio, a validação de dados impede que dados incorretos sejam processados pelo código, o que potencialmente poderá gerar exceções.

  • De uma perspectiva da experiência do usuário, uma caixa de diálogo pode ajudar os usuários mostrando-lhes quais dados inseridos são inválidos.

  • De uma perspectiva do desempenho, a validação de dados em um aplicativo de várias camadas pode reduzir o número de viagens de ida e volta entre o cliente e as camadas do aplicativo, especialmente, quando o aplicativo é composto por serviços Web ou bancos de dados baseados em servidor.

Para validar um controle acoplado no WPF, você precisa definir uma regra de validação e associá-la à associação. Uma regra de validação é uma classe personalizada que deriva de ValidationRule. O exemplo a seguir mostra uma regra de validação, MarginValidationRule, que verifica se um valor vinculado é a Double e está dentro de um intervalo especificado.

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

Nesse código, a lógica de validação de uma regra de validação é implementada substituindo o Validate método, que valida os dados e retorna um ValidationResultarquivo .

Para associar a regra de validação ao controle associado, use a marcação a seguir.

<Window 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://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>

    <!-- Left Margin -->
    <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>
  </Grid >
</Window>

Depois que a regra de validação for associada, o WPF a aplicará automaticamente quando os dados forem inseridos no controle vinculado. Quando um controle contém dados inválidos, o WPF exibirá uma borda vermelha ao redor do controle inválido, conforme mostrado na figura a seguir.

A Margins dialog box with a red border around the invalid left margin value.

WPF não restringe um usuário ao controle inválido até que eles tenham inserido dados válidos. Esse é bom comportamento para uma caixa de diálogo; um usuário poderá navegar livremente pelos controles em uma caixa de diálogo, independentemente de os dados serem válidos ou não. No entanto, isso significa que um usuário pode inserir dados inválidos e pressionar o botão OK. Por esse motivo, seu código também precisa validar todos os controles em uma caixa de diálogo quando o botão OK é pressionado manipulando o Click evento.

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

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;
        }
    }
}
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Input

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

Esse código enumera todos os objetos de dependência em uma janela e, se algum for inválido (conforme retornado pelo GetHasError, o controle inválido obtém o foco, o IsValid método retorna falsee a janela é considerada inválida.

Depois que uma caixa de diálogo for válida, ela pode ser fechada e retornada com segurança. Como parte do processo de retorno, ela precisa retornar um resultado para a função de chamada.

Definindo o resultado da caixa de diálogo modal

Abrir uma caixa de diálogo usando é fundamentalmente como chamar um método: o código que abriu a caixa de diálogo usando ShowDialogShowDialog espera até ShowDialog que retorne. Quando ShowDialog retorna, o código que o chamou precisa decidir se deseja continuar o processamento ou parar o processamento, com base no fato de o usuário ter pressionado o botão OK ou o botão Cancelar. Para facilitar essa decisão, a caixa de diálogo precisa retornar a escolha do usuário como um Boolean valor retornado do ShowDialog método.

Quando o botão OK é clicado, ShowDialog deve retornar true. Isso é obtido definindo a DialogResult propriedade da caixa de diálogo quando o botão OK é clicado.

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

namespace SDKSample
{
    public partial class MarginsDialogBox : Window
    {

        void okButton_Click(object sender, RoutedEventArgs e)
        {
            this.DialogResult = true;
        }
    }
}
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Input

Namespace SDKSample
    Public Class MarginsDialogBox
        Inherits Window

        Private Sub okButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
            ' Dialog box accepted
            MyBase.DialogResult = New Nullable(Of Boolean)(True)
        End Sub
    End Class
End Namespace

Observe que a configuração da DialogResult propriedade também faz com que a janela seja fechada automaticamente, o que alivia a necessidade de chamar Closeexplicitamente .

Quando o botão Cancelar é clicado, deve retornar false, ShowDialog o que também requer a configuração da DialogResult propriedade.

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

namespace SDKSample
{
    public partial class MarginsDialogBox : Window
    {

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

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

Quando a propriedade de IsCancel um botão é definida como e o usuário pressiona o botão Cancelar ou a tecla ESC, DialogResult é definida automaticamente como truefalse. A marcação a seguir tem o mesmo efeito que o código anterior, sem a necessidade de manipular o Click evento.

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

Uma caixa de diálogo retorna false automaticamente quando um usuário pressiona o botão Fechar na barra de título ou escolhe o item de menu Fechar no menu Sistema.

Processando dados retornados de uma caixa de diálogo modal

Quando DialogResult é definido por uma caixa de diálogo, a função que a abriu pode obter o resultado da caixa de diálogo inspecionando a DialogResult propriedade quando ShowDialog retorna.

using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Win32;

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;
            }
        }
    }
}
Imports System.ComponentModel
Imports System.Windows
Imports System.Windows.Controls
Imports Microsoft.Win32

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

Se o resultado da caixa de diálogo for true, a função usará isso como uma indicação para recuperar e processar os dados fornecidos pelo usuário.

Observação

Depois ShowDialog de retornar, uma caixa de diálogo não pode ser reaberta. Em vez disso, você precisa criar uma nova instância.

Se o resultado da caixa de diálogo for false, a função deverá encerrar o processamento de forma adequada.

Criando uma caixa de diálogo personalizada sem janela restrita

Uma caixa de diálogo sem janela restrita, como a Caixa de Diálogo Localizar mostrada na figura a seguir, tem a mesma aparência básica que a caixa de diálogo modal.

Screenshot that shows a Find dialog box.

No entanto, o comportamento é ligeiramente diferente, conforme descrito nas próximas seções.

Abrindo uma caixa de diálogo sem janela restrita

Uma caixa de diálogo sem janela restrita é aberta chamando o Show método.

<!--Main Window-->
<MenuItem Name="editFindMenuItem" Header="_Find" InputGestureText="Ctrl+F" Click="editFindMenuItem_Click" />
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Win32;

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();
        }
    }
}
Imports System.ComponentModel
Imports System.Windows
Imports System.Windows.Controls
Imports Microsoft.Win32

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

Ao contrário ShowDialogdo , Show retorna imediatamente. Consequentemente, a janela de chamada não pode saber quando a caixa de diálogo sem janela restrita é fechada e, portanto, não sabe quando procurar um resultado da caixa de diálogo nem quando obter dados da caixa de diálogo para processamento adicional. Em vez disso, a caixa de diálogo precisa criar uma maneira alternativa de retornar dados para a janela de chamada para o processamento.

Processando dados retornados de uma caixa de diálogo sem janela restrita

Neste exemplo, o FindDialogBox pode retornar um ou mais resultados de localização para a janela principal, dependendo do texto que está sendo pesquisado sem qualquer frequência específica. Assim como ocorre com uma caixa de diálogo modal, uma caixa de diálogo sem janela restrita pode retornar resultados usando propriedades. No entanto, a janela que possui a caixa de diálogo precisa saber quando deve verificar essas propriedades. Uma maneira de habilitar essa opção é para que a caixa de diálogo implemente um evento que é acionado sempre que um texto é encontrado. FindDialogBox implementa o TextFoundEvent para este fim, que primeiro requer um delegado.

using System;

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

Usando o delegado, FindDialogBox implementa o .TextFoundEventHandlerTextFoundEvent

using System;
using System.Windows;
using System.Windows.Controls;
using System.Text.RegularExpressions;

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

    }
}
Imports System.Windows
Imports System.Windows.Controls
Imports System.Text.RegularExpressions

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

Consequentemente, Find pode gerar o evento quando um resultado de pesquisa é encontrado.

using System;
using System.Windows;
using System.Windows.Controls;
using System.Text.RegularExpressions;

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();
        }
    }
}
Imports System.Windows
Imports System.Windows.Controls
Imports System.Text.RegularExpressions

Namespace SDKSample

    Public Class FindDialogBox
        Inherits Window



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

    End Class
End Namespace

A janela do proprietário precisa então se registrar e tratar esse evento.

using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Win32;

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();
        }
    }
}
Imports System.ComponentModel
Imports System.Windows
Imports System.Windows.Controls
Imports Microsoft.Win32

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

Fechando uma caixa de diálogo sem janela restrita

Como DialogResult não precisa ser definida, uma caixa de diálogo sem janela restrita pode ser fechada usando mecanismos de fornecimento do sistema, incluindo o seguinte:

  • Clicar no botão Fechar na barra de título.

  • Pressionar ALT + F4.

  • Escolhendo Fechar no menu Sistema.

Como alternativa, seu código pode chamar Close quando o botão Fechar é clicado.

using System;
using System.Windows;
using System.Windows.Controls;
using System.Text.RegularExpressions;

namespace SDKSample
{
    public partial class FindDialogBox : Window
    {

        void closeButton_Click(object sender, RoutedEventArgs e)
        {
            // Close dialog box
            this.Close();
        }
    }
}
Imports System.Windows
Imports System.Windows.Controls
Imports System.Text.RegularExpressions

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

Confira também