Jak zrobić modalne okno dialogowe w WPF?


140

Piszę moją pierwszą aplikację w WPF i chcę, aby użytkownik wprowadził pewne dane w modalnym oknie dialogowym. Najwyraźniej nie jest to łatwe do wykonania w WPF, ponieważ okno nadrzędne pozostaje w pełni włączone, a metoda, która utworzyła nowe okno podrzędne, nie zatrzymuje się i nie czeka na wywołanie funkcji Close () przez okno podrzędne. Zamiast tego po prostu idzie do przodu. Nie tego chcę.

Jak sprawić, aby okno podrzędne było otwierane i aby okno nadrzędne oczekiwało na zamknięcie okna podrzędnego, zanim okno nadrzędne będzie kontynuowane?


Udostępniam tutaj moją odpowiedź , ponieważ może to pomóc komuś tułającemu się z Google.
Shahin Dohan

Odpowiedzi:



50

Wiele z tych odpowiedzi jest uproszczonych, a jeśli ktoś zaczyna WPF, może nie znać wszystkich „wejść i wyjść”, ponieważ jest to bardziej skomplikowane niż zwykłe powiedzenie komuś „Użyj .ShowDialog()!”. Ale to jest metoda (nie .Show()), której chcesz użyć, aby zablokować użycie okna bazowego i aby kod nie był kontynuowany, dopóki okno modalne nie zostanie zamknięte.

Najpierw potrzebujesz 2 okien WPF. (Jeden będzie dzwonił do drugiego.)

Załóżmy, że z pierwszego okna, które nazywało się MainWindow.xaml, w jego kodzie za nim będzie:

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

Następnie dodaj przycisk do kodu XAML:

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

Kliknij Clickprocedurę prawym przyciskiem myszy i wybierz opcję „Przejdź do definicji”. Stworzy go dla Ciebie w MainWindow.xaml.cs:

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

W ramach tej funkcji musisz określić drugą stronę za pomocą jej klasy strony. Powiedzmy, że nazwałeś tę drugą stronę „ModalWindow”, tak aby stała się ona klasą strony i tak można ją utworzyć (wywołać):

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

Załóżmy, że masz wartość, którą chcesz ustawić w oknie modalnym. Utwórz pole tekstowe i przycisk w ModalWindowXAML:

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

Następnie ponownie utwórz procedurę obsługi zdarzenia (inne Clickzdarzenie) i użyj jej do zapisania wartości pola tekstowego w publicznej zmiennej statycznej ModalWindowi wywołaj 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();
    }
}

Następnie po złożeniu .ShowDialog()oświadczenia możesz pobrać tę wartość i użyć jej:

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

    string valueFromModalTextBox = ModalWindow.myValue;
}

30

Window.Show Window pokaże okno i będzie kontynuować wykonywanie - jest to wywołanie nieblokujące.

Window.ShowDialog zablokuje wątek wywołujący (w pewnym sensie [1]) i wyświetli okno dialogowe. Blokuje również interakcję z oknem nadrzędnym / właścicielem. Gdy okno dialogowe zostanie zamknięte (z dowolnego powodu) ShowDialog powróci do dzwoniącego i umożliwi dostęp do DialogResult (jeśli chcesz).

[1] Będzie utrzymywać pompowanie przez dyspozytora poprzez wpychanie ramki dyspozytora na dipatcher WPF. Spowoduje to, że komunikat pompa będzie dalej pompować.


wyjaśnij to bardziej szczegółowo, proszę? Patrzę na podobny problem, w którym mam uruchomiony proces testowy, ale komunikaty ostrzegawcze mogą pojawiać się jako modalne okna dialogowe, ale nie chcę blokować wykonywania.
Firoso

2

Mając obiekt Window myWindow, myWindow.Show () otworzy go w sposób modelowy, a myWindow.ShowDialog () otworzy go modalnie. Jednak nawet ta ostatnia nie blokuje, z tego co pamiętam.


6
Myślę, że to blokuje. Kod po myWindow.Show () nie jest wykonywany, dopóki myWindow nie wywoła Close ().
Alex Baranosky

Zarówno ty, jak i @AlexBaranosky jesteście poprawni: ShowDialognie wraca, dopóki modal nie zostanie zamknięty, więc blokuje aktualnie wykonywaną operację wysyłającą. Ale ShowDialogsam skutecznie wywołuje Dispatcher.Run(), więc dyspozytor kontynuuje wykonywanie operacji, w efekcie utrzymując responsywność interfejsu użytkownika.
Matt Thomas,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.