【问题标题】:WPF MVVM How to re-center application window after view changes?WPF MVVM 如何在视图更改后重新居中应用程序窗口?
【发布时间】:2014-03-26 07:10:24
【问题描述】:

我正在使用本机 WPF 和 MVVM 开发一个非常简单的应用程序。主要的“shell”视图使用我认为是一种常见的基本模式,其中它包含一个 ContentControl,它是数据绑定到活动视图模型的,它通过数据模板注入视图。这是它的缩略版:

<Window.DataContext>
    <local:ShellViewModel/>
</Window.DataContext>

<Window.Resources>
    <DataTemplate DataType="{x:Type local:DbConfigViewModel}">
        <local:DbConfigView/>
    </DataTemplate>
    <DataTemplate DataType="{x:Type local:AuthenticationViewModel}">
        <local:AuthenticationView/>
    </DataTemplate>
</Window.Resources>

<DockPanel>
    <ContentControl Content="{Binding CurrentViewModel}"/>
</DockPanel>

此窗口设置为根据视图自动调整大小,并设置为居中启动。这适用于初始视图。不过,有些视图要大得多,当它们变得活跃时,它就会成为一个 UI 问题。我需要做的是让应用程序在视图更改时重新居中。

到目前为止,我尝试的是对主窗口的 Left 和 Top 属性进行数据绑定,如下所示:

<Window (....)
    Width="auto" Height="auto"
    SizeToContent="WidthAndHeight"
    WindowStartupLocation="CenterScreen"
    Left="{Binding WindowLeft}"
    Top="{Binding WindowTop}">

我的导航与主 Windows 视图模型中的一个方法相关联,因此在该方法中,将新视图模型设置为 CurrentViewModel 属性后,我会调用此方法:

    private void CenterWindow()
    {
        Rect workArea = System.Windows.SystemParameters.WorkArea;
        WindowLeft = (workArea.Width - Application.Current.MainWindow.Width) / 2 + workArea.Left;
        WindowTop = (workArea.Height - Application.Current.MainWindow.Height) / 2 + workArea.Top;
    }

这似乎应该可以工作,但似乎正在发生的是 MainWindow.Width 和 Height 尚未调整,因此它基于上一个视图而不是我刚刚实例化的视图居中。

那么是否有一些事件或其他地方可以调用此代码,以便在呈现新视图后发生?这甚至是正确的方法吗?

【问题讨论】:

  • 如果您确定用户无法调整窗口大小,我想您应该能够通过为主窗口创建 OnSizeChanged 覆盖并在那里调用 CenterWindow 来做到这一点?注意:MSDN 将WorkArea 描述为获取主显示监视器上工作区域的大小。因此您的方法在多个监视器系统上并不总是如您所愿
  • 我曾考虑过 OnSizeChanged 事件,但我不想干扰客户端调整窗口大小的能力。作为最后的手段,我们会考虑移除这个能力,但如果可能的话,我想找到另一种方法。感谢您提供有关 WorkArea 的提示,我不知道。
  • 您能告诉我任何具有这种行为的专业应用程序吗?我猜你不能,那是因为这是一个坏主意。调整应用程序的大小Window(除非它是一个孩子Window)应该是开发团队的关注点。制作一个流畅的 UI,尽可能地适合所有视图,并将 Window 的大小留给用户...正如 应有的。我想说的是,您提出这个问题的事实表明您的 UI 设计有问题。
  • @Sheridan 虽然我通常会同意你的观点,但这个特殊的应用程序是我正在为我们的工程服务团队开发的一个非常简单的实用程序。应用程序的核心是一个单一的视图,但是我需要他们在到达那里之前通过 2 个简短的对话。与其使用传统的对话服务,我认为只需像我所示的那样交换视图就足够简单了。这是完成任务的一种快速简单的方法,但我只需要解决这个细微差别。
  • 那是我无法理解的一点...流畅的 WPF UI 将适合包含 Window 提供的任何空间...看起来好像 是你实际上 缺少的,以及你应该如何解决这个细微差别,正如你所说的那样。

标签: wpf mvvm centering


【解决方案1】:

然后您需要在窗口中订阅 SizeChanged:

private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
{
    if (e.PreviousSize == e.NewSize)
        return;

    var w = SystemParameters.PrimaryScreenWidth;
    var h = SystemParameters.PrimaryScreenHeight;

    this.Left = (w - e.NewSize.Width) / 2;
    this.Top = (h - e.NewSize.Height) / 2;
}

如果你想在你的 viewModel 中使用交互事件,你可以使用它

【讨论】:

  • 如果窗口不在主屏幕上怎么办?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-24
  • 2016-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多