Сведения о вопросе

Life

20:23, 28th August, 2020

Теги

Почему вы не можете привязать размер формы windows к ApplicationSettings?

Просмотров: 457   Ответов: 5

Обновление: решено, с кодом

Я получил это работает, см. Мой ответ ниже для кода...

оригинальный пост

Как указал Тунди в своем ответе на мой последний вопрос, вы можете связать почти все о windows forms control с ApplicationSettings довольно легко. Так неужели нет никакого способа сделать это с размером формы? В этом руководстве говорится, что вам нужно явно обрабатывать размер, чтобы вы могли сохранить RestoreBounds вместо размера, если окно развернуто или свернуто. Тем не менее, я надеялся, что смогу просто использовать такое свойство, как:

public Size RestoreSize
{
    get
    {
        if (this.WindowState == FormWindowState.Normal)
        {
            return this.Size;
        }
        else
        {
            return this.RestoreBounds.Size;
        }
    }
    set
    {
        ...
    }
}

Но я не вижу способа связать это в конструкторе (размер заметно отсутствует в списке PropertyBinding).



  Сведения об ответе

piter

20:22, 7th August, 2020

Я наконец-то придумал подкласс форм, который решает эту проблему раз и навсегда. Использовать его:

  1. Наследовать от RestorableForm вместо формы.
  2. Добавьте привязку в (ApplicationSettings) - > (PropertyBinding) к WindowRestoreState.
  3. Вызовите Properties.Settings.Default.Save(), когда окно будет готово закрыться.

Теперь положение и состояние окна будут вспоминаться между сеансами. Следуя предложениям других плакатов ниже, я включил функцию ConstrainToScreen, которая гарантирует, что окно хорошо поместится на доступных дисплеях при восстановлении самого себя.

Код

// Consider this code public domain. If you want, you can even tell
// your boss, attractive women, or the other guy in your cube that
// you wrote it. Enjoy!

using System;
using System.Windows.Forms;
using System.ComponentModel;
using System.Drawing;

namespace Utilities
{
    public class RestorableForm : Form, INotifyPropertyChanged
    {
        // We invoke this event when the binding needs to be updated.
        public event PropertyChangedEventHandler PropertyChanged;

        // This stores the last window position and state
        private WindowRestoreStateInfo windowRestoreState;

        // Now we define the property that we will bind to our settings.
        [Browsable(false)]        // Don't show it in the Properties list
        [SettingsBindable(true)]  // But do enable binding to settings
        public WindowRestoreStateInfo WindowRestoreState
        {
            get { return windowRestoreState; }
            set
            {
                windowRestoreState = value;
                if (PropertyChanged != null)
                {
                    // If anybody's listening, let them know the
                    // binding needs to be updated:
                    PropertyChanged(this,
                        new PropertyChangedEventArgs("WindowRestoreState"));
                }
            }
        }

        protected override void OnClosing(CancelEventArgs e)
        {
            WindowRestoreState = new WindowRestoreStateInfo();
            WindowRestoreState.Bounds
                = WindowState == FormWindowState.Normal ?
                  Bounds : RestoreBounds;
            WindowRestoreState.WindowState = WindowState;

            base.OnClosing(e);
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);

            if (WindowRestoreState != null)
            {
                Bounds = ConstrainToScreen(WindowRestoreState.Bounds);
                WindowState = WindowRestoreState.WindowState;
            }
        }

        // This helper class stores both position and state.
        // That way, we only have to set one binding.
        public class WindowRestoreStateInfo
        {
            Rectangle bounds;
            public Rectangle Bounds
            {
                get { return bounds; }
                set { bounds = value; }
            }

            FormWindowState windowState;
            public FormWindowState WindowState
            {
                get { return windowState; }
                set { windowState = value; }
            }
        }

        private Rectangle ConstrainToScreen(Rectangle bounds)
        {
            Screen screen = Screen.FromRectangle(WindowRestoreState.Bounds);
            Rectangle workingArea = screen.WorkingArea;

            int width = Math.Min(bounds.Width, workingArea.Width);
            int height = Math.Min(bounds.Height, workingArea.Height);

            // mmm....minimax
            int left = Math.Min(workingArea.Right - width,
                                Math.Max(bounds.Left, workingArea.Left));
            int top = Math.Min(workingArea.Bottom - height,
                                Math.Max(bounds.Top, workingArea.Top));

            return new Rectangle(left, top, width, height);
        }
    }
}

Настройки Привязки Ссылки


  Сведения об ответе

COOL

17:39, 13th August, 2020

Причина, по которой свойство Form.Size недоступно в привязке параметров UI, заключается в том, что это свойство помечено как DesignerSerializationVisibility.Hidden . Это означает, что дизайнер не знает, как сериализовать его, не говоря уже о создании привязки данных для него. Вместо этого свойство Form.ClientSize является тем, которое получает сериализацию.

Если вы попытаетесь поумнеть, связав Location и ClientSize, то увидите еще одну проблему. Когда вы попытаетесь изменить размер своей формы с левого или верхнего края, вы увидите странное поведение. Это, по-видимому, связано с тем, как двусторонняя привязка данных работает в контексте наборов свойств, которые взаимно влияют друг на друга. И Location , и ClientSize в конечном итоге вызывают общий метод, SetBoundsCore() .

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

Это очень упрощенная версия того, что я делаю:

private void MyForm_FormClosing(object sender, FormClosingEventArgs e)
{
    Properties.Settings.Default.MyState = this.WindowState;
    if (this.WindowState == FormWindowState.Normal)
    {
       Properties.Settings.Default.MySize = this.Size;
       Properties.Settings.Default.MyLoc = this.Location;
    }
    else
    {
       Properties.Settings.Default.MySize = this.RestoreBounds.Size;
       Properties.Settings.Default.MyLoc = this.RestoreBounds.Location;
    }
    Properties.Settings.Default.Save();
}

private void MyForm_Load(object sender, EventArgs e)
{
    this.Size = Properties.Settings.Default.MySize;
    this.Location = Properties.Settings.Default.MyLoc;
    this.WindowState = Properties.Settings.Default.MyState;
} 

Почему это очень упрощенная версия? Потому что делать это правильно намного сложнее , чем кажется :-)


  Сведения об ответе

davran

17:44, 23rd August, 2020

Ну, я быстро поиграл с этим, и вы правы, хотя нет никакого способа напрямую привязать размер формы к AppSettings, вы можете добавить свои собственные значения и изменить размер При загрузке.

Я бы, пожалуй, рекомендовал, чтобы, если это общая функция, вы подкласс Form и сделать его автоматически prob App.Config для настроек размера форм.

(Или вы можете свернуть свой собственный файл.. Заставить его запросить файл Xml "formname.settings.xml" или что-то еще? - думать вслух!)..

Вот что у меня было (очень грубо, без проверки ошибок и т. д.).

App.Config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <appSettings>
        <add key ="FormHeight" value="500" />
        <add key ="FormWidth" value="200"/>
    </appSettings>
</configuration>

код формы

    private void Form1_Load(object sender, EventArgs e)
    {
        string height = ConfigurationManager.AppSettings["FormHeight"];
        int h = int.Parse(height);
        string width = ConfigurationManager.AppSettings["FormWidth"];
        int w = int.Parse(width);
        this.Size = new Size(h, w);
    }

  Сведения об ответе

prince

03:17, 18th August, 2020

Одна из причин, по которой я предполагаю, что привязка размера не разрешена, заключается в том, что экран может меняться между сеансами.

Загрузка размера обратно, когда разрешение уменьшилось, может привести к тому, что строка заголовка окажется за пределами экрана.

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


  Сведения об ответе

FAriza

09:45, 12th August, 2020

Я согласен с ответом Роба Купера. Но я думаю, что Мартин делает очень хороший вывод. Нет ничего лучше, чем когда пользователи открывают ваше приложение, а приложение находится вне экрана!

Таким образом, на самом деле вы захотите объединить оба ответа и учитывать текущие размеры экрана, прежде чем устанавливать размер своей формы.


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться