我正在尝试使用Silverlight的ChildWindow
对象进行确认对话。
理想情况下,我希望它像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.HasResult
将是错误的,并且循环将继续超过3。
我只是想知道,我怎么能正确地解决这个问题。 Silverlight是单线程的,所以我不能让线程进入睡眠状态,然后在我准备就绪时将其唤醒,所以我只是想知道是否还有其他人可以推荐的东西?
我考虑过颠倒逻辑 - 即将我想要发生的操作传递给Yes / No事件,但在我的具体情况下,这不会有效。
提前致谢!
答案 0 :(得分: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 :(得分: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 == 0
(以及i != 3
替换为i % 3 != 0
)。
答案 2 :(得分:0)
查看此项目http://silverlightmsgbox.codeplex.com/。它提供了几个有用的消息框的简单但可呈现的实现,即确认,错误,信息,用户输入等,可能对您有所帮助。祝你好运。