Почему вы не можете привязать размер формы Windows к ApplicationSettings?
-
09-06-2019 - |
Вопрос
Обновить:Решаемая с помощью кода
У меня это заработало, смотрите код в моем ответе ниже...
Оригинальное Сообщение
Как указал Тандей в его ответ к моему последний вопрос, Таким образом, вы можете довольно легко привязать практически все, что касается элемента управления Windows forms, к ApplicationSettings.Так неужели нет никакого способа сделать это с размером формы? Этот учебник говорит, что вам нужно явно обрабатывать Size, чтобы вы могли сохранять RestoreBounds вместо size, если окно развернуто или свернуто.Тем не менее, я надеялся, что смогу просто использовать такое свойство, как:
public Size RestoreSize
{
get
{
if (this.WindowState == FormWindowState.Normal)
{
return this.Size;
}
else
{
return this.RestoreBounds.Size;
}
}
set
{
...
}
}
Но я не вижу способа привязать это в конструкторе (размер заметно отсутствует в списке PropertyBinding).
Решение
Наконец-то я придумал подкласс Form, который решает эту проблему раз и навсегда.Чтобы использовать его:
- Наследуется от RestorableForm вместо Form.
- Добавьте привязку в (ApplicationSettings) -> (PropertyBinding) к WindowRestoreState.
- Вызовите Свойства.Настройки.По умолчанию.Сохранить(), когда окно вот-вот закроется.
Теперь положение и состояние окна будут запоминаться между сеансами.Следуя предложениям с других плакатов ниже, я включил функцию 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);
}
}
}
Настройки Привязки Ссылки
Другие советы
Причина, по которой свойство Form.Size недоступно в пользовательском интерфейсе привязки настроек, заключается в том, что это свойство помечено Видимость сериализации дизайнера.Скрытый.Это означает, что разработчик не знает, как его сериализовать, не говоря уже о создании привязки данных для него.Вместо этого Форма.Размер клиента свойство - это то, которое сериализуется.
Если вы попытаетесь поумнеть, связав Расположение и Размер клиента, вы увидите еще одну проблему.Когда вы попытаетесь изменить размер своей формы с левого или верхнего края, вы увидите странное поведение.По-видимому, это связано с тем, как работает двусторонняя привязка данных в контексте наборов свойств, которые взаимно влияют друг на друга.И то , и другое Расположение и Размер клиента в конечном итоге вызовите общий метод, Установленный балл ().
Кроме того, привязка данных к таким свойствам, как Расположение и Размер это просто неэффективно.Каждый раз, когда пользователь перемещает или изменяет размер формы, 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;
}
Почему это очень упрощенная версия?Потому что делать это правильно - это намного сложнее чем это выглядит :-)
Ну, я быстро поиграл с этим, и вы правы, хотя нет никакого способа напрямую привязать размер формы в AppSettings вы можете добавлять свои собственные значения и изменять размер при загрузке.
Возможно, я бы порекомендовал, если это распространенная функция, создать подкласс Form и автоматически проверять 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);
}
Одна из причин, по которой я предполагаю, что привязка к размеру не разрешена, заключается в том, что экран может меняться между сеансами.
Повторная загрузка размера при уменьшении разрешения может привести к тому, что строка заголовка выйдет за пределы экрана.
Вам также следует опасаться нескольких настроек мониторов, из-за которых мониторы могут быть недоступны при следующем запуске вашего приложения.
Я согласен с ответом Роба Купера.Но я думаю, что Мартин высказал очень вескую мысль.Нет ничего лучше, чем когда пользователи открывают ваше приложение, а само приложение находится за пределами экрана!
Таким образом, на самом деле вам захочется объединить оба ответа и учитывать текущие размеры экрана, прежде чем устанавливать размер вашей формы.