在WPF应用中保存窗口位置和大小的最佳方法是什么?
目前,我正在保存WPF应用程序的窗口大小和位置。以下是我处理的事件:
(我从一个例子中复制了这个)。
问题是,当窗口最小化并恢复时,将检索最后一个WindowClosing的设置。
现在,StateChanged事件在窗口最小化后触发,所以它似乎不是我需要的。
由于
答案 0 :(得分:9)
帮助您和您的用户,并使用LocationChanged事件和SizeChanged事件来保存当时的设置。如果进程异常退出并且设置没有得到保存(咳嗽......探险家......咳嗽......),那么没有什么比应用程序更容易烦恼了。
然后在保存设置之前检查以确保WindowState == Normal。显然,保存最小化或最大化窗口的位置毫无意义。
关于何时加载设置,您可以在InitializeComponent调用之后在构造函数中执行此操作,或者可以使用Initialized事件。没有真正的理由使用SourceInitialized事件,除非你直接对HWND做了一些不必要的事情。
答案 1 :(得分:1)
使用WindowInteropHelper对象获取窗口句柄并使用Screen.FromHandle方法获取窗口所在的实际屏幕。保存时请务必保存屏幕边界,以防它不再存在。
将屏幕恢复到以前的状态时需要注意的一点是,必须在创建窗口句柄后完成,因此在构造函数中无法执行此操作,否则在多个监视器情况下无法正常工作。尝试在SourceInitialized回调
上执行此操作答案 2 :(得分:0)
你是通过数据绑定吗?这就是我做窗口大小和位置的方式。我通常有一个UserConfig.xml文件保存在用户配置文件中。然后我在那里创建元素,因为我在程序中对它们进行了数据处理。我有Application.xaml资源字典引用该文件,并且我想要设置为XPath的所有设置都是XML。然后我只在退出时保存内存中的xml文档。只有一个事件可以处理,没有乱七八糟,没有大惊小怪。
您可以将其扩展为包含与UI相关的任意数量的设置。添加管道设置有点困难,但并非如此。
答案 3 :(得分:0)
我有一个保存大小和状态的解决方案,你可以扩展它以保存位置。它是使用行为完成的。简单地绑定宽度和高度没有按预期工作,因为它会覆盖"正常"具有最大尺寸的州的大小。这就是if(state == normal)
我的窗口Config
上有一个DataContext
属性。
您需要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中加载并保存配置。
答案 4 :(得分:0)
我喜欢 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 - 项目的属性命名空间。