6

ChildWindowSilverlight のオブジェクトを使用して確認ダイアログを表示しようとしています。

MessageBox.Show()理想的には、ユーザーからの入力が受信されるまでアプリケーション全体が停止するように動作するようにしたいと思います。

例えば:

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

ユーザーがOKを押すと、反復は3で停止します...

ただし、次のように何かを行う場合:

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.HasResultfalse になり、ループは 3 を超えて継続します。

どうすればこれを適切に行うことができるのか、ただ疑問に思っています。Silverlight はシングル スレッドであるため、スレッドをスリープ状態にし、準備ができたら起動することはできません。

ロジックを逆にすること、つまり、発生させたいアクションを Yes/No イベントに渡すことを検討しましたが、私の特定のケースでは、これはうまくいきません。

前もって感謝します!

4

3 に答える 3

12

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コンパイラコードの初期バージョンは、既存のイテレータの実装に大きく基づいていました)、構文のサポートが向上しています。

于 2010-01-21T22:48:14.490 に答える
1

RX フレームワークを使用すると、この静かさを簡単に実現できます。

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 == 0(および)i != 3に置き換えるだけですi % 3 != 0

于 2010-01-22T22:53:01.617 に答える
0

このプロジェクトhttp://silverlightmsgbox.codeplex.com/をチェックしてください。これは、確認、エラー、情報、ユーザー入力など、いくつかの便利なメッセージ ボックスのシンプルだが見栄えのする実装を示しており、役に立つかもしれません。幸運を。

于 2011-01-18T00:13:41.703 に答える