Ventana analógica de C # WPF. ShowDialog () o tratar con DispatcherFrame

Declaración del problema.


Como parte del desarrollo de una aplicación, se requería implementar el siguiente esquema:


  1. El método asincrónico solicita datos
  2. El usuario ingresa datos desde el teclado
  3. El método recibe el resultado de entrada como resultado de la función y continúa desde el mismo lugar

Requisito adicional: no cree ventanas adicionales.


Parecería simple? Resultó ser realmente simple. Pero lo primero es lo primero.


Solución


El primer intento de hacerlo de frente y sin buscar en Internet condujo a un bloqueo de la transmisión principal y, por lo tanto, no sirvió de nada. Y estaba a punto de usar ShowDialog, cuando me encontré con un artículo . El autor observó cómo se hace ShowDialog en WPF. Lo que necesitas!


En su artículo, sugiere crear su propia implementación del método 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); } 

No necesito un bloqueo de ventana, ya que todo se muestra en una ventana, y también se requiere un valor de retorno. Eliminamos demasiado, agregamos el correcto ...


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

Dispatcher.PushFrame(frame) evita que el método frame.Continue GetInput() hasta frame.Continue vuelve false . Cuando se inicia un nuevo marco, el bucle principal se detiene y se inicia uno nuevo. Este bucle procesa los mensajes del sistema, mientras que el punto de ejecución en el bucle principal no se mueve más. Cuando salimos del marco actual ( frame.Continue = false ), el bucle principal continúa trabajando desde el mismo lugar.


Ahora solo queda comprobar el rendimiento.


En MainWindow, cree un botón y cuelgue un controlador en él, lo que iniciará la tarea, en la que pasaremos a la entrada del teclado.


Código de manejador:


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

Usé esta solución para ingresar captcha y código adicional para la autenticación de dos factores. Pero puede haber una gran cantidad de aplicaciones.


! El código de muestra contiene violaciones del principio mvvm y no pegues fuerte diseño faltante


Código fuente de Github: prueba de concepto


Enlaces utiles


Artículo "ShowDialog personalizado"
Descripción escasa de la clase DispatcherFrame utilizando traducción automática
En este artículo, se espera la finalización a través de esperar .

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


All Articles