ChildWindow是一个模态窗口,但它不会阻止。有没有办法让它阻止?我基本上想要一个ShowDialog()方法,它将调用ChildWindow.Show(),但在用户关闭ChildWindow之前不会返回。我尝试使用Monitor.Enter()来阻止ChildWindow.Show(),但是ChildWindow从未呈现过,浏览器只是挂起。有人有什么想法吗?
答案 0 :(得分:7)
我不相信它支持这种行为。您可以在CodePlex上vote for it。根据您的需要,您可以使用look at some of Tim Heuer's workarounds here,也可以使用其他自定义控件,例如Silverlight Modal Control (on CodePlex)。
答案 1 :(得分:5)
您无法在Silverlight中执行您要执行的操作。您对UI所做的任何更改都将在UI线程上运行。如果您阻止UI线程,则用户无法与浏览器进行交互,因此他们无法采取任何措施来取消阻止该线程。
如果您真的想要创建阻止对话框窗口,唯一的方法是从非UI线程。例如。你可以创建一个类似于:
的方法 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线程上触发的事件)。
或者,您应该考虑使逻辑异步,而不是强制它是同步的。
答案 2 :(得分:3)
如果要在子窗口关闭时执行某些操作,请使用以下代码。在调用之前隐藏不需要的控件,并在关闭子窗口时显示,简单:)
ChildWindow cw = new ChildWindow();
cw.Closed += new EventHandler(cw_Closed);
cw.Show();
答案 3 :(得分:0)
您可以尝试始终取消关闭事件并稍后设置DialogResult。
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();
}
答案 4 :(得分:0)
使用async and await in Silverlight 5,您可以轻松创建可以阻止的静态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...
}
答案 5 :(得分:-1)
我通过将自定义控件具有垂直和水平对齐方式作为拉伸来创建“阻塞”模式对话框,然后将其添加为当前控件布局的子项。
e.g。
<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);
根据模态中显示的内容,我动态地将控件添加到模态布局中。显然,这不是一个优雅的解决方案,但至少它是有效的。