Share via


Panoramica delle finestre di dialogo

Le applicazioni autonome in genere hanno una finestra principale che visualizza i dati principali su cui opera l'applicazione ed espone la funzionalità per elaborare i dati tramite meccanismi dell'interfaccia utente come barre dei menu, barre degli strumenti e barre di stato. In un'applicazione più complessa sono inoltre disponibili finestre aggiuntive per l'esecuzione delle operazioni riportate di seguito:

  • Visualizzazione di informazioni specifiche agli utenti.

  • Raccolta delle informazioni immesse dagli utenti.

  • Visualizzazione e raccolta di informazioni.

Questi tipi di finestre, noti come finestre di dialogo, si suddividono in due tipi: modali e non modali.

Una finestra di dialogo modale viene visualizzata da una funzione quando tale funzione, per continuare, deve ricevere ulteriori dati dall'utente. Poiché la raccolta dei dati da parte della funzione dipende dalla finestra di dialogo modale, finché quest'ultima rimane aperta l'utente non potrà attivare altre finestre nell'applicazione. Nella maggior parte dei casi, una finestra di dialogo modale può essere chiusa dall'utente tramite la pressione di un pulsante OK o Annulla. Se preme il pulsante OK, l'utente ha immesso dei dati che desidera vengano elaborati dalla funzione. Se preme il pulsante Annulla, l'utente desidera arrestare l'esecuzione della funzione. Gli esempi più comuni di finestre di dialogo modali sono dati dalle finestre di apertura, salvataggio e stampa dei dati.

Una finestra di dialogo non modale, tuttavia, non impedisce a un utente di attivare altre finestre mentre è aperta. Ad esempio, se un utente desidera cercare occorrenze di una determinata parola in un documento, dalla finestra principale verrà spesso aperta una finestra di dialogo in cui l'utente dovrà immettere la parola che desidera cercare. Poiché la ricerca di una parola non impedisce all'utente di modificare il documento, la finestra di dialogo non deve essere modale. In una finestra di dialogo non modale è senz'altro disponibile un pulsante Chiudi per la sua chiusura ed eventualmente ulteriori pulsanti per l'esecuzione di funzioni specifiche, ad esempio un pulsante Trova successivo per cercare la parola successiva corrispondente ai criteri della ricerca.

Windows Presentation Foundation (WPF) consente di creare diversi tipi di finestre di dialogo, tra cui finestre di dialogo, finestre di dialogo comuni e finestre di dialogo personalizzate. Questo argomento illustra i diversi tipi di finestre di dialogo e in Esempio di finestra di dialogo sono disponibili alcuni esempi.

Finestre di messaggio

Una finestra di messaggio è una finestra di dialogo che può essere utilizzata per visualizzare informazioni di testo e consentire agli utenti di prendere decisioni con i pulsanti. Di seguito è illustrata una finestra di messaggio in cui vengono visualizzate informazioni di testo, viene posta una domanda e sono disponibili tre pulsanti per fornire una risposta.

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

Per creare una finestra di messaggio, usare la MessageBox classe . MessageBox consente di configurare il testo della finestra di messaggio, il titolo, l'icona e i pulsanti, usando codice simile al seguente.

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

Per visualizzare una finestra di messaggio, chiamare il staticShow metodo , come illustrato nel codice seguente.

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

Quando il codice per la visualizzazione di una finestra di messaggio deve rilevare ed elaborare la decisione dell'utente (quale pulsante è stato premuto), può analizzare il risultato della finestra di messaggio, come illustrato nel codice riportato di seguito.

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

Per altre informazioni sull'uso delle finestre di messaggio, vedere MessageBoxEsempio di MessageBox e Esempio di finestra di dialogo.

Anche se MessageBox può offrire un'esperienza utente semplice nella finestra di dialogo, il vantaggio dell'uso MessageBox è l'unico tipo di finestra che può essere visualizzato dalle applicazioni eseguite all'interno di una sandbox di sicurezza parzialmente attendibile (vedere Sicurezza), ad esempio le applicazioni browser XAML (XBAP).

Nella maggior parte delle finestre di dialogo vengono visualizzati e raggruppati dati più complessi del risultato di una finestra di messaggio, ad esempio testo, selezione (caselle di controllo), selezione a esclusione reciproca (pulsanti di opzione) e selezione in elenchi (caselle di riepilogo, caselle combinate, elenchi a discesa). Per questi, Windows Presentation Foundation (WPF) fornisce diverse finestre di dialogo comuni e consente di creare finestre di dialogo personalizzate, anche se l'uso di uno dei due è limitato alle applicazioni in esecuzione con attendibilità totale.

Finestre di dialogo comuni

Windows implementa un'ampia gamma di finestre di dialogo riutilizzabili comuni a tutte le applicazioni, incluse le finestre di dialogo per l'apertura di file, il salvataggio di file e la stampa. Poiché queste finestre di dialogo sono implementate dal sistema operativo, possono essere condivise da tutte le applicazioni eseguite nel sistema operativo, con notevoli vantaggi in termini della coerenza di utilizzo: se un utente utilizza con frequenza una finestra di dialogo basata sul sistema operativo in un'applicazione, non dovrà imparare a utilizzare la stessa finestra in altre applicazioni. Poiché queste finestre di dialogo sono disponibili in tutte le applicazioni e poiché consentono un'esperienza utente coerente, sono note come finestre di dialogo comuni.

Windows Presentation Foundation (WPF) incapsula i file aperti, salva file e stampa le finestre di dialogo comuni e le espone come classi gestite da usare nelle applicazioni autonome. Questo argomento fornisce alcuni cenni preliminari su ognuna.

Finestra di dialogo Apri file

La finestra di dialogo Apri illustrata di seguito viene utilizzata dalla funzionalità di apertura file per recuperare il nome di un file da aprire.

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

La finestra di dialogo common open file viene implementata come OpenFileDialog classe e si trova nello spazio dei Microsoft.Win32 nomi . Il codice seguente illustra come creare, configurare e visualizzare questa finestra di dialogo, nonché come elaborare il relativo risultato.

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

Per altre informazioni sulla finestra di dialogo Apri file, vedere Microsoft.Win32.OpenFileDialog.

Nota

OpenFileDialog può essere usato per recuperare in modo sicuro i nomi di file dalle applicazioni in esecuzione con attendibilità parziale (vedere Sicurezza).

Salva file (finestra di dialogo)

La finestra di dialogo Salva con nome illustrata di seguito viene utilizzata dalla funzionalità di salvataggio file per recuperare il nome di un file da salvare.

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

La finestra di dialogo file di salvataggio comune viene implementata come SaveFileDialog classe e si trova nello spazio dei Microsoft.Win32 nomi . Il codice seguente illustra come creare, configurare e visualizzare questa finestra di dialogo, nonché come elaborare il relativo risultato.

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

Per altre informazioni sulla finestra di dialogo Salva file, vedere Microsoft.Win32.SaveFileDialog.

La finestra di dialogo Stampa illustrata di seguito viene utilizzata dalla funzionalità di stampa per la scelta e la configurazione della stampante su cui stampare dati.

Screenshot that shows a Print dialog box.

La finestra di dialogo stampa comune viene implementata come PrintDialog classe e si trova nello spazio dei System.Windows.Controls nomi . Il codice seguente illustra come creare, configurare e visualizzare una finestra di dialogo di questo tipo.

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

Per altre informazioni sulla finestra di dialogo stampa, vedere System.Windows.Controls.PrintDialog. Per informazioni dettagliate sulla stampa in WPF, vedere Panoramica della stampa.

Finestre di dialogo personalizzate

Sebbene le finestre di dialogo comuni siano utili e debbano essere utilizzate quando possibile, non supportano i requisiti delle finestre di dialogo specifiche di vari domini. In questi casi, è necessario creare finestre di dialogo personalizzate. Come verrà illustrato in seguito, una finestra di dialogo è una finestra con particolari comportamenti. Window implementa tali comportamenti e, di conseguenza, si usano Window per creare finestre di dialogo modali e modeless personalizzate.

Creazione di una finestra di dialogo personalizzata modale

In questo argomento viene illustrato come usare Window per creare un'implementazione tipica della finestra di dialogo modale, usando la Margins finestra di dialogo come esempio (vedere Esempio di finestra di dialogo). La Margins finestra di dialogo è illustrata nella figura seguente.

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

Configurazione di una finestra di dialogo modale

L'interfaccia utente di una finestra di dialogo tipica include gli elementi riportati di seguito:

  • I diversi controlli necessari per raccogliere i dati desiderati.

  • Pulsante OK che gli utenti fanno clic per chiudere la finestra di dialogo, tornare alla funzione e continuare l'elaborazione.

  • Pulsante Annulla su cui gli utenti fanno clic per chiudere la finestra di dialogo e arrestare l'ulteriore elaborazione della funzione.

  • Pulsante Chiudi nella barra del titolo.

  • Un'icona.

  • Pulsanti Riduci a icona, Ingrandisci e Ripristina.

  • Menu Sistema per ridurre al minimo, ingrandire, ripristinare e chiudere la finestra di dialogo.

  • Posizione sopra e al centro della finestra che ha aperto la finestra di dialogo.

  • Possibilità di ridimensionare laddove possibile per impedire che la finestra di dialogo sia troppo piccola e fornire all'utente una dimensione predefinita utile. È quindi necessario impostare sia le dimensioni predefinite che le dimensioni minime.

  • Tasto ESC come tasto di scelta rapida che determina la pressione del pulsante Annulla . A tale scopo, impostare la IsCancel proprietà del pulsante Annulla su true.

  • Tasto INVIO (o RETURN) come tasto di scelta rapida che determina la pressione del pulsante OK . A tale scopo, impostare la IsDefault proprietà del pulsante trueOK.

Il codice seguente illustra questa configurazione.

<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

L'esperienza utente relativa all'utilizzo di una finestra di dialogo si estende anche alla barra dei menu della finestra da cui viene aperta la finestra di dialogo. Quando una voce di menu attiva una funzione la cui elaborazione richiede interazione da parte dell'utente tramite una finestra di dialogo, nell'intestazione della voce di menu saranno visibili dei puntini di sospensione, come illustrato di seguito.

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

Quando una voce di menu attiva una funzione che comporta la visualizzazione di una finestra di dialogo che non richiede interazione da parte dell'utente, ad esempio una finestra di dialogo Informazioni su, i puntini di sospensione non sono necessari.

Apertura di una finestra di dialogo modale

Una finestra di dialogo viene in genere visualizzata in seguito alla selezione, da parte dell'utente, di una voce di menu per l'esecuzione di una funzione specifica di un dominio, ad esempio l'impostazione dei margini di un documento in un elaboratore di testo. La visualizzazione di una finestra come una finestra di dialogo è simile alla visualizzazione di una normale finestra, sebbene richieda operazioni di configurazione specifiche. L'intero processo di creazione di un'istanza, configurazione e apertura di una finestra di dialogo viene illustrato nel codice riportato di seguito.

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

In questo caso, il codice passa le informazioni predefinite (i margini correnti) alla finestra di dialogo. Imposta anche la Window.Owner proprietà con un riferimento alla finestra che visualizza la finestra di dialogo. In generale, è sempre opportuno impostare il proprietario di una finestra di dialogo per fornire i comportamenti correlati allo stato della finestra comuni a tutte le finestre di dialogo. Per ulteriori informazioni, vedere Cenni preliminari sulle finestre WPF.

Nota

È necessario fornire un proprietario per supportare l'automazione dell'interfaccia utente (UI) per le finestre di dialogo (vedere panoramica Automazione interfaccia utente).

Dopo aver configurato la finestra di dialogo, viene visualizzata in modo modally chiamando il ShowDialog metodo .

Convalida dei dati forniti dall'utente

Quando viene aperta una finestra di dialogo e l'utente fornisce i dati necessari, la finestra di dialogo deve garantire che i dati forniti siano validi per i motivi riportati di seguito:

  • Da un punto di vista della sicurezza, tutti gli input devono essere convalidati.

  • Da un punto di vista specifico del dominio, la convalida dei dati impedisce l'elaborazione di dati errati da parte del codice, che potrebbe potenzialmente generare eccezioni.

  • Da un punto di vista dell'esperienza utente, una finestra di dialogo può aiutare l'utente mostrandogli quali dati immessi non sono validi.

  • Da un punto di vista delle prestazioni, la convalida dei dati in un'applicazione a più livelli può ridurre il numero di round trip tra il client e i livelli dell'applicazione, in particolare se l'applicazione è composta da servizi Web o database basati su server.

Per convalidare un controllo associato in WPF, è necessario definire una regola di convalida e associarla all'associazione. Una regola di convalida è una classe personalizzata che deriva da ValidationRule. Nell'esempio seguente viene illustrata una regola di convalida, MarginValidationRule, che verifica che un valore associato sia un Double oggetto e si trova all'interno di un intervallo specificato.

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

In questo codice la logica di convalida di una regola di convalida viene implementata eseguendo l'override del Validate metodo , che convalida i dati e restituisce un oggetto appropriato ValidationResult.

Per abbinare la regola di convalida al controllo associato, utilizzare il markup riportato di seguito.

<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>

Dopo aver associato la regola di convalida, WPF lo applicherà automaticamente quando i dati vengono immessi nel controllo associato. Quando un controllo contiene dati non validi, WPF visualizzerà un bordo rosso intorno al controllo non valido, come illustrato nella figura seguente.

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

WPF non limita un utente al controllo non valido fino a quando non sono stati immessi dati validi. In questo modo, l'utente sarà libero di spostarsi tra i controlli della finestra di dialogo anche se i dati immessi non sono validi. Ciò significa, tuttavia, che un utente può immettere dati non validi e premere il pulsante OK. Per questo motivo, il codice deve anche convalidare tutti i controlli in una finestra di dialogo quando il pulsante OK viene premuto gestendo l'evento Click .

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

Questo codice enumera tutti gli oggetti di dipendenza in una finestra e, se presenti, non sono validi (come restituito da GetHasError, il controllo non valido ottiene lo stato attivo, il IsValid metodo restituisce falsee la finestra è considerata non valida.

Dopo essere stata ritenuta valida, la finestra di dialogo può essere chiusa. Questo processo deve inoltre prevedere la restituzione di un risultato alla funzione chiamante.

Impostazione del risultato della finestra di dialogo modale

L'apertura di una finestra di dialogo con ShowDialog è fondamentalmente simile alla chiamata di un metodo: il codice che ha aperto la finestra di dialogo usando ShowDialog attende fino a ShowDialog quando non viene restituito. Quando ShowDialog termina, il codice che ha chiamato deve decidere se continuare l'elaborazione o arrestare l'elaborazione, in base al fatto che l'utente abbia premuto il pulsante OK o il pulsante Annulla . Per facilitare questa decisione, la finestra di dialogo deve restituire la scelta dell'utente come Boolean valore restituito dal ShowDialog metodo .

Quando si fa clic sul pulsante OK , ShowDialog deve restituire true. Questa operazione viene ottenuta impostando la DialogResult proprietà della finestra di dialogo quando si fa clic sul pulsante OK .

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

Si noti che l'impostazione della proprietà determina anche la DialogResult chiusura automatica della finestra, che riduce la necessità di chiamare Closein modo esplicito .

Quando si fa clic sul pulsante Annulla , ShowDialog deve restituire false, che richiede anche l'impostazione della DialogResult proprietà .

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 la proprietà di IsCancel un pulsante è impostata su true e l'utente preme il pulsante Annulla o esc, DialogResult viene impostato automaticamente su false. Il markup seguente ha lo stesso effetto del codice precedente, senza la necessità di gestire l'evento Click .

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

Una finestra di dialogo restituisce false automaticamente quando un utente preme il pulsante Chiudi nella barra del titolo o sceglie la voce di menu Chiudi dal menu Sistema.

Elaborazione dei dati restituiti da una finestra di dialogo modale

Quando DialogResult viene impostato da una finestra di dialogo, la funzione che l'ha aperta può ottenere il risultato della finestra di dialogo esaminando la DialogResult proprietà quando ShowDialog viene restituita.

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 il risultato della finestra di dialogo è true, la funzione utilizza tale risultato con un'indicazione per recuperare ed elaborare i dati forniti dall'utente.

Nota

Dopo ShowDialog la restituzione, non è possibile riaprire una finestra di dialogo. È invece necessario creare una nuova istanza.

Se il risultato della finestra di dialogo è false, l'elaborazione della funzione viene terminata in modo appropriato.

Creazione di una finestra di dialogo personalizzata senza modalità

Una finestra di dialogo non modale, ad esempio la finestra di dialogo Trova illustrata di seguito, presenta sostanzialmente lo stesso aspetto di una finestra di dialogo modale.

Screenshot that shows a Find dialog box.

Il comportamento è invece leggermente diverso, come descritto nelle sezioni riportate di seguito.

Apertura di una finestra di dialogo senza modalità

Viene aperta una finestra di dialogo senza modalità chiamando il Show metodo .

<!--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

A differenza di ShowDialog, Show restituisce immediatamente . Di conseguenza, la finestra chiamante non può stabilire quando la finestra di dialogo non modale viene chiusa e pertanto non sa quando verificare il risultato della finestra di dialogo o quando ottenere dati dalla finestra di dialogo per continuare l'elaborazione. La finestra di dialogo deve quindi disporre di un modo alternativo per restituire dati alla finestra chiamante.

Elaborazione dei dati restituiti da una finestra di dialogo senza modalità

In questo esempio, l'oggetto FindDialogBox può restituire uno o più risultati di ricerca nella finestra principale, a seconda del testo cercato senza una frequenza specifica. Come con una finestra di dialogo modale, una finestra di dialogo non modale può restituire risultati utilizzando le proprietà. Tuttavia, la finestra proprietaria della finestra di dialogo deve sapere quando controllare tali proprietà. A tal fine, la finestra di dialogo dovrebbe implementare un evento generato ogni volta che viene trovato il testo. FindDialogBox implementa per TextFoundEvent questo scopo, che richiede innanzitutto un delegato.

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 il TextFoundEventHandler delegato, FindDialogBox implementa .TextFoundEvent

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

Di conseguenza, Find può generare l'evento quando viene trovato un risultato della ricerca.

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

La finestra proprietaria deve quindi eseguire la registrazione e gestire questo 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

Chiusura di una finestra di dialogo senza modalità

Poiché DialogResult non è necessario impostare un dialogo senza modalità, è possibile chiudere un dialogo senza modalità usando i meccanismi forniti dal sistema, inclusi i seguenti:

  • Pulsante Chiudi nella barra del titolo.

  • ALT + F4.

  • Scegliere Chiudi dal menu Sistema .

In alternativa, il codice può chiamare Close quando si fa clic sul pulsante Chiudi .

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

Vedi anche