FenĂȘtre analogique C # WPF.ShowDialog () ou gĂ©rer DispatcherFrame

ÉnoncĂ© du problĂšme


Dans le cadre du dĂ©veloppement d'une application, il a Ă©tĂ© nĂ©cessaire de mettre en Ɠuvre le schĂ©ma suivant:


  1. La méthode asynchrone demande des données
  2. L'utilisateur entre des données à partir du clavier
  3. La mĂ©thode reçoit le rĂ©sultat d'entrĂ©e comme rĂ©sultat de l'exĂ©cution de la fonction et continue du mĂȘme endroit

Condition supplĂ©mentaire: ne crĂ©ez pas de fenĂȘtres supplĂ©mentaires.


Cela semblerait simple? Cela s'est avéré trÚs simple. Mais tout d'abord.


Solution


La premiÚre tentative de le faire de front et sans chercher sur Internet a conduit à un blocage du thread principal, et donc à rien. Et j'étais sur le point d'utiliser ShowDialog, car je suis tombé sur un article . L'auteur a examiné comment ShowDialog est créé dans WPF. Ce dont vous avez besoin!


Dans son article, il propose de créer sa propre implémentation de la méthode 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); } 

Je n'ai pas besoin d'un verrou de fenĂȘtre, car tout est affichĂ© dans une seule fenĂȘtre et une valeur de retour est Ă©galement requise. On enlĂšve un peu trop, on ajoute le bon ...


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

Dispatcher.PushFrame(frame) empĂȘche la mĂ©thode GetInput() de se GetInput() jusqu'Ă  frame.Continue que frame.Continue devienne false . Lorsqu'une nouvelle image est dĂ©marrĂ©e, la boucle principale s'arrĂȘte et une nouvelle dĂ©marre. Cette boucle traite les messages systĂšme, tandis que le point d'exĂ©cution dans la boucle principale ne se dĂ©place pas plus loin. Lorsque nous frame.Continue = false image actuelle ( frame.Continue = false ), la boucle principale continue de fonctionner au mĂȘme endroit.


Maintenant, il ne reste plus qu'à vérifier les performances.


Dans MainWindow, créez un bouton et raccrochez un gestionnaire, qui lancera la tùche, dans laquelle nous passerons à la saisie au clavier.


Code du gestionnaire:


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

J'ai utilisé cette solution pour saisir le captcha et le code supplémentaire pour l'authentification à deux facteurs. Mais il peut y avoir un grand nombre d'applications.


! L'exemple de code contient des violations du principe mvvm, et ne frappe pas fort conception manquante


Code source Github: preuve de concept


Liens utiles


Article "Dialogue Show Show personnalisé"
Description limitée de la classe DispatcherFrame à l'aide de la traduction automatique
L'attente de l'achÚvement via l'attente est donnée dans cet article.

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


All Articles