Search code examples
c#wpfxamltelerikprism

RadNumericUpDown Increment Rate


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?


Solution

  • 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.