【问题标题】:Saving WPF WIndow and Position保存 WPF 窗口和位置
【发布时间】:2011-02-20 06:13:04
【问题描述】:

在 WPF 应用程序中保存窗口位置和大小的最佳方式是什么?

目前,我正在保存 WPF 应用程序的窗口大小和位置。以下是我处理的事件:

  1. SourceInitialized : 保存的信息被加载到窗口中
  2. WindowClosing : 当前信息保存到后备存储中

(我从一个例子中复制了这个)。

问题是,当窗口最小化并恢复时,会检索上次 WindowClosing 的设置。

现在,StateChanged 事件在窗口最小化后触发,所以它似乎不是我需要的。

谢谢

【问题讨论】:

    标签: wpf windows


    【解决方案1】:

    帮您自己和您的用户一个忙,并使用LocationChanged 事件和SizeChanged 事件来保存当时的设置。如果进程异常退出并且设置没有保存,没有什么比应用程序失忆更烦人的了(咳……explorer……咳……)

    然后在保存设置之前检查以确保 WindowState == Normal。显然,保存最小化或最大化窗口的位置毫无意义。

    至于何时加载设置,您可以在 InitializeComponent 调用之后的构造函数中执行,也可以使用 Initialized 事件。没有真正的理由使用 SourceInitialized 事件,除非您直接使用 HWND 做一些不必要的事情。

    【讨论】:

    • 最大化窗口的位置很重要:它是在哪个显示器上最大化的?
    • 好点。但无论如何存储监视器 ID 和最大化状态而不是最大化边界可能更好,以防分辨率发生变化。
    【解决方案2】:

    使用WindowInteropHelper 对象获取窗口句柄并使用Screen.FromHandle 方法获取窗口所在的实际屏幕。保存时请确保同时保存屏幕边界,以防它不再存在。

    将屏幕恢复到以前的状态时需要注意的是,它必须在创建窗口句柄后完成,因此不能在构造函数中执行此操作,否则在多个监视器情况下将无法正常工作。尝试在 SourceInitialized 回调上执行此操作

    【讨论】:

      【解决方案3】:

      你是通过数据绑定来做这件事的吗?这就是我调整窗口大小和位置的方式。我通常有一个保存在用户配置文件中的 UserConfig.xml 文件。然后我在那里创建元素,因为我在程序中对它们进行数据绑定。我有 Application.xaml 资源字典引用该文件,并且我想要设置为 XML 中的 XPaths 的所有设置。然后我只是在退出时保存内存中的 xml 文档。只需处理一个事件,没有混乱,没有大惊小怪。

      您可以将其扩展为包含尽可能多的 UI 设置。添加管道设置有点困难,但不是很困难。

      【讨论】:

        【解决方案4】:

        我有一个保存大小和状态的解决方案,你可以扩展它来保存位置。它是使用行为完成的。简单地绑定宽度和高度没有按预期工作,因为它会用最大化的大小覆盖“正常”状态的大小。这就是为什么会有一些额外的检查,比如if(state == normal)

        在我的窗口的DataContext 上有一个Config 属性。 您需要引用 System.Windows.Interactivity 来执行此操作。

        public class MainWindowSaveStateBehavior : Behavior<Window>
        {
            public Config Config
            {
                get { return (Config)GetValue(ConfigProperty); }
                set { SetValue(ConfigProperty, value); }
            }
        
            public static readonly DependencyProperty ConfigProperty =
                DependencyProperty.Register("Config", typeof(Config), typeof(MainWindowSaveStateBehavior), new PropertyMetadata(Config_Changed));
        
            private static void Config_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                var b = d as MainWindowSaveStateBehavior;
                if(e.NewValue != null) b.LoadSettings();
            }
        
            protected override void OnAttached()
            {
                base.OnAttached();
                AssociatedObject.SizeChanged += Window_SizeChanged;
                AssociatedObject.StateChanged += Window_StateChanged;
                LoadSettings();
            }
        
            bool _initialized = false;
        
            private void Window_StateChanged(object sender, EventArgs e)
            {
                SaveSettings();
            }
        
            private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
            {
                SaveSettings();
            }
        
            private void LoadSettings()
            {
                if (Config == null) return;
        
                AssociatedObject.Width = Config.WindowWidth;
                AssociatedObject.Height = Config.WindowHeight;
                AssociatedObject.WindowState = Config.WindowState;
        
                _initialized = true;
            }
        
            private void SaveSettings()
            {
                if (Config == null || !_initialized) return;
        
                Config.WindowState = AssociatedObject.WindowState;
                if(AssociatedObject.WindowState == WindowState.Normal)
                {
                    Config.WindowWidth = AssociatedObject.Width;
                    Config.WindowHeight = AssociatedObject.Height;
                }
            }
        }
        

        在 Xaml 中通过添加命名空间来使用该行为

        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
        xmlns:b="<the namespace your behavior lives in>"
        

        然后附加行为

        <i:Interaction.Behaviors>
            <b:MainWindowSaveStateBehavior Config="{Binding Config}" />
        </i:Interaction.Behaviors>
        

        然后,您只需在启动/关闭时在 DataContext 中加载和保存配置。

        【讨论】:

          【解决方案5】:

          我喜欢 CodeWarriors 的回答。我使用 TwoWay 绑定到应用程序设置:

          Height="{Binding Source={x:Static p:Settings.Default}, Path=WindowHeight, Mode=TwoWay}"
          Width="{Binding Source={x:Static p:Settings.Default}, Path=WindowWidth, Mode=TwoWay}"
          Top="{Binding Source={x:Static p:Settings.Default}, Path=WindowTop, Mode=TwoWay}"
          Left="{Binding Source={x:Static p:Settings.Default}, Path=WindowLeft, Mode=TwoWay}"
          

          其中 p - 项目的属性命名空间。

          【讨论】:

            猜你喜欢
            • 2012-02-22
            • 1970-01-01
            • 1970-01-01
            • 2011-07-19
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-04-27
            相关资源
            最近更新 更多