3

I'm wanting to update the UI from a SerialPort DataReceived event handler. I discovered a problem because the event handler was implicitly running in a different thread to the form, so rather than simply update the UI...

myLabel.Text = "Some text";

...I had to take the following approach:

    InvokeControlAction<Label>(myLabel, lbl=> lbl.Text= "Some text");
...
    public static void InvokeControlAction<t>(t cont, Action<t> action) where t : Control
    {
        if (cont.InvokeRequired)
        {
            cont.Invoke(new Action<t, Action<t>>(InvokeControlAction),
                          new object[] { cont, action });
        }
        else
        { 
            action(cont); 
        }
    }

So far so good... However, now I want to update a ToolStripStatusLabel - using the same approach yields a 'there is no implicit reference conversion between ToolStripStatusLabel and Forms.Control' error.

From what I have read, the problems stems from the fact that you can't Invoke a ToolStripStatusLabel.

So how best do I handle this?

Note: delegates, etc are at the threshold of my current ability, so an explanation alongside a solution would be appreciated.

UPDATE 1: Just to clarify, I tried to create ToolStripStatusLabel equivalent of InvokeControlAction, but this won't work because it doesn't have an invoke method.

RESULT: After revisiting my solution, I've implemented it as an Extension Method as Jimmy originally suggested.

I created an static ExtensionMethod class (in it's own 'ExtensionMethods' namespace), added in the InvokeOnToolStripItem method, add a 'using ExtensionMethods;' directive in my original class and called the methods as follows:

tsStatusValue.InvokeOnToolStripItem(ts => ts.Text = "ALARM signal received");
CJM
  • 11,908
  • 20
  • 77
  • 115
  • @Stecya - Care to elaborate? I think the solution *might* involve the StatusStrip's (that the ToolStripStatusLabel is an child of) .invoke method, but I wouldn't know how to begin to do this. – CJM May 12 '11 at 14:24

2 Answers2

2

ToolStripStatusLabel does not inherit from Control, and that's why your generic constraint fails for the exact reason you posted.

What is more, ToolStripStatusLabel (or any ToolStripItem in fact) doesn't have Invoke method. Luckily, containing ToolStrip has, which can be easily accessed using GetCurrentParent method.

Here's extension method that works on any ToolStripItem:

public static void InvokeOnToolStripItem<T>(this T item, Action<T> action)
    where T : ToolStripItem
{
    ToolStrip parent = item.GetCurrentParent();
    if (parent.InvokeRequired)
    {
        parent.Invoke((Delegate)action, new object[] { item });
    }
    else
    {
        action(item);
    }
}

You can use it by simply calling:

myToolStripLabel.InvokeOnToolStripItem(label => label.Text = "Updated!");
myToolStripProgressBar.InvokeOnToolStripItem(bar => bar.PerformStep());
k.m
  • 30,794
  • 10
  • 62
  • 86
  • Jimmy, you are following the route I have travelled! I had already tried the first solution in that CodeProject article and it didn't work.... doesn't recognise SetText and base.Items – CJM May 12 '11 at 15:16
  • You seem to be extending the Toolstrip controls; I embedded the code in my form but it works just the same. Not sure if there is any disadvantage here, but certainly it works! – CJM May 12 '11 at 16:42
  • Yep, extension method works for the very base class of ToolStripItem. This covers ToolStripLabel (which is base class for ToolStripStatusLabel) and few more items you can put in ToolStrip/StatusStrip controls. – k.m May 12 '11 at 16:52
  • Creating an extended control, though, means I can't use the form designed-time tools... which is a pain. – CJM May 12 '11 at 18:08
  • There is no extended control in play here - it's [Extension Method](http://msdn.microsoft.com/en-us/library/bb383977.aspx) (look at the `this` keyword before first argument). You still use regular ToolStripStatusLabel controls, and simply introduce new static class which contains this extension method. – k.m May 12 '11 at 18:15
  • Done some homework on Extension Methods and now implemented as you suggested - thanks again. – CJM May 13 '11 at 09:53
0

To explain the error message, you have writen

where t : Control

but ToolStripStatusLabel does not inherit from Control.

Not sure if that helps you at all and don't really have a solution yet :(

Buh Buh
  • 7,443
  • 1
  • 34
  • 61
  • Yeah, I'd tried creating a ToolStripStatusLabel alternative, but the problem is that it doesn't have an invoke method. – CJM May 12 '11 at 15:17