2010-01-21 10 views
6

Estoy tratando de hacer un cuadro de diálogo de confirmación utilizando el objeto ChildWindow de Silverlight.Silverlight Confirmar diálogo para detener el hilo

Idealmente, me gustaría que funcione como MessageBox.Show(), donde toda la aplicación se detiene hasta que el usuario reciba una entrada.

Por ejemplo:

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

detendría la iteración en la 3, si el usuario pulsa OK ...

Sin embargo, si tuviera que hacer algo en la línea:

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; 
    } 
    } 
} 

Esto claramente no funcionaría, ya que el hilo no se detiene ... confirm.DialogResult.HasResult sería falso, y el ciclo continuaría más allá de 3.

Me pregunto cómo podría hacer esto correctamente. Silverlight tiene un único hilo, así que no puedo simplemente poner el hilo en modo de suspensión y luego reactivarlo cuando estoy listo, así que me pregunto si hay algo más que la gente pueda recomendar.

He considerado invertir la lógica, es decir, pasar las acciones que deseo que ocurran a los eventos Sí/No, pero en mi caso específico esto no funcionaría.

¡Gracias de antemano!

Respuesta

11

No creo que pueda bloquear su código en un bucle de mensajes de la manera que pueda con WinForms 'ShowDialog.

Sin embargo, se puede hacer mal uso de iteradores para lograr el mismo efecto:

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; 
    ... 
} 

Para utilizar este sistema, podría escribir ExecAction(YourMethod());. Tenga en cuenta que esto sería una llamada de bloqueo parcial, y que no he probado esto en absoluto.

Las nuevas características de C# 5 async funcionan exactamente de la misma manera (de hecho, las versiones iniciales del código del compilador async se basaban principalmente en la implementación del iterador existente), pero con una mejor compatibilidad sintáctica.

+1

¡Eso es genial! Voy a dar una oportunidad y ver qué tan bien funciona ... – AlishahNovin

+0

Se puede adoptar fácilmente para ejecutar el enumerador en una cadena de fondo, lo que hace que el flujo de trabajo de IU con múltiples subprocesos sea muy simple. – SLaks

+0

+1. Punto menor: ¿no te refieres a 'yield return confirm' en' YourMethod'? –

1

Esto se puede conseguir fácilmente con calma 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 solución es fácilmente escalable para cualquier regla de determinar cuándo mostrar un cuadro de diálogo. P.ej. supongamos que queremos bloquear la iteración y solicitar confirmación al usuario cada 3 iteraciones. Todo lo que tiene que hacer es reemplazar la condición i == 3 con i % 3 == 0 (y i != 3 con i % 3 != 0).

0

Mira este proyecto http://silverlightmsgbox.codeplex.com/. Presenta una implementación simple pero presentable de varios cuadros de mensaje útiles, es decir, confirmación, error, información, entrada del usuario, etc. y podría ser útil para usted. Buena suerte.

+0

Eso no tiene nada que ver con la pregunta: está solicitando una llamada de bloqueo. – SLaks

Cuestiones relacionadas