2014-05-20 51 views
0

我有一个带有边框的MainWindow和一个没有边框的对话窗口ChildWindow。当一个子窗口打开时,不可能移动主窗口或调整它的大小。如何在WPF中移动无边界的子窗口/对话框

我希望应用程序的行为只有一个窗口。

我试图使用一个行为,因为在下面的链接,但只是移动我的子窗口在主窗口内。

DragBahvior

回答

2

有使拖动或无边界Window S的移动更简单的方法。请参阅MSDN上的Window.DragMove Method页面了解更多细节,但总之,你只需要这一行添加到您的代码在鼠标按下事件处理程序之一:

public YourWindow() 
{ 
    InitializeComponent(); 
    MouseLeftButtonDown += YourWindow_MouseLeftButtonDown; 
} 

...

private void YourWindow_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) 
{ 
    DragMove(); // <-- this is all you need to add 
} 

然后用户可以点击Window的任何区域(取决于您放入的内容)并将其拖动到屏幕上。

UPDATE >>>

所以它好像还有更多你的要求比我第一次注意到。为了达到你想要的,你必须做很多事情。首先,您需要将儿童Window定位在相对于MainWindow.xaml Window的特定位置。当你打开它,做这样的事情:

Window window = new Window(); 
window.Top = this.Top + someHorizontalOffsetAmount; 
window.Left = this.Left + someVerticalOffsetAmount; 
window.LocationChanged += Window_LocationChanged; 
window.ShowDialog(); 

然后你需要为Window.LocationChanged事件的处理程序(这是引发时:

Window window = new Window(); 
window.Top = this.Top; 
window.Left = this.Left; 
window.LocationChanged += Window_LocationChanged; 
window.ShowDialog(); 

孩子Window位置可以通过一些设定数额抵消孩子Window被移动):

private void Window_LocationChanged(object sender, EventArgs e) 
{ 
    Window window = (Window)sender; 
    this.Top = window.Top; 
    this.Left = window.Left; 
} 

就是这样!现在两个Window将一起移动。显然,如果在第一个示例中使用了偏移量,则需要在处理程序中使用相同的偏移量。

+0

然后只有我的对话框窗口正在移动。这不是我想要做的。 – Kingpin

1

这听起来像你的对话框是莫代尔,即它与ShowDialog()调用和使用应用程序的其余部分,直到它被驳回,包括移动主窗口阻止你。

如果这不是你想要的行为,则需要通过只调用Show(),或者更好,让您的对话框无模式,因为你似乎希望它表现为一个窗口,为什么不使用WPF作为它的目的是完全摆脱对话?

+0

是的,如果只在我的主窗口中使用控件叠加层来显示内容,那就太好了。令人失望的是我没有这个选项:( – Kingpin

+0

我的窗口显示ShowDialog,但显示不是我想要的行为 – Kingpin

+0

-1对于*不*提供一个问题的答案你有什么理由拒绝投票我的完美工作的答案?报复?......这是一个苦涩noob的行为。不能忍受失去2个声望点而没有得到你的报复?来吧Gaz ...超过8000的声望,你肯定比这更好。不,这是真的很可怜行为,从一个知名的成员真是出乎意料。 – Sheridan

0

所以我终于找到了一个解决方案。我写了一个扩展到Windows类,它已退出复杂:)

namespace MultiWindowWPF 
{ 
    using System; 
    using System.Drawing; 
    using System.Linq; 
    using System.Threading; 
    using System.Windows; 
    using System.Windows.Forms; 
    using System.Windows.Input; 
    using System.Windows.Media; 
    using System.Windows.Threading; 

    using Application = System.Windows.Application; 

    public static class WindowExtensions 
    { 
    /// <summary> 
    /// Shows the Dialog Modal. 
    /// </summary> 
    /// <param name="dialogWindow">The dialog window.</param> 
    public static void ShowModal(this Window dialogWindow) 
    { 
     Window window = Application.Current.Windows.OfType<Window>().FirstOrDefault(w => w.IsKeyboardFocusWithin) ?? Application.Current.MainWindow; 
     IInputElement lastFocused = FocusManager.GetFocusedElement(window); 
     IInputElement lastKeyboardSelected = Keyboard.FocusedElement; 
     EventHandler locationChanged = (sender, args) => ParentWndMove(dialogWindow); 
     SizeChangedEventHandler sizeChanged = (sender, args) => ParentWndMove(dialogWindow); 
     EventHandler stateChanged = (sender, args) => ParentWndStateChanged(dialogWindow); 

     window.LocationChanged += locationChanged; 
     window.SizeChanged += sizeChanged; 
     window.StateChanged += stateChanged; 

     EventHandler close = (sender, args) => 
     { 

     if (dialogWindow.Dispatcher.CheckAccess()) 
     { 
      dialogWindow.Close(); 
     } 
     else 
     { 
      dialogWindow.Dispatcher.Invoke(dialogWindow.Close); 
     } 

     window.LocationChanged -= locationChanged; 
     window.SizeChanged -= sizeChanged; 
     window.StateChanged -= stateChanged; 
     }; 

     EventHandler closed = (sender, args) => 
     { 
     Window self = sender as Window; 
     Enable(); 
     if (self != null) 
     { 
      self.Owner = null; 
     } 
     }; 

     ExitEventHandler exit = (sender, args) => close(sender, args); 

     DependencyPropertyChangedEventHandler isEnabledChanged = null; 
     isEnabledChanged = (o, eventArgs) => 
     { 
      window.Dispatcher.BeginInvoke(
      DispatcherPriority.ApplicationIdle, 
      new Action(
      () => 
       { 
        FocusManager.SetFocusedElement(window, lastFocused); 
      Keyboard.Focus(lastKeyboardSelected); 
     })); 

     ((Window)o).IsEnabledChanged -= isEnabledChanged; 
     }; 
     window.IsEnabledChanged += isEnabledChanged; 
     dialogWindow.Closed += closed; 
     Application.Current.Exit += exit; 

     dialogWindow.Show(); 
     ParentWndMove(dialogWindow); 

     while (Application.Current != null) 
     { 
     DoEvents(); 
     } 
    } 

    private static void DoEvents() 
    { 
     DispatcherFrame frame = new DispatcherFrame(); 
     Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background, new DispatcherOperationCallback(ExitFrame), frame); 
     Dispatcher.PushFrame(frame); 
     Thread.Sleep(10); 
    } 

    private static void Enable() 
    { 
     foreach (Window window in Application.Current.Windows.OfType<Window>().Where(window => !window.OwnedWindows.OfType<Window>().Any())) 
     { 
     window.IsEnabled = true; 
     } 
    } 

    /// <summary> 
    /// Exits the frame. 
    /// </summary> 
    /// <param name="f">The f.</param> 
    /// <returns></returns> 
    public static object ExitFrame(object f) 
    { 
     ((DispatcherFrame)f).Continue = false; 
     return null; 
    } 

    /// <summary> 
    /// Parents the WND state changed. 
    /// </summary> 
    /// <param name="dialogWindow">The dialog window.</param> 
    public static void ParentWndStateChanged(Window dialogWindow) 
    { 
     Window owner = dialogWindow.Owner; 
     if (owner.WindowState != WindowState.Maximized) 
     { 
     dialogWindow.WindowState = owner.WindowState; 
     } 
     ParentWndMove(dialogWindow); 
    } 

    /// <summary> 
    /// Parents the WND move. 
    /// </summary> 
    /// <param name="dialogWindow">The dialog window.</param> 
    public static void ParentWndMove(Window dialogWindow) 
    { 
     Window owner = dialogWindow.Owner; 
     PresentationSource presentationsource = PresentationSource.FromVisual(dialogWindow); 
     Matrix m = presentationsource.CompositionTarget.TransformToDevice; 

     double centerWidth = owner.Left + owner.ActualWidth/2; 
     double centerHeight = owner.Top + owner.ActualHeight/2; 
     if (owner.WindowState == WindowState.Normal) 
     { 
     dialogWindow.Top = centerHeight - dialogWindow.ActualHeight/2; 
     dialogWindow.Left = centerWidth - dialogWindow.ActualWidth/2; 
     } 
     if (owner.WindowState == WindowState.Maximized) 
     { 
     //there is no current main window position to use, center on working screen 
     Rectangle frame = Screen.FromPoint(new System.Drawing.Point((int)(dialogWindow.Left * m.M11), (int)(dialogWindow.Top * m.M22))).Bounds; 

     dialogWindow.Left = frame.X/m.M11 + (frame.Width/m.M11 - dialogWindow.ActualWidth)/2; 
     dialogWindow.Top = frame.Y/m.M22 + (frame.Height/m.M22 - dialogWindow.ActualHeight)/2; 
     } 
    } 
    } 
}