Chr*_*isF 114
将值保存在user.config文件中.
您需要在设置文件中创建值 - 它应该在Properties文件夹中.创建五个值:
Top
类型 double
Left
类型 double
Height
类型 double
Width
类型 double
Maximized
类型bool
- 保持窗口是否最大化.如果要存储更多信息,则需要使用不同的类型或结构.将前两个初始化为0,将后两个初始化为应用程序的默认大小,将最后一个初始化为false.
在构造函数中:
this.Top = Properties.Settings.Default.Top;
this.Left = Properties.Settings.Default.Left;
this.Height = Properties.Settings.Default.Height;
this.Width = Properties.Settings.Default.Width;
// Very quick and dirty - but it does the job
if (Properties.Settings.Default.Maximized)
{
WindowState = WindowState.Maximized;
}
Run Code Online (Sandbox Code Playgroud)
创建一个Window_Closing事件处理程序并添加以下内容:
if (WindowState == WindowState.Maximized)
{
// Use the RestoreBounds as the current values will be 0, 0 and the size of the screen
Properties.Settings.Default.Top = RestoreBounds.Top;
Properties.Settings.Default.Left = RestoreBounds.Left;
Properties.Settings.Default.Height = RestoreBounds.Height;
Properties.Settings.Default.Width = RestoreBounds.Width;
Properties.Settings.Default.Maximized = true;
}
else
{
Properties.Settings.Default.Top = this.Top;
Properties.Settings.Default.Left = this.Left;
Properties.Settings.Default.Height = this.Height;
Properties.Settings.Default.Width = this.Width;
Properties.Settings.Default.Maximized = false;
}
Properties.Settings.Default.Save();
Run Code Online (Sandbox Code Playgroud)
如果用户在关闭应用程序时缩小显示区域(通过断开屏幕或更改屏幕分辨率),这将失败,因此您应该在应用值之前添加检查所需位置和大小是否仍然有效.
Tho*_*que 71
实际上,您不需要使用代码隐藏来执行此操作(保存设置除外).您可以使用自定义标记扩展将窗口大小和位置绑定到如下设置:
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:my="clr-namespace:WpfApplication1"
Title="Window1"
Height="{my:SettingBinding Height}"
Width="{my:SettingBinding Width}"
Left="{my:SettingBinding Left}"
Top="{my:SettingBinding Top}">
Run Code Online (Sandbox Code Playgroud)
您可以在此处找到此标记扩展的代码:http: //www.thomaslevesque.com/2008/11/18/wpf-binding-to-application-settings-using-a-markup-extension/
Ran*_*ngy 41
刚刚写了一篇博客文章,详细介绍了如何以简单而强大的方式完成此任务.它使用Andy提到的GetWindowPlacement
和SetWindowPlacement
函数,但是他提到的一些奇怪的行为被清理了:
https://engy.us/blog/2010/03/08/saving-window-size-and-location-in-wpf-and-winforms/
以下是与其他答案的一些差异:
And*_*ndy 33
虽然你可以"自己动手"并在某个地方手动保存设置,但一般情况下它会起作用,很容易无法正确处理所有情况.通过在exit处调用GetWindowPlacement()并在启动时调用SetWindowPlacement(),让操作系统为您完成工作要好得多.它可以处理所有可能发生的疯狂边缘情况(多个监视器,如果窗口的正常大小保持最大化时保存,等等),这样你就不必这样做了.
此MSDN示例显示如何在WPF应用程序中使用它们.样本不完美(窗口将在第一次运行时在左上角开始尽可能小,并且设置设计器保存类型的值有一些奇怪的行为WINDOWPLACEMENT
),但它至少应该让你开始.
Lan*_*and 27
Thomas上面发布的"长形式"绑定几乎不需要编码,只需确保您具有命名空间绑定:
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:p="clr-namespace:WpfApplication1.Properties"
Title="Window1"
Height="{Binding Source={x:Static p:Settings.Default}, Path=Height, Mode=TwoWay}"
Width="{Binding Source={x:Static p:Settings.Default}, Path=Width, Mode=TwoWay}"
Left="{Binding Source={x:Static p:Settings.Default}, Path=Left, Mode=TwoWay}"
Top="{Binding Source={x:Static p:Settings.Default}, Path=Top, Mode=TwoWay}">
Run Code Online (Sandbox Code Playgroud)
然后保存代码隐藏:
private void frmMain_Closed(object sender, EventArgs e)
{
Properties.Settings.Default.Save();
}
Run Code Online (Sandbox Code Playgroud)
或者,您可能也喜欢以下方法(请参阅源代码)。将 WindowSettings 类添加到您的项目并插入WindowSettings.Save="True"
主窗口的标题:
<Window x:Class="YOURPROJECT.Views.ShellView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Services="clr-namespace:YOURNAMESPACE.Services"
Services:WindowSettings.Save="True">
Run Code Online (Sandbox Code Playgroud)
其中 WindowSettings 定义如下:
using System;
using System.ComponentModel;
using System.Configuration;
using System.Windows;
namespace YOURNAMESPACE.Services
{
/// <summary>
/// Persists a Window's Size, Location and WindowState to UserScopeSettings
/// </summary>
public class WindowSettings
{
#region Fields
/// <summary>
/// Register the "Save" attached property and the "OnSaveInvalidated" callback
/// </summary>
public static readonly DependencyProperty SaveProperty = DependencyProperty.RegisterAttached("Save", typeof (bool), typeof (WindowSettings), new FrameworkPropertyMetadata(OnSaveInvalidated));
private readonly Window mWindow;
private WindowApplicationSettings mWindowApplicationSettings;
#endregion Fields
#region Constructors
public WindowSettings(Window pWindow) { mWindow = pWindow; }
#endregion Constructors
#region Properties
[Browsable(false)] public WindowApplicationSettings Settings {
get {
if (mWindowApplicationSettings == null) mWindowApplicationSettings = CreateWindowApplicationSettingsInstance();
return mWindowApplicationSettings;
}
}
#endregion Properties
#region Methods
public static void SetSave(DependencyObject pDependencyObject, bool pEnabled) { pDependencyObject.SetValue(SaveProperty, pEnabled); }
protected virtual WindowApplicationSettings CreateWindowApplicationSettingsInstance() { return new WindowApplicationSettings(this); }
/// <summary>
/// Load the Window Size Location and State from the settings object
/// </summary>
protected virtual void LoadWindowState() {
Settings.Reload();
if (Settings.Location != Rect.Empty) {
mWindow.Left = Settings.Location.Left;
mWindow.Top = Settings.Location.Top;
mWindow.Width = Settings.Location.Width;
mWindow.Height = Settings.Location.Height;
}
if (Settings.WindowState != WindowState.Maximized) mWindow.WindowState = Settings.WindowState;
}
/// <summary>
/// Save the Window Size, Location and State to the settings object
/// </summary>
protected virtual void SaveWindowState() {
Settings.WindowState = mWindow.WindowState;
Settings.Location = mWindow.RestoreBounds;
Settings.Save();
}
/// <summary>
/// Called when Save is changed on an object.
/// </summary>
private static void OnSaveInvalidated(DependencyObject pDependencyObject, DependencyPropertyChangedEventArgs pDependencyPropertyChangedEventArgs) {
var window = pDependencyObject as Window;
if (window != null)
if ((bool) pDependencyPropertyChangedEventArgs.NewValue) {
var settings = new WindowSettings(window);
settings.Attach();
}
}
private void Attach() {
if (mWindow != null) {
mWindow.Closing += WindowClosing;
mWindow.Initialized += WindowInitialized;
mWindow.Loaded += WindowLoaded;
}
}
private void WindowClosing(object pSender, CancelEventArgs pCancelEventArgs) { SaveWindowState(); }
private void WindowInitialized(object pSender, EventArgs pEventArgs) { LoadWindowState(); }
private void WindowLoaded(object pSender, RoutedEventArgs pRoutedEventArgs) { if (Settings.WindowState == WindowState.Maximized) mWindow.WindowState = Settings.WindowState; }
#endregion Methods
#region Nested Types
public class WindowApplicationSettings : ApplicationSettingsBase
{
#region Constructors
public WindowApplicationSettings(WindowSettings pWindowSettings) { }
#endregion Constructors
#region Properties
[UserScopedSetting] public Rect Location {
get {
if (this["Location"] != null) return ((Rect) this["Location"]);
return Rect.Empty;
}
set { this["Location"] = value; }
}
[UserScopedSetting] public WindowState WindowState {
get {
if (this["WindowState"] != null) return (WindowState) this["WindowState"];
return WindowState.Normal;
}
set { this["WindowState"] = value; }
}
#endregion Properties
}
#endregion Nested Types
}
}
Run Code Online (Sandbox Code Playgroud)
github 上有一个NuGet 项目 RestoreWindowPlace可以为您完成所有这些操作,并将信息保存在 XML 文件中。
要让它在窗口上工作,只需调用以下命令即可:
((App)Application.Current).WindowPlace.Register(this);
在应用程序中,您创建管理窗口的类。有关更多信息,请参阅上面的 github 链接。
小智 5
我根据 RandomEngys 的精彩答案提出了一个更通用的解决方案。它将位置保存到正在运行的文件夹中的文件中,并且您不需要为创建的每个新窗口创建新属性。这个解决方案对我来说非常有用,代码隐藏中的代码最少。
using System;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows;
using System.Windows.Interop;
using System.Xml;
using System.Xml.Serialization;
namespace WindowPlacementNameSpace
{
// RECT structure required by WINDOWPLACEMENT structure
[Serializable]
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
public RECT(int left, int top, int right, int bottom)
{
this.Left = left;
this.Top = top;
this.Right = right;
this.Bottom = bottom;
}
}
// POINT structure required by WINDOWPLACEMENT structure
[Serializable]
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int X;
public int Y;
public POINT(int x, int y)
{
this.X = x;
this.Y = y;
}
}
// WINDOWPLACEMENT stores the position, size, and state of a window
[Serializable]
[StructLayout(LayoutKind.Sequential)]
public struct WINDOWPLACEMENT
{
public int length;
public int flags;
public int showCmd;
public POINT minPosition;
public POINT maxPosition;
public RECT normalPosition;
}
public static class WindowPlacement
{
private static readonly Encoding Encoding = new UTF8Encoding();
private static readonly XmlSerializer Serializer = new XmlSerializer(typeof(WINDOWPLACEMENT));
[DllImport("user32.dll")]
private static extern bool SetWindowPlacement(IntPtr hWnd, [In] ref WINDOWPLACEMENT lpwndpl);
[DllImport("user32.dll")]
private static extern bool GetWindowPlacement(IntPtr hWnd, out WINDOWPLACEMENT lpwndpl);
private const int SW_SHOWNORMAL = 1;
private const int SW_SHOWMINIMIZED = 2;
private static void SetPlacement(IntPtr windowHandle, string placementXml)
{
if (string.IsNullOrEmpty(placementXml))
{
return;
}
byte[] xmlBytes = Encoding.GetBytes(placementXml);
try
{
WINDOWPLACEMENT placement;
using (MemoryStream memoryStream = new MemoryStream(xmlBytes))
{
placement = (WINDOWPLACEMENT)Serializer.Deserialize(memoryStream);
}
placement.length = Marshal.SizeOf(typeof(WINDOWPLACEMENT));
placement.flags = 0;
placement.showCmd = (placement.showCmd == SW_SHOWMINIMIZED ? SW_SHOWNORMAL : placement.showCmd);
SetWindowPlacement(windowHandle, ref placement);
}
catch (InvalidOperationException)
{
// Parsing placement XML failed. Fail silently.
}
}
private static string GetPlacement(IntPtr windowHandle)
{
WINDOWPLACEMENT placement;
GetWindowPlacement(windowHandle, out placement);
using (MemoryStream memoryStream = new MemoryStream())
{
using (XmlTextWriter xmlTextWriter = new XmlTextWriter(memoryStream, Encoding.UTF8))
{
Serializer.Serialize(xmlTextWriter, placement);
byte[] xmlBytes = memoryStream.ToArray();
return Encoding.GetString(xmlBytes);
}
}
}
public static void ApplyPlacement(this Window window)
{
var className = window.GetType().Name;
try
{
var pos = File.ReadAllText(Directory + "\\" + className + ".pos");
SetPlacement(new WindowInteropHelper(window).Handle, pos);
}
catch (Exception exception)
{
Log.Error("Couldn't read position for " + className, exception);
}
}
public static void SavePlacement(this Window window)
{
var className = window.GetType().Name;
var pos = GetPlacement(new WindowInteropHelper(window).Handle);
try
{
File.WriteAllText(Directory + "\\" + className + ".pos", pos);
}
catch (Exception exception)
{
Log.Error("Couldn't write position for " + className, exception);
}
}
private static string Directory => Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
}
}
Run Code Online (Sandbox Code Playgroud)
在后面的代码中添加这两个方法
///This method is save the actual position of the window to file "WindowName.pos"
private void ClosingTrigger(object sender, EventArgs e)
{
this.SavePlacement();
}
///This method is load the actual position of the window from the file
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
this.ApplyPlacement();
}
Run Code Online (Sandbox Code Playgroud)
在 xaml 窗口中添加此内容
Closing="ClosingTrigger"
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
38487 次 |
最近记录: |