ChildWindow是一个模态窗口,但它不会阻塞。有没有办法使它阻塞?我基本上想要一个ShowDialog()方法,该方法将调用ChildWindow.Show(),但在用户关闭ChildWindow之前不返回。我尝试使用Monitor.Enter()在ChildWindow.Show()后进行阻塞,但ChildWindow从未呈现,浏览器只是挂起了。有人有什么想法吗?
ChildWindow是一个模态窗口,但它不会阻塞。有没有办法使它阻塞?我基本上想要一个ShowDialog()方法,该方法将调用ChildWindow.Show(),但在用户关闭ChildWindow之前不返回。我尝试使用Monitor.Enter()在ChildWindow.Show()后进行阻塞,但ChildWindow从未呈现,浏览器只是挂起了。有人有什么想法吗?
private void ShowModalDialog()
{
AutoResetEvent waitHandle = new AutoResetEvent(false);
Dispatcher.BeginInvoke(() =>
{
ChildWindow cw = new ChildWindow();
cw.Content = "Modal Dialog";
cw.Closed += (s, e) => waitHandle.Set();
cw.Show();
});
waitHandle.WaitOne();
}
这种方法会显示一个对话框窗口,并且在对话框窗口关闭之前不会返回。但是,这种方法只能从非UI线程中调用。如果从UI线程中调用它将导致死锁(因为UI线程正在等待只能在UI线程上触发的事件)。
或者,您应该考虑使您的逻辑异步而不是强制它同步。
ChildWindow cw = new ChildWindow();
cw.Closed += new EventHandler(cw_Closed);
cw.Show();
void ConfigTemplatePopup_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
if (tmpDialogResult != null || DialogResult == true) return;
tmpDialogResult = DialogResult; //this is a field
e.Cancel = true;
var myMessageBox = new WspMessageBox("Are you sure you want to close?", true);
myMessageBox.Closed += (s, e2) =>
{
if (wspMessageBox.DialogResult == true)
{
DialogResult = tmpDialogResult;
}else
{
tmpDialogResult = null;
}
};
myMessageBox.Show();
}
使用Silverlight 5中的async和await,您可以轻松创建一个静态Show方法,该方法可以是阻塞的,例如:
public partial class MyDialog {
MyResultType result;
readonly AutoResetEvent waitHandle;
MyDialog() {
InitializeComponent();
waitHandle = new AutoResetEvent(false);
}
public static Task<MyResultType> Show() {
var dialog = new MyDialog();
dialog.Show();
dialog.Closed += (s, e) => dialog.waitHandle.Set();
return Task<MyResultType>.Factory.StartNew(() => {
dialog.waitHandle.WaitOne(); return dialog.result; });
}
void OkButton_Click(object sender, RoutedEventArgs e) {
result = new MyResultType();
// Initialize result...
Close();
}
}
然后像这样调用对话框
public async void TestDialog() {
var result = await ConfirmBox.Show();
// This code will be performed after the Dialog is closed.
// use result...
}
Task<T>.Factory.StartNew()
的输出是不可等待的。此外,虽然这个答案引入了async/await模式,但它并没有解决不能阻塞UI线程而不冻结浏览器的根本问题,因此这种方法在Keith Mahoney的解决方案之上并没有提供真正的价值。 - Rob Lyndon <Grid x:Name="LayoutRoot" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Rectangle Fill="LightBlue" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Opacity="0.3" />
</Grid>
然后在自定义控件中
Utilities.UITools.MessageBox x = new Utilities.UITools.MessageBox();
x.SetError(e.Result);
this.LayoutRoot.Children.Add(x);