visual ventanas tamaño redimensionar posicionar maximizar mas hacer grande formularios formulario escala controles como automático ajuste ajustar c# visual-studio data-binding .net-2.0

c# - ventanas - ¿Por qué no puede vincular el tamaño de un formulario de Windows a ApplicationSettings?



posicionar formulario c# (5)

Actualización: resuelto, con código

Lo tengo funcionando, ver mi respuesta a continuación para el código ...

Publicación original

Como Tundey señaló en su respuesta a mi última pregunta , puedes vincular casi todo sobre el control de formularios de Windows a ApplicationSettings sin esfuerzo. Entonces, ¿realmente no hay forma de hacer esto con el tamaño de forma? Este tutorial dice que debes manejar el Tamaño explícitamente para que puedas guardar los RestoreBounds en lugar del tamaño si la ventana está maximizada o minimizada. Sin embargo, esperaba poder usar una propiedad como:

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

Pero no veo una manera de enlazar esto en el diseñador (el tamaño es notablemente ausente de la lista de PropertyBinding).


Bueno, he tenido un juego rápido con esto y estás en lo cierto, aunque no hay forma de vincular directamente el tamaño del formulario a AppSettings, puedes agregar tus propios valores y cambiar el tamaño en la carga.

Quizás recomiendo que, si se trata de una función común, subclassifique el formulario y haga que sea automáticamente el problema de App.Config para la configuración del tamaño de formularios.

(O podría hacer rodar su propio archivo ... Hacer que consulte un archivo Xml "formname.settings.xml" o algo así - ¡pensar en voz alta!) ..

Aquí está lo que tenía (muy difícil, sin errores, etc.).

App.Config

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

Código de formulario

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); }


Estoy de acuerdo con la respuesta de Rob Cooper. Pero creo que Martin hace un buen punto. ¡No hay nada como tener a los usuarios abriendo su aplicación y la aplicación está fuera de la pantalla!

Entonces, en realidad, querrás combinar ambas respuestas y tener en cuenta las dimensiones actuales de la pantalla antes de establecer el tamaño de tu formulario.


Finalmente se me ocurrió una subclase de Formulario que resuelve esto, de una vez por todas. Para usarlo:

  1. Heredar de RestorableForm en lugar de Formulario.
  2. Agregue un enlace en (ApplicationSettings) -> (PropertyBinding) a WindowRestoreState.
  3. Llamar a Properties.Settings.Default.Save () cuando la ventana está a punto de cerrarse.

Ahora la posición y el estado de la ventana se recordarán entre sesiones. Siguiendo las sugerencias de otros carteles a continuación, incluí una función de RestringirPantalla que asegura que la ventana se adapta bien a las pantallas disponibles al restaurarse.

Código

// 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); } } }

Configuraciones Vinculaciones Referencias


La razón por la cual la propiedad Form.Size no está disponible en la interfaz de usuario vinculante es porque esta propiedad está marcada como DesignerSerializationVisibility.Hidden . Esto significa que el diseñador no sabe cómo serializarlo, y mucho menos generar un enlace de datos para él. En cambio, la propiedad Form.ClientSize es la que se serializa.

Si intenta hacerse astuto vinculando Location y ClientSize , verá otro problema. Cuando intentes redimensionar tu forma desde el borde izquierdo o superior, verás un comportamiento extraño. Esto aparentemente está relacionado con la forma en que el enlace de datos bidireccional funciona en el contexto de conjuntos de propiedades que se afectan mutuamente. Tanto Location como ClientSize finalmente llaman a un método común, SetBoundsCore () .

Además, el enlace de datos a propiedades como Ubicación y Tamaño simplemente no es eficiente. Cada vez que el usuario mueve o cambia el tamaño del formulario, Windows envía cientos de mensajes al formulario, lo que hace que la lógica de enlace de datos haga un montón de procesamiento, cuando todo lo que realmente desea es almacenar la última posición y tamaño antes de que se cierre el formulario.

Esta es una versión muy simplificada de lo que hago:

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; }

¿Por qué es esta una versión muy simplificada? Porque hacer esto correctamente es mucho más complicado de lo que parece :-)


Una de las razones por las que imagino que el enlace de tamaño no está permitido es porque la pantalla puede cambiar entre sesiones.

Volver a cargar el tamaño cuando la resolución se haya reducido podría hacer que la barra de título esté más allá de los límites de la pantalla.

También debe tener cuidado con las configuraciones de monitores múltiples, donde los monitores pueden no estar disponibles cuando se ejecuta la próxima aplicación.