我正在开发一个WPF应用程序(使用MVVM),它包含几个窗口。所有窗口都指定了相同的尺寸,并在所有者屏幕的中心打开。用户还可以调整窗口的大小。我现在需要两件事。
例如,请考虑以下工作流程:MainWindow - > ChildWindow1 - > ChildWindow2。在MainWindow上单击按钮时,将打开ChildWindow1。在ChildWindow1上单击按钮,将打开ChildWindow2。窗口相互打开,一旦关闭窗口,就会显示上一个窗口。假设用户现在调整ChildWindow2的大小。我希望同样反映在MainWindow和ChildWindow1上,这样当用户关闭ChildWindow2时,ChildWindow1将与调整大小的ChildWindow2的大小相同。这会让用户觉得他们在同一个窗口工作。
此外,如果用户拖动任何Windows,我希望父窗口的位置更改并与子窗口的位置相对应。
我怎样才能实现这两件事?
答案 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
。