I am using a Telerik RadNumericUpDown
control in a C# Prism MVVM application. When my users hold down the up or down arrow the control increments the value of the property it is bound to. However, when that property value is changed, a command is sent to another device over a communications line with some latency. Also, there are instances where the device doesn't succeed in changing the value of this parameter.
Here is the code from my view.
<telerik:RadNumericUpDown x:Name="VoltageNumericControl" HorizontalAlignment="Left" Margin="165,0,0,0" Grid.RowSpan="1" VerticalAlignment="Center" Grid.Row="2" NumberDecimalDigits="2" Maximum="10.00" Minimum="0.00" SmallChange="0.01" ValueFormat="Numeric"
Value="{Binding ModelDevice.Voltage, Mode=TwoWay, Delay= 50}"/>
It increments the value in my ViewModel like:
public double Voltage
{
get { return voltage; }
set
{
dataService.SetVoltage(value); // Triggers command to external device
SetProperty(ref voltage, value); // Updates local value temporarily
// Value is then updated an indeterminate period later when a response is
// received from the external device
}
}
How can I change the behavior of the RadNumericUpDown
control so that holding down either the buttons or the arrow keys doesn't try to continuously update the value of the property its bound to?
How about disabling the control while the external device request is pending and enable it again, when you have a response and the correct value is known? Each control deriving from UIElement
has a property IsEnabled
, that you can use to deactivate user input (control appears greyed out).
Gets or sets a value indicating whether this element is enabled in the user interface (UI) [...] Elements that are not enabled do not participate in hit testing or focus and therefore will not be sources of input events.
You can create a property IsExternalDeviceNotPending
in your view model. and bind it to the IsEnabled
property on RadNumericUpDown
. Note the ..NotPending
(is enabled means no external device pending). If you wanted to make this a positive condition (...Pending
), you have have to use a value converter in XAML to negate the value, so this is simpler.
private bool isExternalDeviceNotPending;
public bool IsExternalDeviceNotPending
{
get => isExternalDeviceNotPending;
private set => SetProperty(ref isExternalDeviceNotPending, value);
}
}
<telerik:RadNumericUpDown x:Name="VoltageNumericControl" IsEnabled="{Binding IsExternalDeviceNotPending}" ... />
Now you can set the IsExternalDeviceNotPending
to false
when the Voltage
gets set, that in turn starts the communication with the external device. The control will be disabled then.
public double Voltage
{
get { return voltage; }
set
{
IsExternalDeviceNotPending = false;
dataService.SetVoltage(value);
SetProperty(ref voltage, value);
}
}
When communication is done, reset it to true
, to enable the control again and allow user input.