|
1 |
| -using System.ComponentModel; |
| 1 | +#if !NET8_0_OR_GREATER |
2 | 2 | using System.Globalization;
|
| 3 | +#endif |
3 | 4 |
|
4 | 5 | namespace MaterialDesignThemes.Wpf;
|
5 | 6 |
|
6 |
| -[TemplatePart(Name = IncreaseButtonPartName, Type = typeof(RepeatButton))] |
7 |
| -[TemplatePart(Name = DecreaseButtonPartName, Type = typeof(RepeatButton))] |
8 |
| -[TemplatePart(Name = TextBoxPartName, Type = typeof(TextBox))] |
9 |
| -public class NumericUpDown : Control |
| 7 | +public class NumericUpDown |
| 8 | +#if NET8_0_OR_GREATER |
| 9 | + : UpDownBase<int> |
| 10 | +#else |
| 11 | + : UpDownBase<int, IntArithmetic> |
| 12 | +#endif |
10 | 13 | {
|
11 |
| - public const string IncreaseButtonPartName = "PART_IncreaseButton"; |
12 |
| - public const string DecreaseButtonPartName = "PART_DecreaseButton"; |
13 |
| - public const string TextBoxPartName = "PART_TextBox"; |
14 |
| - |
15 |
| - private TextBox? _textBoxField; |
16 |
| - private RepeatButton? _decreaseButton; |
17 |
| - private RepeatButton? _increaseButton; |
18 |
| - |
19 | 14 | static NumericUpDown()
|
20 | 15 | {
|
21 | 16 | DefaultStyleKeyProperty.OverrideMetadata(typeof(NumericUpDown), new FrameworkPropertyMetadata(typeof(NumericUpDown)));
|
22 | 17 | }
|
| 18 | +} |
23 | 19 |
|
24 |
| - #region DependencyProperties |
25 |
| - |
26 |
| - |
27 |
| - |
28 |
| - public object? IncreaseContent |
29 |
| - { |
30 |
| - get => GetValue(IncreaseContentProperty); |
31 |
| - set => SetValue(IncreaseContentProperty, value); |
32 |
| - } |
33 |
| - |
34 |
| - // Using a DependencyProperty as the backing store for IncreaseContent. This enables animation, styling, binding, etc... |
35 |
| - public static readonly DependencyProperty IncreaseContentProperty = |
36 |
| - DependencyProperty.Register(nameof(IncreaseContent), typeof(object), typeof(NumericUpDown), new PropertyMetadata(null)); |
37 |
| - |
38 |
| - public object? DecreaseContent |
39 |
| - { |
40 |
| - get => GetValue(DecreaseContentProperty); |
41 |
| - set => SetValue(DecreaseContentProperty, value); |
42 |
| - } |
43 |
| - |
44 |
| - // Using a DependencyProperty as the backing store for DecreaseContent. This enables animation, styling, binding, etc... |
45 |
| - public static readonly DependencyProperty DecreaseContentProperty = |
46 |
| - DependencyProperty.Register(nameof(DecreaseContent), typeof(object), typeof(NumericUpDown), new PropertyMetadata(null)); |
47 |
| - |
48 |
| - #region DependencyProperty : MinimumProperty |
49 |
| - public int Minimum |
50 |
| - { |
51 |
| - get => (int)GetValue(MinimumProperty); |
52 |
| - set => SetValue(MinimumProperty, value); |
53 |
| - } |
54 |
| - public static readonly DependencyProperty MinimumProperty = |
55 |
| - DependencyProperty.Register(nameof(Minimum), typeof(int), typeof(NumericUpDown), new PropertyMetadata(int.MinValue, OnMinimumChanged)); |
56 |
| - |
57 |
| - private static void OnMinimumChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) |
58 |
| - { |
59 |
| - NumericUpDown ctrl = (NumericUpDown)d; |
60 |
| - ctrl.CoerceValue(ValueProperty); |
61 |
| - ctrl.CoerceValue(MaximumProperty); |
62 |
| - } |
63 |
| - |
64 |
| - #endregion DependencyProperty : MinimumProperty |
65 |
| - |
66 |
| - #region DependencyProperty : MaximumProperty |
67 |
| - |
68 |
| - public int Maximum |
69 |
| - { |
70 |
| - get => (int)GetValue(MaximumProperty); |
71 |
| - set => SetValue(MaximumProperty, value); |
72 |
| - } |
73 |
| - |
74 |
| - public static readonly DependencyProperty MaximumProperty = |
75 |
| - DependencyProperty.Register(nameof(Maximum), typeof(int), typeof(NumericUpDown), new PropertyMetadata(int.MaxValue, OnMaximumChanged, CoerceMaximum)); |
76 |
| - |
77 |
| - private static void OnMaximumChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) |
78 |
| - { |
79 |
| - NumericUpDown ctrl = (NumericUpDown)d; |
80 |
| - ctrl.CoerceValue(ValueProperty); |
81 |
| - } |
82 |
| - |
83 |
| - private static object? CoerceMaximum(DependencyObject d, object? value) |
84 |
| - { |
85 |
| - if (d is NumericUpDown numericUpDown && |
86 |
| - value is int numericValue) |
87 |
| - { |
88 |
| - return Math.Max(numericUpDown.Minimum, numericValue); |
89 |
| - } |
90 |
| - return value; |
91 |
| - } |
92 |
| - |
93 |
| - #endregion DependencyProperty : MaximumProperty |
94 |
| - |
95 |
| - #region DependencyProperty : ValueProperty |
96 |
| - public int Value |
97 |
| - { |
98 |
| - get => (int)GetValue(ValueProperty); |
99 |
| - set => SetValue(ValueProperty, value); |
100 |
| - } |
101 |
| - |
102 |
| - public static readonly DependencyProperty ValueProperty = |
103 |
| - DependencyProperty.Register(nameof(Value), typeof(int), typeof(NumericUpDown), new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnNumericValueChanged, CoerceNumericValue)); |
104 |
| - |
105 |
| - private static void OnNumericValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) |
106 |
| - { |
107 |
| - if (d is NumericUpDown numericUpDown) |
108 |
| - { |
109 |
| - var args = new RoutedPropertyChangedEventArgs<int>((int)e.OldValue, (int)e.NewValue) |
110 |
| - { |
111 |
| - RoutedEvent = ValueChangedEvent |
112 |
| - }; |
113 |
| - numericUpDown.RaiseEvent(args); |
114 |
| - if (numericUpDown._textBoxField is { } textBox) |
115 |
| - { |
116 |
| - textBox.Text = ((int)e.NewValue).ToString(CultureInfo.CurrentUICulture); |
117 |
| - } |
118 |
| - |
119 |
| - if (numericUpDown._increaseButton is { } increaseButton) |
120 |
| - { |
121 |
| - increaseButton.IsEnabled = numericUpDown.Value != numericUpDown.Maximum; |
122 |
| - } |
123 |
| - |
124 |
| - if (numericUpDown._decreaseButton is { } decreaseButton) |
125 |
| - { |
126 |
| - decreaseButton.IsEnabled = numericUpDown.Value != numericUpDown.Minimum; |
127 |
| - } |
128 |
| - } |
129 |
| - } |
130 |
| - |
131 |
| - private static object? CoerceNumericValue(DependencyObject d, object? value) |
132 |
| - { |
133 |
| - if (d is NumericUpDown numericUpDown && |
134 |
| - value is int numericValue) |
135 |
| - { |
136 |
| - numericValue = Math.Min(numericUpDown.Maximum, numericValue); |
137 |
| - numericValue = Math.Max(numericUpDown.Minimum, numericValue); |
138 |
| - return numericValue; |
139 |
| - } |
140 |
| - return value; |
141 |
| - } |
142 |
| - #endregion ValueProperty |
143 |
| - |
144 |
| - #region DependencyProperty : AllowChangeOnScroll |
145 |
| - |
146 |
| - public bool AllowChangeOnScroll |
147 |
| - { |
148 |
| - get => (bool)GetValue(AllowChangeOnScrollProperty); |
149 |
| - set => SetValue(AllowChangeOnScrollProperty, value); |
150 |
| - } |
151 |
| - |
152 |
| - public static readonly DependencyProperty AllowChangeOnScrollProperty = |
153 |
| - DependencyProperty.Register(nameof(AllowChangeOnScroll), typeof(bool), typeof(NumericUpDown), new PropertyMetadata(false)); |
154 |
| - |
155 |
| - #endregion |
156 |
| - |
157 |
| - #endregion DependencyProperties |
158 |
| - |
159 |
| - #region Event : ValueChangedEvent |
160 |
| - [Category("Behavior")] |
161 |
| - public static readonly RoutedEvent ValueChangedEvent = EventManager.RegisterRoutedEvent(nameof(ValueChanged), RoutingStrategy.Bubble, typeof(RoutedPropertyChangedEventHandler<int>), typeof(NumericUpDown)); |
162 |
| - |
163 |
| - public event RoutedPropertyChangedEventHandler<int> ValueChanged |
164 |
| - { |
165 |
| - add => AddHandler(ValueChangedEvent, value); |
166 |
| - remove => RemoveHandler(ValueChangedEvent, value); |
167 |
| - } |
168 |
| - #endregion Event : ValueChangedEvent |
169 |
| - |
170 |
| - public override void OnApplyTemplate() |
171 |
| - { |
172 |
| - if (_increaseButton != null) |
173 |
| - _increaseButton.Click -= IncreaseButtonOnClick; |
174 |
| - |
175 |
| - if (_decreaseButton != null) |
176 |
| - _decreaseButton.Click -= DecreaseButtonOnClick; |
177 |
| - if (_textBoxField != null) |
178 |
| - _textBoxField.TextChanged -= OnTextBoxFocusLost; |
179 |
| - |
180 |
| - _increaseButton = GetTemplateChild(IncreaseButtonPartName) as RepeatButton; |
181 |
| - _decreaseButton = GetTemplateChild(DecreaseButtonPartName) as RepeatButton; |
182 |
| - _textBoxField = GetTemplateChild(TextBoxPartName) as TextBox; |
183 |
| - |
184 |
| - if (_increaseButton != null) |
185 |
| - _increaseButton.Click += IncreaseButtonOnClick; |
186 |
| - |
187 |
| - if (_decreaseButton != null) |
188 |
| - _decreaseButton.Click += DecreaseButtonOnClick; |
189 |
| - |
190 |
| - if (_textBoxField != null) |
191 |
| - { |
192 |
| - _textBoxField.LostFocus += OnTextBoxFocusLost; |
193 |
| - _textBoxField.Text = Value.ToString(CultureInfo.CurrentUICulture); |
194 |
| - } |
195 |
| - |
196 |
| - base.OnApplyTemplate(); |
197 |
| - } |
| 20 | +#if !NET8_0_OR_GREATER |
| 21 | +public class IntArithmetic : IArithmetic<int> |
| 22 | +{ |
| 23 | + public int Add(int value1, int value2) => value1 + value2; |
198 | 24 |
|
199 |
| - private void OnTextBoxFocusLost(object sender, EventArgs e) |
200 |
| - { |
201 |
| - if (_textBoxField is { } textBoxField) |
202 |
| - { |
203 |
| - if (int.TryParse(textBoxField.Text, NumberStyles.Integer, CultureInfo.CurrentUICulture, out int numericValue)) |
204 |
| - { |
205 |
| - SetCurrentValue(ValueProperty, numericValue); |
206 |
| - } |
207 |
| - else |
208 |
| - { |
209 |
| - textBoxField.Text = Value.ToString(CultureInfo.CurrentUICulture); |
210 |
| - } |
211 |
| - } |
212 |
| - } |
| 25 | + public int Subtract(int value1, int value2) => value1 - value2; |
213 | 26 |
|
214 |
| - private void IncreaseButtonOnClick(object sender, RoutedEventArgs e) => OnIncrease(); |
| 27 | + public int Compare(int value1, int value2) => value1.CompareTo(value2); |
215 | 28 |
|
216 |
| - private void DecreaseButtonOnClick(object sender, RoutedEventArgs e) => OnDecrease(); |
| 29 | + public int MinValue() => int.MinValue; |
217 | 30 |
|
218 |
| - private void OnIncrease() |
219 |
| - { |
220 |
| - SetCurrentValue(ValueProperty, Value + 1); |
221 |
| - } |
| 31 | + public int MaxValue() => int.MaxValue; |
| 32 | + public int One() => 1; |
222 | 33 |
|
223 |
| - private void OnDecrease() |
224 |
| - { |
225 |
| - SetCurrentValue(ValueProperty, Value - 1); |
226 |
| - } |
| 34 | + public int Max(int value1, int value2) => Math.Max(value1, value2); |
227 | 35 |
|
228 |
| - protected override void OnPreviewKeyDown(KeyEventArgs e) |
229 |
| - { |
230 |
| - if (e.Key == Key.Up) |
231 |
| - { |
232 |
| - OnIncrease(); |
233 |
| - e.Handled = true; |
234 |
| - } |
235 |
| - else if (e.Key == Key.Down) |
236 |
| - { |
237 |
| - OnDecrease(); |
238 |
| - e.Handled = true; |
239 |
| - } |
240 |
| - base.OnPreviewKeyDown(e); |
241 |
| - } |
| 36 | + public int Min(int value1, int value2) => Math.Min(value1, value2); |
242 | 37 |
|
243 |
| - protected override void OnPreviewMouseWheel(MouseWheelEventArgs e) |
244 |
| - { |
245 |
| - if (IsKeyboardFocusWithin && AllowChangeOnScroll) |
246 |
| - { |
247 |
| - if (e.Delta > 0) |
248 |
| - { |
249 |
| - OnIncrease(); |
250 |
| - } |
251 |
| - else if (e.Delta < 0) |
252 |
| - { |
253 |
| - OnDecrease(); |
254 |
| - } |
255 |
| - e.Handled = true; |
256 |
| - } |
257 |
| - base.OnPreviewMouseWheel(e); |
258 |
| - } |
| 38 | + public bool TryParse(string text, IFormatProvider? formatProvider, out int value) |
| 39 | + => int.TryParse(text, NumberStyles.Integer, formatProvider, out value); |
259 | 40 | }
|
| 41 | +#endif |
0 commit comments