วิธีสร้างกล่องโต้ตอบโมดอลใน WPF


133

ฉันกำลังเขียนแอปพลิเคชันแรกของฉันใน WPF และต้องการให้ผู้ใช้ป้อนข้อมูลบางอย่างในหน้าต่างโต้ตอบโมดอล เห็นได้ชัดว่านี่ไม่ใช่เรื่องง่ายที่จะทำใน WPF เนื่องจากหน้าต่างพาเรนต์ยังคงเปิดใช้งานอย่างสมบูรณ์และวิธีการที่สร้างหน้าต่างลูกใหม่จะไม่หยุดและรอให้หน้าต่างลูกเรียกปิด () แต่มันจะก้าวต่อไป นี่ไม่ใช่สิ่งที่ฉันต้องการ

ฉันจะเปิดหน้าต่างลูกได้อย่างไรและให้หน้าต่างพาเรนต์รอให้เด็กปิดก่อนที่หน้าต่างพาเรนต์จะทำงานต่อไป


แชร์คำตอบของฉันที่นี่เนื่องจากอาจช่วยให้บางคนหลงทางจาก Google
Shahin Dohan

คำตอบ:


222

คุณลองแสดงหน้าต่างของคุณโดยใช้วิธี ShowDialogหรือไม่?

อย่าลืมตั้งค่าคุณสมบัติ Ownerบนหน้าต่างโต้ตอบไปที่หน้าต่างหลัก วิธีนี้จะหลีกเลี่ยงพฤติกรรมแปลก ๆ เมื่อ Alt + Tabbing ฯลฯ


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 จะบล็อกเธรดการโทร (kinda [1]) และแสดงไดอะล็อก นอกจากนี้ยังจะบล็อกการโต้ตอบกับหน้าต่างหลัก / การเป็นเจ้าของ เมื่อกล่องโต้ตอบถูกปิด (ด้วยเหตุผลใดก็ตาม) ShowDialog จะกลับไปยังผู้โทรและจะอนุญาตให้คุณเข้าถึง DialogResult (หากคุณต้องการ)

[1] มันจะทำให้ผู้มอบหมายงานสูบน้ำโดยการผลักเฟรมดิสแพตเชอร์ไปที่เครื่องวัดพิกัด WPF ซึ่งจะทำให้ปั๊มข้อความยังคงปั๊มอยู่


กรุณาอธิบายรายละเอียดเพิ่มเติม ฉันกำลังพบปัญหาที่คล้ายกันซึ่งฉันมีกระบวนการทดสอบที่กำลังทำงานอยู่ แต่ข้อความเตือนสามารถปรากฏขึ้นเป็นกล่องโต้ตอบโมดอล แต่ฉันไม่ต้องการบล็อกการดำเนินการ
Firoso

2

รับวัตถุหน้าต่าง myWindow myWindow.Show () จะเปิดขึ้นโดยไม่ใช้โหมดและ myWindow.ShowDialog () จะเปิดขึ้นโดยไม่จำเป็น อย่างไรก็ตามแม้สิ่งหลังจะไม่ปิดกั้นจากสิ่งที่ฉันจำได้


6
ฉันเชื่อว่ามันบล็อก โค้ดหลัง myWindow.Show () ไม่ทำงานจนกว่า myWindow เรียก Close ()
Alex Baranosky

ทั้งคุณและ @AlexBaranosky ถูกต้อง: ShowDialogจะไม่กลับมาจนกว่าโมดอลจะปิดดังนั้นจึงบล็อกการดำเนินการของผู้มอบหมายงานที่กำลังดำเนินการอยู่ แต่ShowDialogตัวมันเองเรียกได้อย่างมีประสิทธิภาพDispatcher.Run()ดังนั้นผู้มอบหมายงานจึงยังคงดำเนินการต่อไปโดยมีผลให้ UI ตอบสนอง
Matt Thomas
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.