Як зробити модальний діалог у WPF?


133

Я пишу свою першу заявку у WPF і хочу, щоб користувач вводив деякі дані у модальне діалогове вікно. Мабуть, це не просто зробити в WPF, оскільки батьківське вікно залишається повністю включеним, а метод, який створив нове дочірнє вікно, не зупиняється і чекає, коли дочірнє вікно зателефонує Close (). Натомість він просто продовжує рухатися вперед. Це не те, що я хочу.

Як я можу змусити відкрити вікно дитини і змусити батьківське вікно чекати, коли дитина закриється, перш ніж батьківське вікно продовжить виконання?


Ділюсь моєю відповіддю тут, оскільки це може допомогти комусь тинятися сюди від Google.
Шахін Дохан

Відповіді:



43

Багато з цих відповідей спрощені, і якщо хтось починає WPF, вони можуть не знати всіх "входів і виходів", оскільки це складніше, ніж просто сказати комусь "Використовуйте .ShowDialog()!". Але це метод (не .Show()), який ви хочете використовувати для того, щоб заблокувати використання базового вікна і не допустити продовження дії коду до модального вікна.

По-перше, вам потрібно 2 вікна WPF. (Один буде дзвонити іншому.)

Скажімо, у першому вікні, яке називалося MainWindow.xaml, у його коді буде:

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

Потім додайте кнопку до свого XAML:

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

І клацніть правою кнопкою миші Clickрозпорядок, виберіть "Перейти до визначення". Він створить його для вас у MainWindow.xaml.cs:

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

У межах цієї функції вам потрібно вказати іншу сторінку, використовуючи її клас сторінки. Скажіть, ви назвали цю іншу сторінку "ModalWindow", так що вона стає її класом сторінок і таким чином ви б створили (викликали) її:

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

Скажімо, у вашому модальному діалоговому вікні вам потрібно встановити необхідне значення. Створіть текстове поле та кнопку в ModalWindowXAML:

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

Потім знову створіть обробник подій (інша Clickподія) та скористайтеся ним, щоб зберегти значення текстового поля до загальнодоступної статичної змінної увімкнено ModalWindowта виклик 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();
    }
}

Потім, після вашої .ShowDialog()заяви, ви можете схопити це значення і використовувати його:

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

    string valueFromModalTextBox = ModalWindow.myValue;
}

29

Window.Show Window покаже вікно, а продовження виконання - це виклик, що не блокує.

Window.ShowDialog заблокує викликовий потік (свого роду [1]) та покаже діалогове вікно. Це також заблокує взаємодію з батьківським / власним вікном. Після закриття діалогового вікна (з будь-якої причини) ShowDialog повернеться до абонента і дозволить отримати доступ до DialogResult (якщо ви цього бажаєте).

[1] Це дозволить утримати диспетчер накачування, натиснувши диспетчерську рамку на диспетчер WPF. Це призведе до того, що насос повідомлення продовжить перекачувати.


поясніть це детальніше будь ласка? Я дивлюся на подібну проблему, коли у мене запущений тестовий процес, але попереджувальні повідомлення можуть з'являтися як модальні діалоги, але я не хочу блокувати виконання.
Фіросо

2

Враховуючи об’єкт Window myWindow, myWindow.Show () відкриє його без режиму, а myWindow.ShowDialog () відкриє його модально. Однак навіть останнє не блокує, з того, що я пам’ятаю.


6
Я вважаю, що це блокує. Код після myWindow.Show () виконується лише після виклику myWindow Close ().
Олексій Бараноський

І ви, і @AlexBaranosky вірні: ShowDialogне повертаються, поки модаль не закритий, тому він блокує операцію диспетчера, що виконується в даний момент. Але ShowDialogсам по собі ефективно телефонує Dispatcher.Run(), тож диспетчер продовжує виконувати операції, фактично підтримуючи інтерфейс користувача відповідним.
Метт Томас
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.