We currently have an application that reads data from serial communications. Throughout the application we need to display this data in the UI, and so we have created a method to update the textbox/label/numeric/progress bar using BeginInvoke.
However, this is starting to become cumbersome, as every control needs its own ‘Setter’, such that we already have 20 or so methods, which all do basically the same thing.
While I can see an easy way to genericize this to a specific control (e.g. only 1 for labels, 1 for textboxes), it would be ideal to only have 1 (maybe extension) method that we can call to update the data in the UI.
Here was our original method splayed everywhere:
private void SetCell1Cell2Async(decimal value)
{
if (spinCell1Cell2.InvokeRequired)
{
spinCell1Cell2.BeginInvoke(new EventHandler(delegate
{
spinCell1Cell2.Value = value;
}));
}
else
{
if (spinCell1Cell2.IsDisposed) return; // Do not process if the control has been disposed of
if (spinCell1Cell2.IsHandleCreated)
{
// This handle may not be created when creating this form AFTER data is already flowing
// We could capture this data for future display (i.e. via deferUpdate = true or similar), but it is easier to ignore it
// i.e. Do Nothing
return;
}
spinCell1Cell2.Value = value;
}
}
Here is our current method (this works for Controls that use the Text property to display data):
delegate void SetTextAsyncCallback(Control ctrl, string text);
public static void SetTextAsync(this Control invoker, string text)
{
if (invoker.InvokeRequired)
{
invoker.BeginInvoke(new SetTextAsyncCallback(SetTextAsync), invoker, text);
}
else
{
if (invoker.IsDisposed) return; // Do not process if the control has been disposed of
if (!invoker.IsHandleCreated)
{
// This handle may not be created when creating this form AFTER data is already flowing
// We could capture this data for future display (i.e. via deferUpdate = true or similar), but it is easier to ignore it
// i.e. Do Nothing
return;
}
invoker.Text = text;
}
}
As you may see, this method works with anything that uses the Text property to display its data.
Ideally I would like to be able to ‘pass in’ the property to update, and to supply a method that would take a string, double, decimal, boolean etc, but I’m a bit lost as where to go from here.
Any help appreciated.
I would make a more universal solution, with something like this in the Form:
Using delegates, you only have to declare the actual action once, while the type of execution is decided later on (in the SafeInvoke-method). If you’d rather have some extension methods, here is an example:
Edit
After reading your question again I noticed this wasn’t really what you asked about, so I’ll give you a more relevant example: