Какой метод WPF можно использовать для установки некоторых свойств при первом отображении элемента управления? - PullRequest
4 голосов
/ 15 июня 2011

Мне нужно сохранить размер / положение и состояние окна моего приложения, когда пользователь закрывает приложение, и устанавливать их обратно, когда пользователь после этого открывает приложение.

Я сделал это легко, используя ключи реестра (это дажелучший способ сделать это?), но мне интересно, куда я на самом деле должен поместить код для установки этих свойств.

Мне нужно установить их, когда окно «впервые появляется», я думаю.Но у меня есть несколько методов, которые можно использовать в этом случае, а именно:

  • Window.Show ()
  • Window.Activate ()
  • Window.ApplyTemplate ()
  • Window.Arrange ()
  • Window.ArrangeCore ()
  • Window.ArrangeOverride ()
  • Window.BeginInit ()
  • Window.EndInit ()
  • Window.Measure ()
  • Window.MeasureCore ()
  • Window.MeasureOverride ()
  • Window.OnApplyTemplate ()
  • Window.OnInitialized ()
  • Window.OnRender ()
  • Window.UpdateLayout ()

Я знаю, что большинство из нихпросто плохая идея (например, UpdateLayout () будет вызываться waaaaaaay слишком часто).В идеале я ищу метод, который будет вызываться только один раз в жизни окна, чтобы мне не нужно было добавлять флажок, проверяющий, является ли это первым вызовом метода.

, какой из них будетлучше всего в этом случае?и почему?

побочный вопрос: я поместил код для сохранения значений в Window.Close () (я переопределяю метод в моем MyWindow классе), но я мог бы также поместить его вWindow.OnClosing () или Window.OnClosed ().Имеет ли это какое-то значение в моем случае?

побочный вопрос (бис): мне также нужно сохранить порядок столбцов таблицы данных, куда я должен поместить код «сохранения» и «загрузки» в этом случае?

Ответы [ 3 ]

3 голосов
/ 15 июня 2011

Хорошо, мне кажется, вы рассматриваете WPF так, как если бы вы работали в старом школьном приложении WinForms. Вам больше не нужно отслеживать события формы, чтобы получать информацию из свойств форм. Большинство управляющих свойств WPF - это то, что называется Свойство зависимости .

Вот некоторые из умных свойств, которые представляют свойства зависимости: Привязка данных .

Если вы затем подумаете о написании приложения с архитектурой MVVM , вы быстро сможете сами решить следующие вопросы ... =)

В представлении * 1 вы можете создать либо свойства зависимости, либо стандартные свойства и реализовать INotifyPropertyChanged , которые содержат размер / макет / положение / и т. Д. Затем свяжите свойства формы (в xaml или коде) со свойствами представления. Затем вы можете реализовать любые функции, которые вам нравятся, для хранения / извлечения значений по умолчанию и автоматического обновления при изменении формы, просто адаптировав Get / Set свойств в представлении.

В качестве быстрого примера для Windows 'Заголовок:

<Window x:Class="MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="{Binding Path=DisplayName}"
        WindowStartupLocation="CenterScreen" >
    <Grid>...</Grid>
</Window>

Пример реализации представления:

public class SampleView : System.ComponentModel.INotifyPropertyChanged
{

    public event PropertyChangedEventHandler System.ComponentModel.INotifyPropertyChanged.PropertyChanged;
    public delegate void PropertyChangedEventHandler(object sender, System.ComponentModel.PropertyChangedEventArgs e);

    private string _Title;
    public string Title {
        get {
            if (_Title == null) {
                _Title = My.Settings.MainWindowTitle;
            }
            return _Title;
        }
        set {
            _Title = value;
            if (!(_Title == My.Settings.MainWindowTitle)) {
                if (PropertyChanged != null) {
                    PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs("Title"));
                }
                My.Settings.MainWindowTitle = Title;
                My.Settings.Save();
            }
        }
    }
}

РЕДАКТИРОВАТЬ: Относительно того, как лучше хранить пользовательские настройки, я не рекомендовал бы реестр, хотя, это далеко не неслыханно. В настоящее время реестр заполнен настройками, для которых , на мой взгляд , реестр не был предназначен. Подумайте об использовании настроек приложения с настройкой пользовательской области. Это позволит справиться с большинством вопросов о том, где и как данные хранятся / извлекаются, и предоставит вам приятный типобезопасный интерфейс для вас.

* 1 Лично я предпочитаю попытаться связать все с ViewModel и у меня почти полностью тупые виды; хотя я знаю, что существует множество допустимых случаев для представлений, имеющих код. Я бы не сказал, что Size / Layout / etc - это действительно бизнес-логика, и до сих пор я этим не занимался, поэтому, вероятно, это следует обрабатывать в самом View.

РЕДАКТИРОВАТЬ 2 - Быстрый пример настроек области действия пользователя / приложения:

Вот краткая картина настроек, которые я добавил в проект:

Settings screenshot

Следующий код пытается использовать настройки приложения и области действия пользователя. Примечание: Настройки области приложения доступны только для чтения во время выполнения

public class SettingsExample
{
    private Form1 frmMain = new Form1();

    public void Main()
    {
        frmMain.BackColor = My.Settings.DefaultBackColour;
    }

    public void UserLoggedIn()
    {
        frmMain.BackColor = My.Settings.UserBackcolour;
    }

    public void UpdateUserBackcolour(System.Drawing.Color newColour)
    {
        My.Settings.UserBackcolour = newColour;
        My.Settings.Save();
    }

    public void UpdateDefaultBackcolour(System.Drawing.Color newColour)
    {
        My.Settings.DefaultBackColour = newColour;
        // Compiler Error
        // This property is read only because it is an application setting
        // Only user settings can be changed at runtime
    }

}
0 голосов
/ 01 августа 2011

Мой выбор: я наконец-то положил код для загрузки значений из реестра в window.Show ().

причина, по которой я это сделал, из-за 2 вещей:

  1. Я сохраняю состояние окна (свернутое / развернутое) и способ, которым WPF это делает, мне нужно сначала установить ширину / высоту, а затем развернутое состояние (если необходимо), иначе оно испортит раскладка. И если я не установлю ширину / высоту в первую очередь, я потеряю их, когда в дальнейшем буду максимизировать окно. Так что я должен делать вещи в следующем порядке: ширина + высота и их состояние. (Кроме того, это необходимо при работе с несколькими экранами, в противном случае вы потеряете экран, на котором работали). Это означает, что некоторые из перечисленных методов нецелесообразны (например, «измерить»)

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

помещение кода в window.Show () удалось решить эти 2 проблемы. Я мог бы получить тот же результат с одним или несколькими другими методами, но мне просто надоело пробовать разные конфигурации, и в итоге я использовал первый, который дал мне полное удовлетворение.

0 голосов
/ 15 июня 2011

Во-первых, вы забыли о

Загруженное событие - происходит, когда элемент выложен, представлен и готов к взаимодействие. (Унаследовано от FrameworkElement.)

Нет простого ответа. Сценарий может варьироваться, будь то дочернее «диалоговое» окно (тогда я бы просто установил размер на строку перед Show ()), новый экземпляр того же окна или новый экземпляр приложения.

Я буду утверждать, что UpdateLayout () - плохая идея. На самом деле, это очень хорошая идея. Например:

private bool m_onStart = true;

public MainWindow()
{
        InitializeComponent();
        this.LayoutUpdated += new EventHandler(MainWindow_LayoutUpdated);
}

void MainWindow_LayoutUpdated(object sender, EventArgs e)
{
     if (m_onStart)
     {
         m_onStart = false;
         Dispatcher.BeginInvoke(() =>
         {
              //Start App
         }
         );
     }
 }

Даже если он вызывается тысячу раз в секунду (что очень маловероятно), вы даже не заметите его и не повредите производительности.

В общем, вы можете создать вспомогательный метод, который сохранит предпочтения пользователя, а затем прочитает его. Поскольку задача связана с представлением и использует MVVM, а привязка для этого является излишним, установите размер в событии Loaded (сделайте это, когда все ядра, инициализация и визуальное дерево выполнены).

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