Why can't you bind the size of the window shape to ApplicationSettings?

Update: Solved with code

I got it working, see my answer below for code ...

Original post

As Tundei pointed out in his answer to my last question , you can bind almost all of Windows to easily manage ApplicationSettings elements. So there is no way to do this using the Size form? This guideline says that you need to handle the size explicitly so that you can save RestoreBounds instead of size if the window is maximized or minimized. However, I was hoping I could just use a property like:

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

But I see no way to bind this in the constructor (the size is noticeably absent from the PropertyBinding list).

+2
c # data-binding visual-studio
Aug 20 '08 at 18:59
source share
5 answers

Finally, I came up with a subclass of Form that solves this once and for all. To use it:

  • Inherit from RestorableForm instead of form.
  • Add the binding in (ApplicationSettings) -> (PropertyBinding) to WindowRestoreState.
  • Call Properties.Settings.Default.Save () when the window closes.

Now the window position and state will be remembered between sessions. Following the recommendations of the other posters below, I turned on the ConstrainToScreen function, which ensures that the window works perfectly on the available displays when restoring.

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

Links to Binding Links

+11
Aug 20 '08 at 23:06
source share

The reason that the Form.Size property is not available in the parameter binding interface is because this property is marked with DesignerSerializationVisibility.Hidden . This means that the developer does not know how to serialize it, not to mention creating a data binding for it. Instead, the Form.ClientSize property is serialized.

If you try to get smarter by linking Location and ClientSize , you will see another problem. When you try to resize your shape to the left or top, you will see strange behavior. This, apparently, is related to how two-way data binding works in the context of sets of properties that mutually influence each other. Both Location and ClientSize eventually call the common SetBoundsCore () method.

In addition, data binding to properties such as Location and Size is simply ineffective. Every time a user moves or resizes a form, Windows sends hundreds of messages to the form, forcing the data binding logic to do more processing when all you really need is to keep the last position and size until the form is closed.

This is a very simplified version of what I am doing:

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

Why is this a very simplified version? Because doing it right is a lot harder than it looks :-)

+5
Nov 04 '08 at 2:59
source share

It's good that I quickly played around with this, and you're right, while there is no way to directly bind the form size to AppSettings, you can add your own values ​​and change the size at startup.

I would recommend that if this is a normal function, you subclass Form and automatically run App.Config to adjust the size of the forms.

(Or you can flip your own file .. Ask him to request the Xml file "formname.settings.xml" or something like that - think out loud!) ..

Here is what I had (very rude, without error checking, etc.).

App.Config

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

Form code

  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); } 
+1
Aug 20 '08 at 19:41
source share

One of the reasons I assume that sizing is not allowed is because the screen can change between sessions.

Loading the size back while decreasing the resolution may cause the title bar to go off the screen.

You also need to be careful with a few monitor settings, where monitors may not be available the next time you launch the application.

+1
Aug 20 '08 at 19:52
source share

I agree with Rob Cooper's answer. But I think Martin speaks very well. It’s not like users are opening your application and the application is disconnected from the screen!

Thus, in fact, you need to combine both answers and keep in mind the current screen sizes before setting the form size.

+1
Aug 20 '08 at 20:04
source share



All Articles