Come creare una finestra di dialogo modale in WPF?


133

Sto scrivendo la mia prima applicazione in WPF e voglio che l'utente inserisca alcuni dati in una finestra di dialogo modale. Apparentemente, questo non è semplice da fare in WPF, perché la finestra padre rimane completamente abilitata e il metodo che ha creato la nuova finestra figlio non si ferma e aspetta che la finestra figlio chiami Close (). Invece continua ad andare avanti. Questo non è quello che voglio.

Come posso aprire la finestra figlio e fare in modo che la finestra padre attenda la chiusura del figlio prima che la finestra padre continui a essere eseguita?


Condividere la mia risposta qui perché potrebbe aiutare qualcuno a vagare qui da Google.
Shahin Dohan,

Risposte:


222

Hai provato a mostrare la tua finestra usando il metodo ShowDialog ?

Non dimenticare di impostare la proprietà Owner nella finestra di dialogo sulla finestra principale. Questo eviterà comportamenti strani quando Alt + Tabbing, ecc.


43

Molte di queste risposte sono semplicistiche e se qualcuno sta iniziando WPF, potrebbe non conoscere tutti i "dettagli", in quanto è più complicato del dire semplicemente a qualcuno "Usa .ShowDialog()!". Ma questo è il metodo (non .Show()) che si desidera utilizzare per bloccare l'uso della finestra sottostante e impedire che il codice continui fino alla chiusura della finestra modale.

Innanzitutto, sono necessarie 2 finestre WPF. (Uno chiamerà l'altro.)

Dalla prima finestra, diciamo che è stato chiamato MainWindow.xaml, nel suo code-behind sarà:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }
}

Quindi aggiungi il pulsante al tuo XAML:

<Button Name="btnOpenModal" Click="btnOpenModal_Click" Content="Open Modal" />

E fai clic con il tasto destro del mouse sulla Clickroutine, seleziona "Vai alla definizione". Lo creerà per te in MainWindow.xaml.cs:

private void btnOpenModal_Click(object sender, RoutedEventArgs e)
{
}

All'interno di quella funzione, devi specificare l'altra pagina usando la sua classe di pagina. Supponiamo che tu abbia chiamato quell'altra pagina "ModalWindow", in modo che diventi la sua classe di pagina ed è il modo in cui la creeresti (chiamandola):

private void btnOpenModal_Click(object sender, RoutedEventArgs e)
{
    ModalWindow modalWindow = new ModalWindow();
    modalWindow.ShowDialog();
}

Supponi di avere un valore che devi impostare nella finestra di dialogo modale. Crea una casella di testo e un pulsante in ModalWindowXAML:

<StackPanel Orientation="Horizontal">
    <TextBox Name="txtSomeBox" />
    <Button Name="btnSaveData" Click="btnSaveData_Click" Content="Save" /> 
</StackPanel>

Quindi creare Clicknuovamente un gestore eventi (un altro evento) e utilizzarlo per salvare il valore della casella di testo in una variabile statica pubblica ModalWindowe chiamare this.Close().

public partial class ModalWindow : Window
{
    public static string myValue = String.Empty;        
    public ModalWindow()
    {
        InitializeComponent();
    }

    private void btnSaveData_Click(object sender, RoutedEventArgs e)
    {
        myValue = txtSomeBox.Text;
        this.Close();
    }
}

Quindi, dopo la tua .ShowDialog()dichiarazione, puoi prendere quel valore e usarlo:

private void btnOpenModal_Click(object sender, RoutedEventArgs e)
{
    ModalWindow modalWindow = new ModalWindow();
    modalWindow.ShowDialog();

    string valueFromModalTextBox = ModalWindow.myValue;
}

29

Window.Show Window mostrerà la finestra e continuerà l'esecuzione - è una chiamata non bloccante.

Window.ShowDialog bloccherà il thread chiamante (kinda [1]) e mostrerà la finestra di dialogo. Bloccherà anche l'interazione con la finestra principale / proprietaria. Quando la finestra di dialogo viene chiusa (per qualsiasi motivo) ShowDialog tornerà al chiamante e ti consentirà di accedere a DialogResult (se lo desideri).

[1] Continuerà a pompare il dispatcher spingendo un telaio del dispatcher sul dipatcher WPF. Ciò farà sì che il pump dei messaggi continui a pompare.


spiegalo più in dettaglio per favore? Sto osservando un problema simile in cui ho un processo di test in esecuzione ma i messaggi di avviso possono apparire come finestre di dialogo modali ma non voglio bloccare l'esecuzione.
Firoso,

2

Dato un oggetto Window myWindow, myWindow.Show () lo aprirà in modo non modale e myWindow.ShowDialog () lo aprirà in modo modale. Tuttavia, anche quest'ultimo non si blocca, da quello che ricordo.


6
Credo che blocchi. Il codice dopo myWindow.Show () non viene eseguito fino a quando myWindow chiama Close ().
Alex Baranosky,

Sia tu che @AlexBaranosky avete ragione: ShowDialognon ritorna fino alla chiusura del modale, quindi blocca l'operazione di dispatcher attualmente in esecuzione. Ma ShowDialogsi chiama in Dispatcher.Run()modo efficace , quindi il dispatcher continua a eseguire operazioni, mantenendo in effetti l'interfaccia utente reattiva.
Matt Thomas,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.