WPF维护多个窗口的窗口大小

时间:2015-03-06 10:57:13

标签: c# wpf mvvm

我正在开发一个WPF应用程序(使用MVVM),它包含几个窗口。所有窗口都指定了相同的尺寸,并在所有者屏幕的中心打开。用户还可以调整窗口的大小。我现在需要两件事。

  1. 在用户调整任何窗口大小的情况下,在所有窗口中保持相同的大小。
  2. 如果用户拖动屏幕上的任何窗口,则在所有窗口中保持相同的位置。
  3. 例如,请考虑以下工作流程:MainWindow - > ChildWindow1 - > ChildWindow2。在MainWindow上单击按钮时,将打开ChildWindow1。在ChildWindow1上单击按钮,将打开ChildWindow2。窗口相互打开,一旦关闭窗口,就会显示上一个窗口。假设用户现在调整ChildWindow2的大小。我希望同样反映在MainWindow和ChildWindow1上,这样当用户关闭ChildWindow2时,ChildWindow1将与调整大小的ChildWindow2的大小相同。这会让用户觉得他们在同一个窗口工作。

    此外,如果用户拖动任何Windows,我希望父窗口的位置更改并与子窗口的位置相对应。

    我怎样才能实现这两件事?

2 个答案:

答案 0 :(得分:0)

我采用的方式是使用WPF行为,它允许您封装特定于UI的(即非View Modelish)行为。

我不知道你的确切要求(这些是应用程序中唯一的窗口吗?它们是否总是同步?)但一般的方法是创建一个SynchronizedWindowBehavior,我将附加到不同的Windows。

此行为将访问某种中央WindowSynchronizationService,一个事件聚合器或单件服务(可能在您的DI容器中注册),它发布解耦事件。每个行为实例都会侦听附加窗口的Move和Resize事件,并在聚合器上发布事件。其他行为实例使用此事件并相应地调整其大小/移动其附加窗口。

这是一个很好的教程,既可以定义Blend行为,也可以将它们连接到窗口,还可以(特别)监听Window resize事件:http://10rem.net/blog/2010/01/09/a-wpf-behavior-for-window-resize-events-in-net-35

答案 1 :(得分:0)

我会创建一个可以订阅和调用操作的类。这个类看起来像:

internal class ActionService<T>
{
    private static ActionService<T> instance;
    private readonly List<ServiceAction<T>> registeredActions;

    private ActionService()
    {
        registeredActions = new List<ServiceAction<T>>();       
    }

    internal static ActionService<T> Instance()
    {
        return instance ?? (instance = new ActionService<T>());
    }

    internal void Subscribe(string actionName, Action<T> action)
    {
        registeredActions.Add(new ServiceAction<T>(actionName, action));
    }

    internal void Unsubscribe(string actionName)
    {
        registeredActions.RemoveAll(action => action.ActionName == actionName);
    }

    internal void Invoke(string actionName, T parameter)
    {
        foreach (ServiceAction<T> action in registeredActions.Where(action => action.ActionName == actionName).ToArray())
        {
            action.Action.Invoke(parameter);
        }
    }

    private class ServiceAction<TSub>
    {
        internal ServiceAction(string actionName, Action<TSub> action)
        {
            ActionName = actionName;
            Action = action;
        }

        internal string ActionName { get; private set; }
        internal Action<TSub> Action { get; private set; }
    }
}

在每个ViewModel的构造函数中,您可以调用类似于:

的内容
ActionService<Thickness>.Instance.Subscribe("SizeChanged", SizeChaned);

第二个参数是一个函数,因此您必须将以下内容添加到ViewModel:

private void SizeChanged(Thickness thickness)
{
  // Change the size to the passed value
}

现在,如果有人更改了您可以调用的任何窗口的大小:

ActionService<Thickness>.Instance.Invoke("SizeChanged", ACTUALSIZE_AS_THICKNESS);

您可以在想要通过ViewModel或Model-Borders进行通信的任何地方使用此ActionService