que tenían el mismo problema y aplicado del comportamiento de diálogo modal como se describe en este post: http://social.msdn.microsoft.com/Forums/vstudio/en-US/820bf10f-3eaf-43a8-b5ef-b83b2394342c/windowsshowmodal-to-parentowner-window-only-not-entire-application?forum=wpf
También probé un enfoque de múltiples hilos de interfaz de usuario, pero esto causó problemas con terceros bibliotecas (Caliburn micro & telerik controles wpf), ya que no están diseñados para ser utilizados en múltiples subprocesos de UI. Es posible hacer que funcionen con múltiples subprocesos de UI, pero prefiero una solución más simple ...
Si implementa el diálogo como se describe, ya no puede usar la propiedad DialogResult, ya que causaría un "DialogResult can establecerse solo después de que se crea Window y se muestra como diálogo "excepción". Simplemente implemente su propiedad y úsela en su lugar.
son necesarios los siguientes ventanas de referencia de la API:
/// <summary>
/// Enables or disables mouse and keyboard input to the specified window or control.
/// When input is disabled, the window does not receive input such as mouse clicks and key presses.
/// When input is enabled, the window receives all input.
/// </summary>
/// <param name="hWnd"></param>
/// <param name="bEnable"></param>
/// <returns></returns>
[DllImport("user32.dll")]
private static extern bool EnableWindow(IntPtr hWnd, bool bEnable);
A continuación, utilice la siguiente:
// get parent window handle
IntPtr parentHandle = (new WindowInteropHelper(window.Owner)).Handle;
// disable parent window
EnableWindow(parentHandle, false);
// when the dialog is closing we want to re-enable the parent
window.Closing += SpecialDialogWindow_Closing;
// wait for the dialog window to be closed
new ShowAndWaitHelper(window).ShowAndWait();
window.Owner.Activate();
Este es el controlador de eventos, que vuelve a habilitar la ventana padre, cuando el diálogo se cierra:
private void SpecialDialogWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
var win = (Window)sender;
win.Closing -= SpecialDialogWindow_Closing;
IntPtr winHandle = (new WindowInteropHelper(win)).Handle;
EnableWindow(winHandle, false);
if (win.Owner != null)
{
IntPtr parentHandle = (new WindowInteropHelper(win.Owner)).Handle;
// reenable parent window
EnableWindow(parentHandle, true);
}
}
Y este es el ShowAndWaitHelper necesario para lograr el comportamiento de diálogo modal (Esto bloquea la ejecución del hilo, pero aún ejecuta el ciclo del mensaje.
private sealed class ShowAndWaitHelper
{
private readonly Window _window;
private DispatcherFrame _dispatcherFrame;
internal ShowAndWaitHelper(Window window)
{
if (window == null)
{
throw new ArgumentNullException("window");
}
_window = window;
}
internal void ShowAndWait()
{
if (_dispatcherFrame != null)
{
throw new InvalidOperationException("Cannot call ShowAndWait while waiting for a previous call to ShowAndWait to return.");
}
_window.Closed += OnWindowClosed;
_window.Show();
_dispatcherFrame = new DispatcherFrame();
Dispatcher.PushFrame(_dispatcherFrame);
}
private void OnWindowClosed(object source, EventArgs eventArgs)
{
if (_dispatcherFrame == null)
{
return;
}
_window.Closed -= OnWindowClosed;
_dispatcherFrame.Continue = false;
_dispatcherFrame = null;
}
}
Tu respuesta ha sido increíblemente útil. Hice una versión del método de extensión 'async Task ShowDialogAsync' de esto. –
jnm2