Winforms to WPF conversion: BeginInvoke to what?

mmr picture mmr · Apr 17, 2009 · Viewed 15.3k times · Source

Here's my old code from WinForms:

    private void ValueChanged(double inValue1, double inValue2) {
        //only manual mode for this driver, so that's easy.
        if (ValueLabel.InvokeRequired) {
            ValueLabel.Invoke(new MethodInvoker(delegate {
                ValueLabel.Text = (inValue1* inValue2/ 1000).ToString("f1");
            }
                ));
        }
        else {
            ValueLabel.Text = (inValue1* inValue2/ 1000).ToString("f1");
        }
    }

Is there an easy way to convert this to be WPF friendly? So far, I have:

   private void KVPValueChanged(double inValue1, double inValue2) {
        if (ValueLabel.Dispatcher.Thread == Thread.CurrentThread){
            ValueLabel.Content = (inValue1* inValue2/ 1000).ToString("f1");
        } else {
            ValueLabel.Dispatcher.BeginInvoke(delegate {
                ValueLabel.Content = (inValue1* inValue2/ 1000).ToString("f1");
            });
        }
    }

But that second 'delegate' call fails. How can I invoke this delegate? I suppose I can go through the whole making a delegate method, making an instance of the delegate method, invoking that particular instance, etc, but I thought the whole point of these anonymous delegates was to avoid that hassle. Plus, my old winforms code has that first implementation all over the place, so I'd really like to avoid having to de-anonymize all my delegates.

Edit: I can try to use the MethodInvoker like I was before, but then the compiler gets confused. MethodInvoker is part of System.Windows.Forms, so using that approach doesn't work. As in:

    private void ValueChanged(double inValue1, double inValue2) {
        if (ValueLabel.Dispatcher.Thread == Thread.CurrentThread) {
            ValueLabel.Content = (inValue1* inValue2/ 1000).ToString("f1");
        }
        else {
            ValueLabel.Dispatcher.BeginInvoke(new System.Windows.Forms.MethodInvoker(delegate {
                ValueLabel.Content = (inValue1* inValue2/ 1000).ToString("f1");
            }));
        }
    }

That use of MethodInvoker is not kosher. Is there a separate implementation of it, or some other way to use the same behavior?

Answer

mjeanes picture mjeanes · Apr 17, 2009

System.Windows.Forms.MethodInvoker is simply a Delegate that take no parameters and returns void. In WPF, you can just replace it with System.Action. There are also other built-in Delegates that accept parameters, return values, or both.

In your case,

ValueLabel.Dispatcher.BeginInvoke(new System.Windows.Forms.MethodInvoker(delegate {
            ValueLabel.Content = (inValue1* inValue2/ 1000).ToString("f1");
        }));

becomes

ValueLabel.Dispatcher.BeginInvoke(new Action(delegate() {
            ValueLabel.Content = (inValue1* inValue2/ 1000).ToString("f1");
        }));