2010-01-21 13 views
6

Próbuję zrobić okno dialogowe z potwierdzeniem za pomocą obiektu Silverlight o numerze ChildWindow.Silverlight Potwierdź okno dialogowe, aby wstrzymać wątek

Idealnie, chciałbym, aby działało jak MessageBox.Show(), gdzie cała aplikacja zatrzymuje się, dopóki dane wejściowe nie zostaną odebrane od użytkownika.

Na przykład:

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

zatrzyma iteracji na 3, jeśli użytkownik kliknie OK ...

Jednak jeśli miałbym zrobić coś wzdłuż linii:

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

To oczywiście nie zadziała, ponieważ wątek nie zostanie zatrzymany ... confirm.DialogResult.HasResult byłby fałszywy, a pętla potrwa dłużej niż 3.

Zastanawiam się, jak mógłbym zrobić to poprawnie. Silverlight jest jednowątkowy, więc nie mogę po prostu uśpić nici i obudzić go, kiedy jestem gotowy, więc zastanawiam się, czy jest coś jeszcze, co ludzie mogliby polecić?

Zastanawiałem się nad odwróceniem logiki - tj. Przekazaniem działań, które chcę wykonać, na zdarzenia Tak/Nie, ale w moim konkretnym przypadku to by nie działało.

Z góry dziękuję!

Odpowiedz

11

Nie sądzę, że będziesz w stanie zablokować swój kod w pętli wiadomości tak, jak możesz z WinForms 'ShowDialog.

Można jednak nadużywać iteratory aby osiągnąć ten sam efekt:

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

Aby korzystać z tego systemu, by napisać ExecAction(YourMethod());. Zauważ, że byłoby to połączenie półblokujące i nie testowałem tego w ogóle.

Nowe funkcje C# 5 async działają dokładnie tak samo (w rzeczywistości początkowe wersje kodu kompilatora async były silnie oparte na istniejącej implementacji iteratora), ale z ładniejszą obsługą syntaktyczną.

+1

To całkiem geniusz! Zrobię to zdjęcie i zobaczę jak to działa ... – AlishahNovin

+0

Można go łatwo zaimplementować do wykonania modułu wyliczającego w wątku tła, co czyni bardzo prosty wielowątkowy przepływ pracy interfejsu użytkownika. – SLaks

+0

+1. Drobny punkt: nie masz na myśli zwrotu 'yield return'' w' YourMethod'? –

1

Można to osiągnąć spokój łatwo 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); 

Rozwiązanie łatwo Wagi dla każdej reguły określającej kiedy pokazać okno. Na przykład. Załóżmy, że chcemy zablokować iterację i zażądać potwierdzenia użytkownika co 3 iteracje. Wszystko, co musisz zrobić, to zastąpić warunek i == 3 z i % 3 == 0 (i i != 3 z i % 3 != 0).

0

Sprawdź ten projekt http://silverlightmsgbox.codeplex.com/. Przedstawia prostą, ale reprezentacyjną implementację kilku przydatnych komunikatów, tj. Potwierdzenie, błąd, informacje, dane wprowadzane przez użytkownika itp. I może być dla ciebie pomocna. Powodzenia.

+0

To nie ma nic wspólnego z pytaniem - prosi o blokadę. – SLaks