¿Por qué no puedes enlazar el Tamaño de un formulario de windows para ApplicationSettings?

StackOverflow https://stackoverflow.com/questions/18585

Pregunta

Actualización:Resuelve, con el código

Yo tengo trabajo, véase mi respuesta a continuación para el código...

Post Original

Como Tundey señalado en su respuesta a mi la última pregunta, usted puede enlazar casi todo sobre un control de formularios windows forms para ApplicationSettings con poco esfuerzo.Entonces, ¿hay realmente ninguna manera de hacer esto con el Tamaño del formulario? Este tutorial dice que usted necesita para manejar el Tamaño explícitamente así que usted puede ahorrar RestoreBounds en lugar de tamaño si la ventana está maximizada o minimizada.Sin embargo, yo esperaba que me podría utilizar una propiedad como:

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

Pero no puedo ver una manera de enlazar esta en el diseñador (Tamaño es notablemente falta de la PropertyBinding lista).

¿Fue útil?

Solución

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

  1. Heredar de RestorableForm en lugar de la Forma.
  2. Agregar un enlace en (ApplicationSettings) -> (PropertyBinding) a WindowRestoreState.
  3. Propiedades De Llamada.Los ajustes.Por defecto.Guardar() cuando la ventana está a punto de cerrar.

Ahora la posición de la ventana y el estado será recordado entre los períodos de sesiones.Siguiendo las sugerencias de otros carteles a continuación, he incluido una función ConstrainToScreen que hace que la ventana se ajusta muy bien en la muestra cuando se restaura a sí mismo.

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

La Configuración De Los Enlaces De Las Referencias

Otros consejos

La razón por la que la Forma.El tamaño de la propiedad no está disponible en la configuración de enlace de la interfaz de usuario es debido a que esta propiedad está marcada DesignerSerializationVisibility.Oculto.Esto significa que el diseñador no sabe cómo serialise, y mucho menos generar un enlace de datos para ello.En lugar de la El formulario.ClientSize la propiedad es el que consigue serializado.

Si usted intenta y consigue inteligente por la unión Ubicación y ClientSize, verás otro problema.Cuando intenta cambiar el tamaño del formulario desde el borde izquierdo o superior, verás comportamiento extraño.Al parecer, esto es relacionado con la forma en que el enlace de datos bidireccional funciona en el contexto de conjuntos de propiedades que mutuamente se afectan unos a otros.Ambos Ubicación y ClientSize finalmente llamar a un método común, SetBoundsCore().

También, el enlace de datos para las propiedades como Ubicación y Tamaño no es eficiente.Cada vez que el usuario mueve o cambia el tamaño del formulario, Windows envía cientos de mensajes a la forma, causando la lógica de enlace de datos para hacer un montón de procesamiento, cuando todo lo que realmente quiero es guardar la última posición y tamaño antes de que se cierre el formulario.

Esta es una versión muy simplificada de lo que yo 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é esta es una versión muy simplificada?Porque haciendo esto correctamente es mucho más complicado de lo que parece :-)

Bien, he tenido un juego rápido con esto y estás en lo correcto, mientras que no hay manera directamente se unen el tamaño de la forma a AppSettings, usted puede agregar sus propios valores y cambiar el tamaño de la carga.

Yo sería, tal vez, recomendamos que si esta es una característica común, subclase Formulario y hacer que automáticamente se prob la Aplicación.Config para los formularios de configuración de tamaño.

(O usted podría rodar su propio archivo..Llegar a la consulta de un archivo Xml "formname.settings.xml" o algo así?- pensar en voz alta!)..

Heres lo que tenía (muy áspero, ninguna comprobación de 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>

El Código Del 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);
    }

Una de las razones que me imagino que el tamaño de la unión no es permitido es porque la pantalla puede cambiar entre sesiones.

Carga el tamaño de la espalda cuando la resolución se ha reducido podría resultar en la barra de título está más allá de los límites de la pantalla.

También es necesario ser cauteloso con múltiples configuraciones de monitor, donde los monitores puede no estar disponible cuando la aplicación siguiente se ejecuta.

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

Así que, en realidad, usted querrá combinar ambas respuestas y tener en cuenta las actuales dimensiones de la pantalla antes de configurar el tamaño del formulario.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top