Skip Navigation LinksHome > View Post

BeginUpdate and finally

A while back Bruusi mentioned the BeginUpdate and EndUpdate methods to me and I've been in love with them ever since. Basically, they allow you to significantly improve the performance of your WinForms UI (and reduce flicker) by avoiding unnecessary repainting of controls.

It's pretty common that you need to populate some kind of list control with a lot of values, for example:

foreach (Something something in stuff)
{
    MyListControl.Items.Add(something.Description);
}

Doing this will actually cause the control to recalculate it's layout with each new addition, which is a total waste of time. Add the BeginUpdate and EndUpdate calls however and the repaint won't happen until you call EndUpdate():

MyListControl.BeginUpdate();

foreach (Something something in stuff)
{
    MyListControl.Items.Add(something.Description);
}

MyListControl.EndUpdate();

There is a caveat here though. If something horrible happens (namely, some kind of exception) between the Begin and End then you'll be locked in a BeginUpdate and your control will never update. This is not good if you want your application to 'recover' from exceptions (which is pretty common in WinForms) as that particular control will now be rendered useless (no pun intended). This is mainly down to the fact that Begin and EndUpdates are nested - that is, if you BeginUpdate twice you'll have to EndUpdate twice before the control will update.

The solution to this is to add a finally block:

try
{
    MyListControl.BeginUpdate();
    
    foreach (Something something in stuff)
    {
        MyListControl.Items.Add(something.Description);
    }
}
finally
{
    // NOTE, calling End without an appropriate Begin is OK
    MyListControl.EndUpdate();
}

Now wouldn't it be cool if we had a BeginUpdating method that returned an IDisposable so we could implement the using syntax instead?

using (MyListControl.BeginUpdating())
{
    foreach (Something something in stuff)
    {
        MyListControl.Items.Add(something.Description);
    }
}

I often implement this in custom controls. It's much nicer to work with and the using block takes care of all the finally stuff for me. You could easily add it to an existing control using the following pattern:

public class YourControl : Control
{
    //....
    
    public IDisposable BeginUpdating()
    {
        this.BeginUpdate();
        return new Updating(this);
    }
    
    private class Updating : IDisposable
    {
        private YourControl _control;
    
        public Updating(YourControl yourControl)
        {
            _control = yourControl;
        }
    
        public void Dispose()
        {
            _control.EndUpdate();
        }
    }
}

A useful technique, I'm sure you'll agree.

Note - the preferred way to add many items to a listbox is using AddRange, but sometimes this isn't convenient. You should find BeginUpdate and EndUpdate methods on most of the stock controls but they are not part of the Control base class.

EDIT - thanks to Brian for pointing out my error in hiding the Control.Update() method. I've changed the code to use BeginUpdating() - that'll teach me to code from memory :)

Tags: .NET

 
Josh Post By Josh Twist
1:53 AM
10 Jul 2006

» Next Post: Blowing our own trumpet
« Previous Post: RRAD makes me feel ill

Comments are closed for this post.

Posted by Brian @ 10 Jul 2006 7:24 AM
I like the above, but aren't you hiding Control.Update( ) with the above code?

Posted by Josh @ 10 Jul 2006 9:56 AM
Whoops - dead right Brian, corrected!

Thanks

Posted by Brian @ 11 Jul 2006 5:26 AM
No problem. Actually, ReSharper pointed it out to me when I added your code to my project. :)

© 2005 - 2014 Josh Twist - All Rights Reserved.