Search code examples
c#inheritancepanel

Inheritance - Change value on Parent and reflect this on all the children


I am trying to implement a status indicator that includes some text and a green/red/yellow circle. I want this panel to be included in several forms, and that when the text/color is updated, the changes are reflected on every children.

I have a base class:

public class StatusIndicatorBase : Panel
{
    public Brush indicatorColor;
    public SolidBrush redBrush = new SolidBrush(Color.Red);
    public SolidBrush greenBrush = new SolidBrush(Color.Green);
    public SolidBrush yellowBrush = new SolidBrush(Color.Yellow);
    public Label indicatorText = new Label() { AutoSize = false, BackColor = Color.Transparent };
    public int indicatorBorderSize = 1;
    public int indicatorSize = 20;
    public int marginSize = 8;
    public enum status { red, green, yellow };

    public void SetText(string message, status currentStatus)
    {
        int oldWidth = TextRenderer.MeasureText(indicatorText.Text, indicatorText.Font).Width;
        indicatorText.Text = message;
        int newWidth = TextRenderer.MeasureText(indicatorText.Text, indicatorText.Font).Width;
        indicatorText.Width = newWidth;
        indicatorText.Top = (indicatorText.Height - this.Height);
        this.Width = indicatorText.Width + indicatorSize;
        this.Location = new Point(this.Location.X + (oldWidth - newWidth), this.Location.Y);
        SetColor(currentStatus);
        this.Refresh();
    }

    public string GetText()
    {
        return indicatorText.Text;
    }

    public void SetColor(status currentStatus)
    {
        switch (currentStatus)
        {
            case status.green:
                indicatorColor = greenBrush;
                break;
            case status.red:
                indicatorColor = redBrush;
                break;
            case status.yellow:
                indicatorColor = yellowBrush;
                break;
        }
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        Graphics g = e.Graphics;
        Pen pen = new Pen(Color.Black, indicatorBorderSize);
        g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
        int size = indicatorSize - indicatorBorderSize * 4;
        g.DrawEllipse(pen, this.Width - indicatorSize, 0, size, size);
        g.FillEllipse(indicatorColor, this.Width - indicatorSize, 0, size, size);
        g.Dispose();
        this.BringToFront();
    }

    protected override void OnResize(EventArgs e)
    {
        base.OnResize(e);
    }
}

And the children class that inheritate from it:

public class StatusIndicator : StatusIndicatorBase
{

    public StatusIndicator(int clientWidth, int clientHeight)
    {
        this.Height = indicatorSize;
        this.RightToLeft = RightToLeft.Yes;
        this.Location = new Point(clientWidth - indicatorSize - marginSize, clientHeight - this.Height - marginSize);
        this.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
        SetText("", status.green);
        this.Controls.Add(indicatorText);
    }
}

Then I create a few status indicator objects in different forms:

statusIndicator = new StatusIndicator(this.ClientRectangle.Width, this.ClientRectangle.Height);
this.Controls.Add(statusIndicator);

However, when I do:

statusIndicator.SetText("All goooood", StatusIndicator.status.green);

only that statusIndicator will get updated.

I know that I am doing something wrong, probably the whole approach is wrong, but I cannot figure out what.


Solution

  • I managed to solve this without inheritance, like @canton7 commented.

    public class StatusIndicatorBase
    {
        public static SolidBrush redBrush = new SolidBrush(Color.Red);
        public static SolidBrush greenBrush = new SolidBrush(Color.Green);
        public static SolidBrush yellowBrush = new SolidBrush(Color.Yellow);
        public static SolidBrush indicatorColor = greenBrush;
        public static Label indicatorText = new Label() { AutoSize = false, BackColor = Color.Transparent, Text = "" };
        public static int indicatorBorderSize = 1;
        public static int indicatorSize = 20;
        public static int marginSize = 8;
        public int oldTextWidth;
        public int newTextWidth;
        public enum status { red, green, yellow };
    
    
        public static void SetText(string message, status currentStatus)
        {
            SetColor(currentStatus);
            indicatorText.Text = message;
        }
    
        public static string GetText()
        {
            return indicatorText.Text;
        }
    
        private static void SetColor(status currentStatus)
        {
            switch (currentStatus)
            {
                case status.green:
                    indicatorColor = greenBrush;
                    break;
                case status.red:
                    indicatorColor = redBrush;
                    break;
                case status.yellow:
                    indicatorColor = yellowBrush;
                    break;
            }
        }
    

    Then created a class that inheritates from Panel and use an event for TextChanged to fire when the StatusIndicatorBase text changes. This way I can have several panels with the indicator "light" and text and update the text on all of them by just changing the text on StatusIndicatorBase.

    public class StatusIndicator : Panel
    {
        private Label indicatorText = new Label() { AutoSize = false, BackColor = Color.Transparent, Text = ""};
        private SolidBrush indicatorColor = StatusIndicatorBase.indicatorColor;
    
    
        public StatusIndicator(int clientWidth, int clientHeight)
        {
            this.Height = StatusIndicatorBase.indicatorSize;            
            this.RightToLeft = RightToLeft.Yes;
            this.Location = new Point(clientWidth - StatusIndicatorBase.indicatorSize - StatusIndicatorBase.marginSize, clientHeight - this.Height - StatusIndicatorBase.marginSize);
            this.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
            this.Controls.Add(this.indicatorText);
            UpdateIndicator();
            StatusIndicatorBase.indicatorText.TextChanged += IndicatorText_TextChanged;
        }
    
        private void IndicatorText_TextChanged(object sender, EventArgs e)
        {
            UpdateIndicator();
        }
    
        public void UpdateIndicator()
        {
            int oldWidth = TextRenderer.MeasureText(this.indicatorText.Text, this.indicatorText.Font).Width;
            this.indicatorText.Text = StatusIndicatorBase.indicatorText.Text;
            int newWidth = TextRenderer.MeasureText(this.indicatorText.Text, this.indicatorText.Font).Width;
            this.indicatorText.Width = newWidth;
            this.indicatorText.Top = (indicatorText.Height - this.Height);
            this.Width = this.indicatorText.Width + StatusIndicatorBase.indicatorSize;
            this.Location = new Point (this.Location.X + (oldWidth - newWidth), this.Location.Y);
            this.indicatorColor = StatusIndicatorBase.indicatorColor;
            this.Refresh();
        }
    
        protected override void OnPaint(PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            Pen pen = new Pen(Color.Black, StatusIndicatorBase.indicatorBorderSize);
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
            int size = StatusIndicatorBase.indicatorSize - StatusIndicatorBase.indicatorBorderSize * 4;
            g.DrawEllipse(pen, this.Width - StatusIndicatorBase.indicatorSize, 0, size, size);
            g.FillEllipse(this.indicatorColor, this.Width - StatusIndicatorBase.indicatorSize, 0, size, size);
    
            g.Dispose();
            this.BringToFront();
        }
    }
    

    enter image description hereenter image description here