Tony Jang
Tony Jang

Reputation: 141

How to refresh UserControl which create by GDI+ when property changes

First, I'm not good in English. So if there are grammatical errors, please understand..

I referred to here.

I've created a simple solution with 2 projects. The 1st project (class library) contains a custom control which draws Tank by GDI+. The 2nd project (windows forms) is a test application.

I want to use Tank for control that can show real-time value which set by calling Value Property. I have many problems to implement this. Mosts are solved, but there is a problem.

In 2nd project, If I start Form1 after add Timer to the Form1 and set Value property that made by random to show real-time Value in timer_tick(), I have to call tank1.Refresh() in Form1_Paint().

There are two pictures that show this problem. In each picture, Left is control that is created same way(works same way) such as right One and is not called .Refresh() in Form1_Paint().

picture1

picture2

Is there better way such as just calling Invalidate() in timer_tick() not calling tank.Refresh in Form_Paint()? I've seen some question and answer that explained .Invalidate(), .Refresh(), .Update() or recommended using events but I don't know which way is better.

And Why tank1 is not repainted when I called Invalidate() in Form1_Paint()?

I wish someone understand beginner's pain....

Here is code

public class Tank : UserControl
{
    public Tank();

    public float MAX { get; set; }
    public float MIN { get; set; }
    public float Value { get; set; }

    protected override void Dispose(bool disposing);
    protected override void OnPaint(PaintEventArgs e);
}

public partial class Form1 : Form
{
    Random R = new Random();

    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Paint(object sender, PaintEventArgs e)
    {
        tank1.Refresh();
        //waterStorageBasin1.Refresh();
    }
    private void button1_Click(object sender, EventArgs e)
    {
        timer1.Start();
    }

    private void timer1_Tick(object sender, EventArgs e)
    {
        tank1.Value = (float)(R.NextDouble() * 10);
        waterStorageBasin1.Value = (float)(R.NextDouble() * 10);

        label1.Text = Math.Round(tank1.Value, 2).ToString();
        label2.Text = Math.Round(waterStorageBasin1.Value, 2).ToString();
        //I want this way
        //Invalidate();
    }
}

Upvotes: 0

Views: 781

Answers (1)

Tony Jang
Tony Jang

Reputation: 141

Hans Passant answered that this.Invalidate() would be better.
@HansPassant Thanks for your help!

    public float Value
    {
        get
        {
            return _tankLevel_Value;
        }
        set
        {
            _tankLevel_Value = value;
            this.Invalidate();
        }
    }

Upvotes: 1

Related Questions