2010-01-21 15 views
6

J'essaye de faire une boîte de dialogue de confirmation en utilisant l'objet ChildWindow de Silverlight.Silverlight Confirmer la boîte de dialogue pour mettre en pause le fil

Idéalement, je voudrais que cela fonctionne comme MessageBox.Show(), où l'application entière s'arrête jusqu'à ce qu'une entrée soit reçue de l'utilisateur.

Par exemple:

for (int i = 0; i < 5; i++) 
{ 
    if (i==3 && MessageBox.Show("Exit early?", 
     "Iterator", MessageBoxButton.OKCancel) == MessageBoxResult.OK) 
    { 
     break; 
    } 
} 

cesseraient l'itération à 3 si l'utilisateur touche OK ...

Cependant, si je devais faire quelque chose le long des lignes:

ChildWindow confirm = new ChildWindow(); 
confirm.Title = "Iterator"; 
confirm.HasCloseButton = false; 
Grid container = new Grid(); 

Button closeBtn = new Button(); 
closeBtn.Content = "Exit early"; 
closeBtn.Click += delegate { confirm.DialogResult = true; confirm.Close(); }; 
container.Children.Add(closeBtn); 

Button continueBtn = new Button(); 
continueBtn.Content = "Continue!"; 
continueBtn.Click += delegate { confirm.DialogResult = false; confirm.Close(); }; 
container.Children.Add(continueBtn); 

confirm.Content = container; 

for(int i=0;i<5;i++) { 
    if (i==3) { 
    confirm.Show(); 
    if (confirm.DialogResult.HasResult && (bool)confirm.DialogResult) { 
     break; 
    } 
    } 
} 

Cela ne fonctionnerait pas clairement, car le fil n'est pas arrêté ... confirm.DialogResult.HasResult serait faux, et la boucle continuerait après 3.

Je me demandais simplement comment je pourrais y arriver correctement. Silverlight est monothread, donc je ne peux pas mettre le fil en veille et le réveiller quand je suis prêt, alors je me demande s'il y a autre chose que les gens pourraient recommander?

J'ai envisagé d'inverser la logique - c'est-à-dire de passer les actions que je veux réaliser aux événements Oui/Non, mais dans mon cas, cela ne marcherait pas vraiment.

Merci d'avance!

Répondre

11

Je ne pense pas que vous serez en mesure de bloquer votre code dans une boucle de message comme vous pouvez avec ShowDialog de WinForms.

Cependant, vous pouvez abuser itérateurs pour obtenir le même effet:

interface IAction { void Execute(Action callback); } 

public static void ExecAction(IEnumerator<IAction> enumerator) { 
    if (enumerator.MoveNext()) 
     enumerator.Current.Execute(() => ExecAction(enumerator)); 
} 

class DialogAction : ChildWindow, IAction { 
    void IAction.Execute(Action callback) { 
     //Show the window, then call callback when it's closed 
    } 
} 

IEnumerator<IAction> YourMethod() { 
    ... 
    var confirm = new DialogAction(); 
    yield return confirm; 
    if (confirm.DialogResult.HasResult && (bool)confirm.DialogResult) 
     yield break; 
    ... 
} 

Pour utiliser ce système, vous pouvez écrire ExecAction(YourMethod());. Notez que ce serait un appel semi-bloquant, et que je n'ai pas testé cela du tout. Les nouvelles fonctionnalités async de C# 5 fonctionnent exactement de la même manière (en fait, les versions initiales du code du compilateur async étaient fortement basées sur l'implémentation de l'itérateur existant), mais avec une meilleure prise en charge syntaxique.

+1

C'est génial! Je vais essayer et voir comment ça marche ... – AlishahNovin

+0

Il peut facilement être adopté pour exécuter l'énumérateur dans un thread d'arrière-plan, ce qui rend très simple le flux de travail de l'interface utilisateur multithread. – SLaks

+0

+1. Point secondaire: ne voulez-vous pas dire «return return confirm» dans «YourMethod»? –

1

Vous pouvez y parvenir facilement avec calme RX Framework:

var continued = Observable.FromEvent<RoutedEventArgs>(continueBtn, "Click"); 

var iter = new Subject<int>(); 

var ask = iter.Where(i => i == 3).Do(_ => confirm.Show()); 

iter.Where(i => i != 3 && i < 10) 
    .Merge(ask.Zip(continued, (i, _) => i)) 
    .Do(i => Debug.WriteLine("Do something for iteration {0}", i)) 
    .Select(i => i + 1) 
    .Subscribe(iter); 

iter.OnNext(0); 

La solution évolue facilement pour toute règle déterminer à quel moment afficher une boîte de dialogue. Par exemple. Supposons que nous voulons bloquer l'itération et demander une confirmation de l'utilisateur toutes les 3 itérations. Tout ce que vous avez à faire est de remplacer la condition i == 3 par i % 3 == 0 (et i != 3 par i % 3 != 0).

0

Découvrez ce projet http://silverlightmsgbox.codeplex.com/. Il présente une implémentation simple mais présentable de plusieurs boîtes de message utiles, à savoir confirmation, erreur, info, entrée utilisateur, etc. et pourrait vous être utile. Bonne chance.

+0

Cela n'a rien à voir avec la question - il demande un appel bloquant. – SLaks