如何使ChildWindow阻止

时间:2009-08-13 17:59:23

标签: silverlight silverlight-3.0

ChildWindow是一个模态窗口,但它不会阻止。有没有办法让它阻止?我基本上想要一个ShowDialog()方法,它将调用ChildWindow.Show(),但在用户关闭ChildWindow之前不会返回。我尝试使用Monitor.Enter()来阻止ChildWindow.Show(),但是ChildWindow从未呈现过,浏览器只是挂起。有人有什么想法吗?

6 个答案:

答案 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);

根据模态中显示的内容,我动态地将控件添加到模态布局中。显然,这不是一个优雅的解决方案,但至少它是有效的。