我有一个带有Border的MainWindow和一个没有Border的Dialog的ChildWindow。当子窗口打开时,无法移动主窗口或调整其大小。
我希望应用程序表现得像只有一个Window。
我试图使用以下链接中的行为,但这只是在主窗口内移动我的子窗口。
答案 0 :(得分:3)
有一种更简单的方法可以启用拖动或移动无边框Window
。有关详细信息,请参阅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
的任何区域(取决于您放入其中的内容)并将其拖动到屏幕上。
更新&gt;&gt;&gt;
因此,您的要求似乎比我第一次注意到的更多。要实现您想要的目标,您必须做很多事情。首先,您需要将孩子Window
放在相对于MainWindow.xaml Window
的特定地点中。当你打开它时,做这样的事情:
Window window = new Window();
window.Top = this.Top;
window.Left = this.Left;
window.LocationChanged += Window_LocationChanged;
window.ShowDialog();
子Window
位置可能会被某个设定金额抵消:
Window window = new Window();
window.Top = this.Top + someHorizontalOffsetAmount;
window.Left = this.Left + someVerticalOffsetAmount;
window.LocationChanged += Window_LocationChanged;
window.ShowDialog();
然后你需要Window.LocationChanged
事件的处理程序(在移动子Window
时引发):
private void Window_LocationChanged(object sender, EventArgs e)
{
Window window = (Window)sender;
this.Top = window.Top;
this.Left = window.Left;
}
那就是它!现在两个Window
将一起移动。显然,如果在第一个示例中使用偏移量,那么您需要在Window_LocationChanged
处理程序中使用相同的偏移量。
答案 1 :(得分:1)
听起来你的对话框是模态,即它是用ShowDialog()
调用的,并停止使用应用程序的其余部分直到它被解除,包括移动主窗口。
如果这不是您想要的行为,那么您需要通过调用Show()
来建立对话无模式,或者更好,因为您似乎希望它表现为一个窗口,为什么不按原样使用WPF并完全摆脱对话?
答案 2 :(得分: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;
}
}
}
}