How to implement correctly all auto-sizing mechanism of the controls?
How to notify the layout system about changes of PreferredSize property correctly?
Here is a part of my code.
// Cached preferred size.
// I do not want recalculate the preferred size each time when the PreferredSize property is accessed or
// the GetPreferredSize method is called.
private Size _PreferredSize ;
// I know that this method is called by PreferredSize property with proposedSize.IsEmpty
// It also called directly by Layout engine of the parent control with specified proposedSize
public override Size GetPreferredSize(Size proposedSize) {
if (_PreferredSize.IsEmpty) this.UpdatePreferredSize();
if (proposedSize.IsEmpty) return _PreferredSize;
// This is required to allow an anchored and one direction auto-sized control to be resized.
// If PreferredSize Width or Heigh is Zero this means the control is one direction auto-sized.
Size ps = _PreferredSize;
if (ps.Width == 0) {
ps.Width = proposedSize.Width < Int32.MaxValue ? proposedSize.Width : this.Width;
}
if (ps.Height == 0) {
ps.Height = proposedSize.Height < Int32.MaxValue ? proposedSize.Height : this.Height;
}
// this is required to allow an auto-sized GrowOnly control to be Docked with ability to Grow - be larger then PreferredSize
if (this.AutoSizeMode == AutoSizeMode.GrowOnly &;;&;; this.Dock != DockStyle.None) {
ps = new Size(Math.Max(ps.Width, this.Width), Math.Max(ps.Height, this.Height));
}
return ps;
}
// Called from UpdatePreferredSize or from any other place (for example OnPaint) to change the Cached Preferred Size.
protected virtual void SetPreferredSize(Size value) {
if (_PreferredSize != value) {
_PreferredSize = value;
OnPreferredSizeChanged(new EventArgs());
}
}
// Called when any property (Image, Text and etc.) affected on PreferredSize was changed.
public void ResetPreferredSize() {
SetPreferredSize(Size.Empty);
}
// Here is a place where PreferredSize is calculated
protected virtual void UpdatePreferredSize(){
Size ps = Size.Empty;
.
.
.
.
SetPreferredSize(ps);
}
protected virtual void OnPreferredSizeChanged(System.EventArgs e) {
if (PreferredSizeChanged != null) PreferredSizeChanged(this, e);
if (this.AutoSize) {
Control pc = this.Parent;
if (pc == null) {
// What to do if there is no parent?
// Should i resize the control by myself (this.Size = bla bla bla)?
this.Size = this.PreferredSize; // Like here, but depends of AutoSizeMode of course.
}
else {
// Is this code is correct?
// Is there any better way to notify the layout engine about
// the changes and force it to resize the control?
pc.PerformLayout(this, "PreferredSize");
}
}
}
public event System.EventHandler PreferredSizeChanged;