Skip to content

Commit 9cf0c82

Browse files
committed
Fixing clamping on NumericUpDown control
Updated UI test, but need new XAMLTest before it will run
1 parent 190649c commit 9cf0c82

File tree

7 files changed

+52
-92
lines changed

7 files changed

+52
-92
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+

2+
#if NET462
3+
namespace System.Diagnostics.CodeAnalysis;
4+
//
5+
// Summary:
6+
// Specifies that when a method returns System.Diagnostics.CodeAnalysis.NotNullWhenAttribute.ReturnValue,
7+
// the parameter will not be null even if the corresponding type allows it.
8+
[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
9+
internal sealed class NotNullWhenAttribute : Attribute
10+
{
11+
//
12+
// Summary:
13+
// Initializes the attribute with the specified return value condition.
14+
//
15+
// Parameters:
16+
// returnValue:
17+
// The return value condition. If the method returns this value, the associated
18+
// parameter will not be null.
19+
public NotNullWhenAttribute(bool returnValue)
20+
{
21+
ReturnValue = returnValue;
22+
}
23+
24+
//
25+
// Summary:
26+
// Gets the return value condition.
27+
//
28+
// Returns:
29+
// The return value condition. If the method returns this value, the associated
30+
// parameter will not be null.
31+
public bool ReturnValue { get; }
32+
}
33+
#endif

src/MaterialDesignThemes.Wpf/UpDownBase.cs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
namespace MaterialDesignThemes.Wpf;
55

6+
using System.Diagnostics.CodeAnalysis;
7+
68

79
#if NET8_0_OR_GREATER
810
using System.Numerics;
@@ -20,7 +22,7 @@ public class UpDownBase<T> : UpDownBase
2022
private static T Clamp(T value, T min, T max) => T.Clamp(value, min, max);
2123
private static T Add(T value1, T value2) => value1 + value2;
2224
private static T Subtract(T value1, T value2) => value1 - value2;
23-
private static bool TryParse(string text, IFormatProvider? formatProvider, out T? value)
25+
private static bool TryParse(string text, IFormatProvider? formatProvider, [MaybeNullWhen(false)] out T value)
2426
=> T.TryParse(text, formatProvider, out value);
2527
private static int Compare(T value1, T value2) => value1.CompareTo(value2);
2628
#else
@@ -39,8 +41,9 @@ public class UpDownBase<T, TArithmetic> : UpDownBase
3941
private static T Clamp(T value, T min, T max) => _arithmetic.Max(_arithmetic.Min(value, max), min);
4042
private static T Add(T value1, T value2) => _arithmetic.Add(value1, value2);
4143
private static T Subtract(T value1, T value2) => _arithmetic.Subtract(value1, value2);
42-
private static bool TryParse(string text, IFormatProvider? formatProvider, out T? value)
44+
private static bool TryParse(string text, IFormatProvider? formatProvider, [NotNullWhen(true)] out T value)
4345
=> _arithmetic.TryParse(text, formatProvider, out value);
46+
4447
private static int Compare(T value1, T value2) => _arithmetic.Compare(value1, value2);
4548
#endif
4649

@@ -134,7 +137,7 @@ private static void OnNumericValueChanged(DependencyObject d, DependencyProperty
134137
if (value is T numericValue)
135138
{
136139
var upDownBase = ToUpDownBase(d);
137-
numericValue = Clamp(numericValue, upDownBase.Minimum, upDownBase.Maximum);
140+
numericValue = upDownBase.ClampValue(numericValue);
138141
return numericValue;
139142
}
140143
return value;
@@ -213,7 +216,7 @@ private void OnTextBoxFocusLost(object sender, EventArgs e)
213216
{
214217
if (TryParse(textBoxField.Text, CultureInfo.CurrentUICulture, out T? value))
215218
{
216-
SetCurrentValue(ValueProperty, value);
219+
SetCurrentValue(ValueProperty, ClampValue(value));
217220
}
218221
//NB: Because setting ValueProperty will coerce the value, we re-assign back to the textbox here.
219222
textBoxField.Text = Value?.ToString();
@@ -228,6 +231,9 @@ private void OnTextBoxFocusLost(object sender, EventArgs e)
228231

229232
private void OnDecrease() => SetCurrentValue(ValueProperty, Clamp(Subtract(Value, ValueStep), Minimum, Maximum));
230233

234+
private T ClampValue(T value)
235+
=> Clamp(value, Minimum, Maximum);
236+
231237
protected override void OnPreviewKeyDown(KeyEventArgs e)
232238
{
233239
if (e.Key == Key.Up)
@@ -364,6 +370,6 @@ public interface IArithmetic<T>
364370

365371
T Min(T value1, T value2);
366372

367-
bool TryParse(string text, IFormatProvider? formatProvider, out T? value);
373+
bool TryParse(string text, IFormatProvider? formatProvider, [NotNullWhen(true)] out T value);
368374
}
369375
#endif

tests/MaterialDesignThemes.UITests/Samples/UpDownControls/BoundNumericUpDown.xaml.cs

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,4 @@
1-
using System;
2-
using System.Collections.Generic;
3-
using System.Linq;
4-
using System.Text;
5-
using System.Threading.Tasks;
6-
using System.Windows;
7-
using System.Windows.Controls;
8-
using System.Windows.Data;
9-
using System.Windows.Documents;
10-
using System.Windows.Input;
11-
using System.Windows.Media;
12-
using System.Windows.Media.Imaging;
13-
using System.Windows.Navigation;
14-
using System.Windows.Shapes;
15-
using Xunit.Sdk;
16-
17-
namespace MaterialDesignThemes.UITests.Samples.UpDownControls;
1+
namespace MaterialDesignThemes.UITests.Samples.UpDownControls;
182

193
/// <summary>
204
/// Interaction logic for BoundNumericUpDown.xaml
@@ -23,8 +7,8 @@ public partial class BoundNumericUpDown : UserControl
237
{
248
public BoundNumericUpDown()
259
{
26-
this.ViewModel = new BoundNumericUpDownViewModel();
27-
this.DataContext = this.ViewModel;
10+
ViewModel = new BoundNumericUpDownViewModel();
11+
DataContext = ViewModel;
2812
InitializeComponent();
2913
}
3014

tests/MaterialDesignThemes.UITests/Samples/UpDownControls/BoundNumericUpDownViewModel.cs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,4 @@
1-
using System;
2-
using System.Collections.Generic;
3-
using System.Linq;
4-
using System.Text;
5-
using System.Threading.Tasks;
6-
using CommunityToolkit.Mvvm.ComponentModel;
1+
using CommunityToolkit.Mvvm.ComponentModel;
72

83
namespace MaterialDesignThemes.UITests.Samples.UpDownControls;
94

tests/MaterialDesignThemes.UITests/Samples/UpDownControls/BoundNumericUpDownWindow.xaml

Lines changed: 0 additions & 22 deletions
This file was deleted.

tests/MaterialDesignThemes.UITests/Samples/UpDownControls/BoundNumericUpDownWindow.xaml.cs

Lines changed: 0 additions & 34 deletions
This file was deleted.

tests/MaterialDesignThemes.UITests/WPF/UpDownControls/NumericUpDownTests.cs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -158,15 +158,13 @@ public async Task InternalTextBoxIsFocused_WhenGettingKeyboardFocus()
158158
recorder.Success();
159159
}
160160

161-
[Fact]
161+
[Fact(Skip = "Needs XAMLTest 1.2.3 or later")]
162162
public async Task NumericUpDown_ValueSetGreaterThanMaximum_CoercesToMaximum()
163163
{
164164
await using var recorder = new TestRecorder(App);
165165

166166
//Arrange
167-
await App.InitializeWithMaterialDesign();
168-
IWindow window = await App.CreateWindow<BoundNumericUpDownWindow>();
169-
var userControl = await window.GetElement<BoundNumericUpDown>();
167+
var userControl = await LoadUserControl<BoundNumericUpDown>();
170168
var numericUpDown = await userControl.GetElement<NumericUpDown>();
171169
var buttonToFocus = await userControl.GetElement<Button>("btnToFocus");
172170

@@ -177,15 +175,15 @@ public async Task NumericUpDown_ValueSetGreaterThanMaximum_CoercesToMaximum()
177175
//Act
178176
//Input a number greater than the maximum
179177
await numericUpDown.MoveKeyboardFocus();
180-
//await numericUpDown.SendInput(new KeyboardInput("99"));
181178
await numericUpDown.SendKeyboardInput($"99");
179+
182180
await buttonToFocus.MoveKeyboardFocus();
183181

184182
//Assert
185183
//The value and bound property in the VM should be set to the maximum
186184
Assert.Equal(10, await numericUpDown.GetValue());
187185
var viewModel = await userControl.GetProperty<BoundNumericUpDownViewModel>(nameof(BoundNumericUpDown.ViewModel));
188-
Assert.Equal(10, viewModel.Value);
186+
Assert.Equal(10, viewModel?.Value);
189187

190188
recorder.Success();
191189
}

0 commit comments

Comments
 (0)