Сохранение окна и положения WPF - PullRequest
3 голосов
/ 17 мая 2010

Как лучше всего сохранить положение и размер окна в приложении WPF?

В настоящее время я сохраняю размер окна и положение приложения WPF. Вот события, которые я обрабатываю:

  1. SourceInitialized: сохраненная информация загружается в окно
  2. WindowClosing: текущая информация сохраняется в резервном хранилище

(я скопировал это из примера).

Проблема в том, что когда окно свернуто и восстановлено, извлекаются настройки из последнего закрытия окна.

Теперь событие StateChanged запускается ПОСЛЕ того, как окно свернулось, так что оно, похоже, не то, что мне нужно.

Спасибо

Ответы [ 4 ]

9 голосов
/ 17 мая 2010

Сделайте себе и своим пользователям услугу и используйте событие LocationChanged и событие SizeChanged , чтобы сохранить настройки в это время. Нет ничего более раздражающего, чем приложение, которое получает амнезию, если процесс завершается ненормально и настройки не сохраняются (кашель ... исследователь ... кашель ...)

Затем просто убедитесь, что WindowState == Normal перед сохранением настроек. Очевидно, что бессмысленно сохранять положение свернутого или развернутого окна.

Что касается того, когда загружать настройки, то вы можете просто сделать это в конструкторе после вызова InitializeComponent или использовать событие Initialized. Нет реальной причины использовать событие SourceInitialized, если вы не делаете что-то непосредственно с HWND, в чем не должно быть необходимости.

1 голос
/ 24 ноября 2010

Используйте объект WindowInteropHelper , чтобы получить дескриптор окна, и используйте метод Screen.FromHandle, чтобы получить реальный экран, на котором находится окно. При сохранении также сохраняйте границы экрана на тот случай, если он больше не существует.

Одно предостережение при восстановлении экрана до его прежнего состояния - это должно быть сделано после того, как дескриптор окна создан, поэтому не может сделать это в конструкторе, иначе не будет работать должным образом в нескольких ситуациях монитора. Попробуйте сделать это с помощью обратного вызова SourceInitialized

0 голосов
/ 22 июня 2017

У меня есть решение для сохранения размера и состояния, вы можете расширить его, чтобы сохранить положение. Это сделано с использованием поведения. Простое связывание ширины и высоты не сработало, как ожидалось, потому что оно перезаписывало бы размер "нормального" состояния максимальными размерами. Вот почему есть некоторые дополнительные проверки, такие как 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 при запуске / завершении работы.

0 голосов
/ 17 мая 2010

Вы делаете это через привязку данных? Именно так я делаю размеры и расположение окон. У меня обычно есть файл UserConfig.xml, который сохраняется в профиле пользователя. Затем я создаю элементы, привязывая их в программе. У меня есть словарь ресурсов Application.xaml, ссылающийся на этот файл, и все параметры, которые я хочу установить в XPaths в XML. Затем я просто сохраняю в памяти XML-документ при выходе. Только одно событие для обработки, без беспорядка, без суеты.

И вы можете расширить его, чтобы охватить столько настроек, сколько вам нужно для пользовательского интерфейса. Добавление настроек сантехники немного сложнее, но не так ужасно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...