Frage

Aktualisieren:Mit Code gelöst

Ich habe es zum Laufen gebracht, den Code finden Sie in meiner Antwort unten ...

Ursprünglicher Beitrag

Wie Tundey in betonte seine Antwort zu meinem letzte Frage, können Sie fast alles über ein Windows Forms-Steuerelement ganz mühelos an ApplicationSettings binden.Gibt es also wirklich keine Möglichkeit, dies mit der Formulargröße zu tun? Dieses Tutorial besagt, dass Sie die Größe explizit behandeln müssen, damit Sie RestoreBounds anstelle der Größe speichern können, wenn das Fenster maximiert oder minimiert ist.Ich hoffte jedoch, dass ich einfach eine Eigenschaft wie die folgende nutzen könnte:

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

Aber ich sehe keine Möglichkeit, dies im Designer zu binden (Größe fehlt insbesondere in der PropertyBinding-Liste).

War es hilfreich?

Lösung

Endlich habe ich eine Form-Unterklasse entwickelt, die dieses Problem ein für alle Mal löst.Um es zu benutzen:

  1. Von RestorableForm anstelle von Form erben.
  2. Fügen Sie eine Bindung in (ApplicationSettings) -> (PropertyBinding) zu WindowRestoreState hinzu.
  3. Rufen Sie Properties.Settings.Default.Save() auf, wenn das Fenster geschlossen wird.

Jetzt werden Fensterposition und -status zwischen den Sitzungen gespeichert.Den Vorschlägen anderer Poster unten folgend, habe ich eine Funktion „ConstrainToScreen“ eingefügt, die sicherstellt, dass das Fenster beim Wiederherstellen gut auf die verfügbaren Displays passt.

Code

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

Referenzen zu Einstellungsbindungen

Andere Tipps

Der Grund, warum die Form.Size-Eigenschaft in der Benutzeroberfläche für die Einstellungsbindung nicht verfügbar ist, liegt darin, dass diese Eigenschaft markiert ist DesignerSerializationVisibility.Hidden.Das bedeutet, dass der Designer nicht weiß, wie er es serialisieren soll, geschweige denn, wie er eine Datenbindung dafür generieren soll.Stattdessen die Form.ClientSize Die Eigenschaft ist diejenige, die serialisiert wird.

Wenn Sie versuchen, durch Bindung schlau zu werden Standort Und ClientSize, werden Sie ein anderes Problem sehen.Wenn Sie versuchen, die Größe Ihres Formulars vom linken oder oberen Rand aus zu ändern, werden Sie ein seltsames Verhalten feststellen.Dies hängt offenbar mit der Art und Weise zusammen, wie die bidirektionale Datenbindung im Kontext von Eigenschaftssätzen funktioniert, die sich gegenseitig beeinflussen.Beide Standort Und ClientSize schließlich eine gemeinsame Methode aufrufen, SetBoundsCore().

Auch die Datenbindung an Eigenschaften wie Standort Und Größe ist einfach nicht effizient.Jedes Mal, wenn der Benutzer das Formular verschiebt oder seine Größe ändert, sendet Windows Hunderte von Nachrichten an das Formular, was dazu führt, dass die Datenbindungslogik viele Verarbeitungsvorgänge durchführt, während Sie eigentlich nur die letzte Position und Größe speichern möchten, bevor das Formular geschlossen wird.

Dies ist eine sehr vereinfachte Version von dem, was ich mache:

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

Warum ist dies eine sehr vereinfachte Version?Weil es richtig ist, es richtig zu machen viel schwieriger als es aussieht :-)

Nun, ich habe kurz damit gespielt und Sie haben Recht, obwohl es keine Möglichkeit gibt, dies direkt zu tun binden Wenn Sie die Größe des Formulars in AppSettings festlegen, können Sie Ihre eigenen Werte hinzufügen und die Größe beim Laden ändern.

Ich würde vielleicht empfehlen, dass Sie, wenn dies eine häufige Funktion ist, eine Unterklasse für „Form“ erstellen und App.Config automatisch auf die Einstellungen für die Formulargröße prüfen lassen.

(Oder Sie könnten Ihre eigene Datei rollen.Lassen Sie es eine XML-Datei „formname.settings.xml“ abfragen oder so?- laut denken!)..

Hier ist, was ich hatte (sehr grob, keine Fehlerprüfung usw.).

App.Config

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

Formularcode

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

Ich stelle mir vor, dass eine Größenbindung unter anderem deshalb nicht zulässig ist, weil sich der Bildschirm zwischen den Sitzungen ändern kann.

Das erneute Laden der Größe bei verringerter Auflösung kann dazu führen, dass die Titelleiste über den Bildschirmrand hinausragt.

Sie müssen auch bei Konfigurationen mit mehreren Monitoren vorsichtig sein, da bei der nächsten Ausführung der App möglicherweise keine Monitore mehr verfügbar sind.

Ich stimme der Antwort von Rob Cooper zu.Aber ich denke, Martin macht einen sehr guten Punkt.Es gibt nichts Schöneres, als wenn Benutzer Ihre Anwendung öffnen und die App außerhalb des Bildschirms ist!

In Wirklichkeit sollten Sie also beide Antworten kombinieren und die aktuellen Bildschirmabmessungen berücksichtigen, bevor Sie die Größe Ihres Formulars festlegen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top