2010-01-21 2 views
6

Я пытаюсь сделать диалог подтверждения с помощью объекта Silverlight ChildWindow.Silverlight Confirm Dialog to Pause Thread

В идеале, я хотел бы, чтобы он работал как MessageBox.Show(), где все приложение останавливается до тех пор, пока от пользователя не будет получен вход.

Например:

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

бы остановить итерации в 3, если пользователь нажимает кнопку OK ...

Однако, если бы я сделать что-то вдоль линий:

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

Это явно не сработало бы, так как нить не остановилась ... confirm.DialogResult.HasResult будет ложным, и цикл продолжится до 3.

Мне просто интересно, как я могу это сделать. Silverlight однопоточен, поэтому я не могу просто поставить поток спать, а затем разбудить его, когда я буду готов, поэтому мне просто интересно, есть ли что-нибудь еще, что люди могли бы порекомендовать?

Я решил обратить вспять логику, то есть передать действия, которые я хочу встретить в событиях Yes/No, но в моем конкретном случае это не совсем сработало.

Заранее благодарен!

ответ

11

Я не думаю, что вы сможете заблокировать свой код в цикле сообщений так, как вы можете с помощью WinForms 'ShowDialog.

Однако, вы можете неправильно использовать итераторы для достижения того же эффекта:

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

Чтобы использовать эту систему, можно было бы написать ExecAction(YourMethod());. Обратите внимание, что это будет полублокирующий вызов, и я вообще не тестировал это.

Функции C# 5 async работают точно так же (на самом деле исходные версии кода компилятора async были в значительной степени основаны на существующей реализации итератора), но с более сильной синтаксической поддержкой.

+1

Это довольно гений! Я дам этот снимок и посмотрю, как хорошо он работает ... – AlishahNovin

+0

Его можно легко принять, чтобы выполнить перечислитель в фоновом потоке, создав очень простой многопоточный рабочий процесс пользовательского интерфейса. – SLaks

+0

+1. Незначительная точка: вы не имеете в виду 'yield return confirm' в' YourMethod'? –

1

Вы можете достичь этого тихого легко с 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); 

решение легко масштабируется для любого правила, определяющего, когда нужно показать диалог. Например. предположим, что мы хотим заблокировать итерацию и запросить подтверждение пользователя каждые 3 итерации. Все, что вам нужно сделать, это заменить условие i == 3 на i % 3 == 0i != 3 с i % 3 != 0).

0

Посмотрите этот проект http://silverlightmsgbox.codeplex.com/. Он представляет собой простую, но презентабельную реализацию нескольких полезных ящиков сообщений, то есть подтверждения, ошибки, информации, ввода пользователя и т. Д. И может быть вам полезен. Удачи.

+0

Это не имеет никакого отношения к вопросу - он просит заблокировать звонок. – SLaks

 Смежные вопросы

  • Нет связанных вопросов^_^