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<开发者_StackOverflow中文版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");
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());
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 :(
精彩评论