1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
| [TemplatePart(Name = "PART_UpButton", Type = typeof(ButtonBase))]
[TemplatePart(Name = "PART_DownButton", Type = typeof(ButtonBase))]
[TemplatePart(Name = "PART_TextBox", Type = typeof(TextBox))]
[DefaultEvent("ValueChanged")]
public class NumericUpDown : Control
{
static NumericUpDown()
{
DefaultStyleKeyProperty.OverrideMetadata(
typeof(NumericUpDown),
new FrameworkPropertyMetadata(typeof(NumericUpDown)));
}
#region Value
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register(nameof(Value), typeof(int), typeof(NumericUpDown),
new FrameworkPropertyMetadata(0,
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
OnValueChanged, CoerceValue),
ValidateValue);
public int Value
{
get => (int)GetValue(ValueProperty);
set => SetValue(ValueProperty, value);
}
private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var c = (NumericUpDown)d;
if (c._textBox != null) c._textBox.Text = e.NewValue.ToString();
c.RaiseEvent(new RoutedPropertyChangedEventArgs<int>(
(int)e.OldValue, (int)e.NewValue, ValueChangedEvent));
}
private static object CoerceValue(DependencyObject d, object v)
{
var c = (NumericUpDown)d;
var value = (int)v;
return value < c.Minimum ? c.Minimum
: value > c.Maximum ? c.Maximum
: value;
}
private static bool ValidateValue(object v) => v is int;
#endregion
#region Minimum / Maximum / SmallChange
public int Minimum { get => (int)GetValue(MinimumProperty); set => SetValue(MinimumProperty, value); }
public static readonly DependencyProperty MinimumProperty =
DependencyProperty.Register(nameof(Minimum), typeof(int), typeof(NumericUpDown),
new FrameworkPropertyMetadata(0, (d, e) => ((NumericUpDown)d).CoerceValue(ValueProperty)));
public int Maximum { get => (int)GetValue(MaximumProperty); set => SetValue(MaximumProperty, value); }
public static readonly DependencyProperty MaximumProperty =
DependencyProperty.Register(nameof(Maximum), typeof(int), typeof(NumericUpDown),
new FrameworkPropertyMetadata(100, (d, e) => ((NumericUpDown)d).CoerceValue(ValueProperty)));
public int SmallChange { get => (int)GetValue(SmallChangeProperty); set => SetValue(SmallChangeProperty, value); }
public static readonly DependencyProperty SmallChangeProperty =
DependencyProperty.Register(nameof(SmallChange), typeof(int), typeof(NumericUpDown), new PropertyMetadata(1));
#endregion
#region ValueChanged event
public static readonly RoutedEvent ValueChangedEvent =
EventManager.RegisterRoutedEvent(nameof(ValueChanged), RoutingStrategy.Bubbling,
typeof(RoutedPropertyChangedEventHandler<int>), typeof(NumericUpDown));
public event RoutedPropertyChangedEventHandler<int> ValueChanged
{
add => AddHandler(ValueChangedEvent, value);
remove => RemoveHandler(ValueChangedEvent, value);
}
#endregion
private ButtonBase? _upButton;
private ButtonBase? _downButton;
private TextBox? _textBox;
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
if (_upButton != null) _upButton.Click -= (_, _) => Value += SmallChange;
if (_downButton != null) _downButton.Click -= (_, _) => Value -= SmallChange;
if (_textBox != null) _textBox.TextChanged -= OnTextBoxTextChanged;
_upButton = GetTemplateChild("PART_UpButton") as ButtonBase;
_downButton = GetTemplateChild("PART_DownButton") as ButtonBase;
_textBox = GetTemplateChild("PART_TextBox") as TextBox;
if (_upButton != null) _upButton.Click += (_, _) => Value += SmallChange;
if (_downButton != null) _downButton.Click += (_, _) => Value -= SmallChange;
if (_textBox != null)
{
_textBox.Text = Value.ToString();
_textBox.TextChanged += OnTextBoxTextChanged;
}
}
private void OnTextBoxTextChanged(object sender, TextChangedEventArgs e)
{
if (int.TryParse(_textBox!.Text, out int result))
Value = result;
}
}
|