A better version of Flowlayoutpanel Control in C#

A

The FlowLayoutPanel shares many of an ordinary panel control. They ultimately serve the same purpose, which is to organize children controls. In other words, is a container control that provides dynamically layout for the child controls. However, the stock version of the toolbox has some major limitations in terms of performance. For that reason the following minor modifications can improve your flowlayout panel’s performance, especially if you want to add a large amount of child controls.

   public delegate void VoidObject(object obj);
    ...
    ...
    public partial class FlowLayoutPanel : System.Windows.Forms.FlowLayoutPanel
    {
        private Control _focusedControl = null;
        public VoidObject onChildFocus = null;
        public Control focusedControl
        {
            get
            {
                return _focusedControl;
            }
            set
            {
                onChildFocus?.Invoke(value);
                _focusedControl = value;
            }
        }

        public FlowLayoutPanel() : base()
        {
            DoubleBuffered = true;
            this.SetStyle(ControlStyles.UserPaint, true);
            this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
            this.ControlAdded += FlowLayoutPanel_ControlAdded;
            this.ControlRemoved += FlowLayoutPanel_ControlRemoved;

        }

        protected override void OnScroll(ScrollEventArgs se)
        {
            //Invalidate();
            base.OnScroll(se);
        }

        protected override void OnResize(EventArgs se)
        {
            this.SuspendLayout();
            foreach (Control c in this.Controls)
            {
                if (c.HasMethod("InheritedResize"))
                {
                    c.GetType().GetMethod("InheritedResize").Invoke(c, new object[] { this.Width, this.Height });
                }
            }
            this.ResumeLayout();
            this.Invalidate();
        }

        void Control_Entered(object sender, EventArgs e)
        {
            focusedControl = (Control)sender;
        }

        private void FlowLayoutPanel_ControlRemoved(object sender, ControlEventArgs e)
        {
            e.Control.Enter -= new EventHandler(Control_Entered);
        }

        public void ForcedInvalidation()
        {
            this.SuspendLayout();
            foreach (Control c in this.Controls)
            {
                if (c.HasMethod("InheritedResize"))
                {
                    c.GetType().GetMethod("InheritedResize").Invoke(c, new object[] { this.Width, this.Height });
                }
            }
            this.ResumeLayout();
            this.Invalidate();
        }

        private void FlowLayoutPanel_ControlAdded(object sender, ControlEventArgs e)
        {
            this.SuspendLayout();
            if (e.HasMethod("InheritedResize"))
            {
                e.GetType().GetMethod("InheritedResize").Invoke(e, new object[] { this.Width, this.Height });
            }
            e.Control.Enter += new EventHandler(Control_Entered);
            this.ResumeLayout();
        }

        public virtual void Add(Control value)
        {
            Application.DoEvents();
            this.InvokeIfRequired(() => this.Controls.Add(value));
            Application.DoEvents();
        }

        public void ClearAndDispose()
        {
            List<Control> ctrls = new List<Control>(this.Controls.Cast<Control>());
            Application.DoEvents();
            this.InvokeIfRequired(() => this.Controls.Clear());
            Application.DoEvents();
            foreach (Control c in ctrls)
            {
                c.InvokeIfRequired(() => c.Dispose());
                Application.DoEvents();
            }
            Application.DoEvents();
            ctrls.Clear();
        }

        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams cp = base.CreateParams;
                cp.ExStyle |= 0x02000000; // WS_CLIPCHILDREN
                return cp;
            }
        }
    }

Below is an extensions class which is required for the previous example.

public static class Extensions
{
    public static bool HasMethod(this object obj, string methodName)
    {
        var type = obj.GetType();
        return type.GetMethod(methodName) != null;
    }

    public static void InvokeIfRequired(this ISynchronizeInvoke obj, System.Windows.Forms.MethodInvoker action)
    {
        if (obj.InvokeRequired)
        {
            var args = new object[0];
            obj.Invoke(action, args);
        }
        else
        {
            action();
        }
    }
}

Disclaimer: The present content may not be used for training artificial intelligence or machine learning algorithms. All other uses, including search, entertainment, and commercial use, are permitted.

Leave a Reply to Io. D Cancel reply

Categories

Tags