Category: code snippets

Updating Controls in Windows Forms

How often do you find yourself writing code like this:

string[] files = GetFiles(path);

filesListView.BeginUpdate();

for (int i = 0; i < files.Length; i++)

{

    //possibly something more

    filesListView.Items.Add(new ListViewItem(files[i]));

}

filesListView.EndUpdate();

You suspend control with BeginUpdate() in order not to repaint itself with every change you make, then do several updates to it, and then you let go of it, with EndUpdate(), so that it could repaint itself to reflect all the changes. Easy and simple isn’t it? So, what’s the problem? I can see at least two:

  1. Readability
  2. It’s error prone.

I created only very few lines of code for this example, but you have to look into the code to find the portion between BeginUpdate, and EndUpdate. It’s not apparent at the first glimpse of an eye, as it should be. I think that you should be able to immediatelly tell, what portion of the code happens when the control is suspended, and what not. With this code, you first have to parse it to find BeginUpdate(), and then matching EndUpdate.

And hey, have you ever forgotten to add EndUpdate, at the end of similar code snippet? It, compiles, you don’t even get a warning, but it works far from what you would like it to.

To overcome those constraints I decided  to create a simple helper class that would allow me to change code above to something like:

string[] files = GetFiles(path);

using (new Update<ListView>(filesListView))

{

    for (int i = 0; i < files.Length; i++)

    {

        //possibly something more

        filesListView.Items.Add(new ListViewItem(files[i]));

    }

}

//do something else if you need to

Isn’t it much cleaner? Immediately from looking at the code you can see which portion is in Update block. You also don’t have to worry

that  you forget to call EndUpdate() – it will be done for you.

If you ever played with WinForms controls, you certainly noticed that not every control has Begin/EndUpdate pair of methods. I never actually checked, but I assumed that for those who do have them, those methods come from some base class, or maybe interface. I was greatly surprised to discover, that neither of those assumptions was true. There simply are controls that do have those methods, and those that do not, period. I guess that’s not the best solution, and there should be and interface like IUpdateable, ISupportsUpdate or something.

Lack of that interface made me use Update<T> where T:Control instead of Update<T> where T:IUpdateable, so now you can pass in any control, even one, that has no Begin/EndUpdate methods implemented.

So what now? Throw NotImplementedException? That was my initial thought, but it means that everything would compile, and you would get exception during runtime which is something I really dislike. This leaves us with another option: if given control doesn’t implement said methods do nothing. It may seem the most reasonable option but it promises consistent behavior, and doesn’t provide it.

Imagine code like this:

using (new Update<Label>(myLabel))

{

    for (int i = 0; i < 10; i++)

    {

        myLabel.Text += i.ToString();

        Application.DoEvents();

        Thread.Sleep(500);

    }

}

Label, obviously doesn’t have Begin/EndUpdate, but it’s a Control and this code would compile. Someone would expect that for 5 seconds label’s text stays unchanged, and after that it updates, all the changes in one go. Well, he/she would be bitterly disappointed by the outcome, since instead of one change, we would have 10 of them. It’s not what we wanted, it’s not what we ought to have, since it means that we get inconsistent behavior.

So what now? I poke around a little bit with Reflector, and I discovered, that Control class has internal method BeginUpdateInternal, and consequently EndUpdateInternal. That’s what we wanted! Althought it’s a hacks, because we need to use reflection to call internal method from outside of its assembly it’s the best option we have in this situation. Now we can call public methods for controls that have them, and Control’s internal classes for other ones.

Still, I’m not completely satisfied with this solution. I shouldn’t be able to do it for Label, TextBox or any other control that is not meant to be updated this way, but to do this, all those controls that do support this behavior should all be marked with Interface, and that’s something that only BCL team can do.

Final code for Update<T> looks like this:

public class Update<T> : IDisposable where T : Control

{

    private T _control;

    private Type _type;

    private bool _hasPublicUpdate = false;

 

    public Update(T control)

    {

        _type = control.GetType();

        MethodInfo beginUpdate = _type.GetMethod("BeginUpdate");

        if (beginUpdate == null)

        {

            _type = typeof(System.Windows.Forms.Control);

            beginUpdate = _type.GetMethod("BeginUpdateInternal", BindingFlags.NonPublic | BindingFlags.Instance);

        }

        else

        {

            _hasPublicUpdate = true;

        }

        _control = control;

        beginUpdate.Invoke(_control, null);

    }

 

    public void Dispose()

    {

        MethodInfo endUpdate = null;

        if (_hasPublicUpdate)

        {

            endUpdate = _type.GetMethod("EndUpdate");

            endUpdate.Invoke(_control, null);

        }

        else

        {

            endUpdate = _type.GetMethod("EndUpdateInternal", BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { typeof(bool) }, new ParameterModifier[] { new ParameterModifier(1) });

            endUpdate.Invoke(_control, new object[] { true });

        }

        _control = null;

        GC.SuppressFinalize(this);

    }

}

Technorati tags: , , , , , ,

Get to running application from ROT

While cleaning old projects I found this one, that I wrote some time ago, and decided to post here, because it took me long time to figure it out, and although at the end it didn’t work (to clarify things, not because there is something wrong with it, because if how that particular app registered its instances to ROT) I don’t want to go through it again.

IBindCtx bindCtx;

Dictionary<string, Namespace.Application> items = new Dictionary<string, Namespace.Application>();

List<Namespace.Application> itms = new List<Namespace.Application>();

IRunningObjectTable rot;

IEnumMoniker monikerEnum;

IMoniker[] monikers = new IMoniker[1];

IntPtr numFetched;

string description = string.Empty;

object o;

Guid iid = new Guid("some guid here");

Namespace.Application app;

GetRunningObjectTable(0, out  rot);

rot.EnumRunning(out monikerEnum);

monikerEnum.Reset();

while (monikerEnum.Next(1, monikers, IntPtr.Zero)==0)

{

    try

    {

        rot.GetObject(monikers[0], out o);

        if (o is Namespace.Application)

        {

            CreateBindCtx(0, out bindCtx);

            monikers[0].BindToStorage(bindCtx, null, ref iid, out o);

            //monikers[0].GetDisplayName(bindCtx, null, out description);

            app = o as Namespace.Application;

            //app.ActiveApplication = true;

            //items.Add(description, o as Namespace.Application);

            app.PinOnTop = true;

            itms.Add(app);

        }

    }

    catch { }

}

return items;

Hope it helps someone.

Technorati Tags: , ,

How to embed custom control in ToolStrip

ToolStrip is very useful container control, but it has it’s default set of controls you can put onto it. What if you wanted to have, say DateTimePicker, or some totally custom control you have made? You can inherit it from ToolStripItem, override some methods and properties, but there is a much quicker way, if you don’t need any custom behaviour.

To illustrate this i created simple form with ToolStrip, and I embeded DateTimePicker into it, as you can se below (code follows)

As you can see, all the magic that happens is thanks to ToolStripControlHost class.

private void Form1_Load(object sender, EventArgs e)

{

   _deadlineDateTimePicker = new DateTimePicker();

   ToolStripControlHost _deadlineToolStripControlHost = new ToolStripControlHost(_deadlineDateTimePicker);

   _deadlineDateTimePicker.Width = 140;

   _mainToolStrip.SuspendLayout();

   _mainToolStrip.Items.Add(_deadlineToolStripControlHost);

   //add other controls here

   _mainToolStrip.ResumeLayout();

}

Measure code execution time

From time to time there is a need to measure how much time it takes for a certain fragment of code to execute.

First thought how to do this would probably be something like this:

            DateTime start = new DateTime();
            DoSomething();
            TimeSpan time = DateTime.Now.Subtract(start);
            Console.WriteLine("Time taken: {0}", time.Ticks.ToString());

In .NET 2.0 however there is a class tailored fir this task: System.Diagnostics.Stopwatch.

To use it you would rewrite code above to something like:

            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            DoSomething();
            stopwatch.Stop();
            Console.WriteLine("Time measured: {0}", stopwatch.ElapsedTicks.ToString());

To learn more, visit MSDN site.

 

How to get an image given its URL

Form with loaded image
While cleaning old temporary projects, I usually create to test some feature, I found one, that I think may me useful, so i decided to post it here.

It’s a program I created some time ago, when i needed to download a image, from given URL and display it, or save. Here is the simplest solution to do this.

WebClient c = new WebClient();
byte[] b = c.DownloadData(textBox1.Text);
using (MemoryStream ms = new MemoryStream(b))
{
    Bitmap i = new Bitmap(ms);
    panel1.BackgroundImage = i;
}
panel1.BackgroundImageLayout = ImageLayout.Center;