C # WPF analogue Window.ShowDialog () atau berurusan dengan DispatcherFrame

Pernyataan masalah


Sebagai bagian dari pengembangan satu aplikasi, diperlukan untuk mengimplementasikan skema berikut:


  1. Metode asinkron meminta data
  2. Pengguna memasukkan data dari keyboard
  3. Metode menerima hasil input sebagai hasil dari fungsi dan berlanjut dari tempat yang sama

Persyaratan tambahan: Jangan membuat jendela tambahan.


Akan terlihat sederhana? Ternyata sangat sederhana. Tetapi hal pertama yang pertama.


Solusi


Upaya pertama untuk melakukannya secara langsung dan tanpa mencari di Internet menyebabkan terhambatnya utas utama, dan, karenanya, tidak ada gunanya. Dan saya akan menggunakan ShowDialog, ketika saya menemukan sebuah artikel . Penulis melihat bagaimana ShowDialog dibuat di WPF. Apa yang kamu butuhkan!


Dalam artikelnya, ia menyarankan untuk membuat implementasi sendiri dari metode ShowDialog


[DllImport("user32")] internal static extern bool EnableWindow(IntPtr hwnd, bool bEnable); public void ShowModal() { IntPtr handle = (new WindowInteropHelper(Application.Current.MainWindow)).Handle; EnableWindow(handle, false); DispatcherFrame frame = new DispatcherFrame(); this.Closed += delegate { EnableWindow(handle, true); frame.Continue = false; }; Show(); Dispatcher.PushFrame(frame); } 

Saya tidak perlu kunci jendela, karena semuanya ditampilkan dalam satu jendela, dan nilai kembali juga diperlukan. Kami menghapus terlalu banyak, tambahkan yang benar ...


  public string GetInput() { var frame = new DispatcherFrame(); ButtonClicked += () => { frame.Continue = false; }; Dispatcher.PushFrame(frame); return Text; } 

Dispatcher.PushFrame(frame) mencegah metode GetInput() sampai frame.Continue menjadi false . Ketika bingkai baru dimulai, loop utama berhenti dan yang baru dimulai. Loop ini memproses pesan sistem, sedangkan titik eksekusi di loop utama tidak bergerak lebih jauh. Ketika kita keluar dari frame saat ini ( frame.Continue = false ), loop utama terus bekerja dari tempat yang sama.


Sekarang tinggal memeriksa kinerja saja.


Di MainWindow, buat tombol dan letakkan handler di atasnya yang akan meluncurkan tugas, di mana kita akan beralih ke input keyboard.


Kode Penangan:


  public RelayCommand ButtonClick => new RelayCommand(() => { Task.Factory.StartNew(() => { //   Thread.Sleep(1000); //  -  var control = new PopupControlModel(); //  ,      Result = control.GetInput(); //    Thread.Sleep(2000); }); }); } 

Saya menggunakan solusi ini untuk memasukkan captcha dan kode tambahan untuk otentikasi dua faktor. Tetapi bisa ada sejumlah besar aplikasi.


! Kode sampel berisi pelanggaran prinsip mvvm, dan jangan memukul keras desain yang hilang


Kode sumber Github: Bukti konsep


Tautan yang bermanfaat


Artikel "Custom ShowDialog"
Deskripsi sedikit tentang kelas DispatcherFrame menggunakan terjemahan mesin
Menunggu penyelesaian melalui menunggu diberikan dalam artikel ini .

Source: https://habr.com/ru/post/id452268/


All Articles