0

I'm reading the weight on a scale connected over a serial port. When the weight changed the scale returns an event. This event is working great but I can't change the value of a WPF element in the event handler (tried both labels and textboxes) with the new weight.

The event handler is inside the correct window class.

When I call a messagebox to display the weight all is fine.

Can anyone explain to me how to change the wpf elements after the event callback. This is my callback function.

public void OnWeightUpdate(string weight) {
    if(String.IsNullOrEmpty(weight)) {
        MessageBox.Show("Empty weight string, possible bad connection with scale");
    }
    else {
        MessageBox.Show(weight);
        LblScaleAmount.Content = weight;
    }
}
Mark Baijens
  • 13,028
  • 11
  • 47
  • 73
  • Try to do `Dispatcher.Invoke(() => LblScaleAmount.Content = weight);` – Evk Jul 04 '17 at 07:57
  • Thanks a lot, that indeed did the trick. Please put your commend as an answer so i can accept it. – Mark Baijens Jul 04 '17 at 08:18
  • In WPF, the best answer is to simply use data binding. It is rare to need to call `Dispatcher.Invoke()` and it certainly does not seem appropriate here. See marked duplicate for details on how to do that, and other ways of managing cross-thread updates. – Peter Duniho Jul 04 '17 at 08:25
  • @PeterDuniho why it is certainly not appropriate here? – Evk Jul 04 '17 at 08:26
  • @Evk: because there's no need for it. In WPF, in some cases you are forced into it: you may be dealing with collection updates which are not automatically marshalled back to the UI thread, or you may have specific requirements regarding the scheduling of the callback, for example. But in this scenario, the root case is that the OP has failed to follow best practices in WPF and is setting UI element values from code-behind instead of using data binding. The right solution is to guide them toward using data binding, which will solve this and a host of other issues they don't even know they have. – Peter Duniho Jul 04 '17 at 08:31

1 Answers1

1

Since you receive weight information from serial port - there is a high chance that your callback runs on background (non-UI thread). You cannot update interface controls from background thread, so you need to dispatch update operation back to UI thread:

Dispatcher.Invoke(() => LblScaleAmount.Content = weight);
Evk
  • 98,527
  • 8
  • 141
  • 191