wpf中NumericUpDown控件
NumericUpDown控件看起来像是⼀个⽂本框与⼀对⽤户可单击以调整值的箭头的组合。该控件显⽰并设置固定的数值选择列表中的单个数值。⽤户可以通过单击向上和向下、按向上和向下键或在控件的⽂本框部件中键⼊⼀个数字来增⼤和减⼩数字。单击向上键时,值向最⼤值⽅向移动;单击向下键时,值向最⼩值⽅向移动。
我这⾥提供的是在⽹上找的别⼈⾃⼰写好的NumericUpDown控件,然后我进⾏了样式修改,修改之后是长按向上键,值会不停的增⼤,直⾄最⼤值,同理,长按向下键,值会不停的减⼩,直⾄最⼩值(就是把以前的Button换成了RepeatButton)。单击功能仍和以前⼀样。
代码奉上:
⾸先这个是⾃定义控件:
public class NumericUpDown : Control
{
static NumericUpDown()
{
InitializeCommands();
// Listen to MouLeftButtonDown event to determine if NumericUpDown should move focus to itlf
EventManager.RegisterClassHandler(typeof(NumericUpDown),
Mou.MouDownEvent, new MouButtonEventHandler(NumericUpDown.OnMouLeftButtonDown), true);
DefaultStyleKeyProperty.OverrideMetadata(typeof(NumericUpDown), new FrameworkPropertyMetadata(typeof(NumericUpDown)));
}
public NumericUpDown()
: ba()
{
updateValueString();
}
#region Properties
#region Value
public decimal Value
{
get { return (decimal)GetValue(ValueProperty); }
t { SetValue(ValueProperty, value); }
}
/// <summary>
/// Identifies the Value dependency property.
/
// </summary>
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register(
"Value", typeof(decimal), typeof(NumericUpDown),
new FrameworkPropertyMetadata(DefaultValue,
new PropertyChangedCallback(OnValueChanged),
new CoerceValueCallback(CoerceValue)
)
);
private static void OnValueChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
{
NumericUpDown control = (NumericUpDown)obj;
decimal oldValue = (decimal)args.OldValue;
decimal newValue = (decimal)args.NewValue;
#region Fire Automation events
NumericUpDownAutomationPeer peer = UIElementAutomationPeer.FromElement(control) as NumericUpDownAutomationPeer;
if (peer != null)
{
peer.RaiValueChangedEvent(oldValue, newValue);
}
#endregion
RoutedPropertyChangedEventArgs<decimal> e = new RoutedPropertyChangedEventArgs<decimal>(
oldValue, newValue, ValueChangedEvent);
control.OnValueChanged(e);
control.updateValueString();
跳跳糖舞蹈}
/// <summary>
/// Rais the ValueChanged event.
/// </summary>
/// <param name="args">Arguments associated with the ValueChanged event.</param>
protected virtual void OnValueChanged(RoutedPropertyChangedEventArgs<decimal> args)
{
RaiEvent(args);
}
private static object CoerceValue(DependencyObject element, object value)
{
decimal newValue = (decimal)value;
NumericUpDown control = (NumericUpDown)element;
newValue = Math.Max(control.Minimum, Math.Min(control.Maximum, newValue));
newValue = Decimal.Round(newValue, control.DecimalPlaces);
return newValue;
}
#endregion
#region Minimum
public decimal Minimum
{
get { return (decimal)GetValue(MinimumProperty); }
t { SetValue(MinimumProperty, value); }
}
public static readonly DependencyProperty MinimumProperty =
DependencyProperty.Register(
"Minimum", typeof(decimal), typeof(NumericUpDown),
new FrameworkPropertyMetadata(DefaultMinValue,
new PropertyChangedCallback(OnMinimumChanged), new CoerceValueCallback(CoerceMinimum)
)
);
private static void OnMinimumChanged(DependencyObject element, DependencyPropertyChangedEventArgs args) {
element.CoerceValue(MaximumProperty);
element.CoerceValue(ValueProperty);
}
private static object CoerceMinimum(DependencyObject element, object value)
{
decimal minimum = (decimal)value;
NumericUpDown control = (NumericUpDown)element;
return Decimal.Round(minimum, control.DecimalPlaces);
}
#endregion
#region Maximum猫齿鲨
public decimal Maximum
{
get { return (decimal)GetValue(MaximumProperty); }
t { SetValue(MaximumProperty, value); }
}
public static readonly DependencyProperty MaximumProperty =
DependencyProperty.Register(
"Maximum", typeof(decimal), typeof(NumericUpDown),
new FrameworkPropertyMetadata(DefaultMaxValue,
new PropertyChangedCallback(OnMaximumChanged),
new CoerceValueCallback(CoerceMaximum)
)
);
private static void OnMaximumChanged(DependencyObject element, DependencyPropertyChangedEventArgs args) {
element.CoerceValue(ValueProperty);
}
人有孝心private static object CoerceMaximum(DependencyObject element, object value)
{
NumericUpDown control = (NumericUpDown)element;
decimal newMaximum = (decimal)value;
return Decimal.Round(Math.Max(newMaximum, control.Minimum), control.DecimalPlaces);
}
#endregion
#region Change
public decimal Change
get { return (decimal)GetValue(ChangeProperty); }
t { SetValue(ChangeProperty, value); }
}
public static readonly DependencyProperty ChangeProperty =
DependencyProperty.Register(
"Change", typeof(decimal), typeof(NumericUpDown),
new FrameworkPropertyMetadata(DefaultChange, new PropertyChangedCallback(OnChangeChanged), new CoerceValueCallback(CoerceChange)), new ValidateValueCallback(ValidateChange)
);
private static bool ValidateChange(object value)
{
decimal change = (decimal)value;
return change > 0;
}
private static void OnChangeChanged(DependencyObject element, DependencyPropertyChangedEventArgs args)忍者头像
{
}
private static object CoerceChange(DependencyObject element, object value)
{
decimal newChange = (decimal)value;
NumericUpDown control = (NumericUpDown)element;
decimal coercedNewChange = Decimal.Round(newChange, control.DecimalPlaces);
//If Change is .1 and DecimalPlaces is changed from 1 to 0, we want Change to go to 1, not 0.
//Put another way, Change should always be rounded to DecimalPlaces, but never smaller than the
//previous Change
if (coercedNewChange < newChange)
{
coercedNewChange = smallestForDecimalPlaces(control.DecimalPlaces);
}
return coercedNewChange;
}
private static decimal smallestForDecimalPlaces(int decimalPlaces)
{
if (decimalPlaces < 0)
{
throw new ArgumentException("decimalPlaces");
}
decimal d = 1;
for (int i = 0; i < decimalPlaces; i++)
{
d /= 10;
}
return d;
}
#endregion
#region DecimalPlaces
public int DecimalPlaces
{
get { return (int)GetValue(DecimalPlacesProperty); }
t { SetValue(DecimalPlacesProperty, value); }
}
public static readonly DependencyProperty DecimalPlacesProperty =
年会节目创意简单DependencyProperty.Register(
"DecimalPlaces", typeof(int), typeof(NumericUpDown),
new FrameworkPropertyMetadata(DefaultDecimalPlaces,
new PropertyChangedCallback(OnDecimalPlacesChanged)
), new ValidateValueCallback(ValidateDecimalPlaces)
);
private static void OnDecimalPlacesChanged(DependencyObject element, DependencyPropertyChangedEventArgs args)竹石的诗意
{
NumericUpDown control = (NumericUpDown)element;
control.CoerceValue(ChangeProperty);
control.CoerceValue(MinimumProperty);
control.CoerceValue(MaximumProperty);
control.CoerceValue(ValueProperty);
control.updateValueString();
private static bool ValidateDecimalPlaces(object value)
{
int decimalPlaces = (int)value;
return decimalPlaces >= 0;
}
#endregion
#region ValueString
//public string ValueString
//{
// get
// {
// return (string)GetValue(ValueStringProperty);
// }
//}
//private static readonly DependencyPropertyKey ValueStringPropertyKey =
/
/ DependencyProperty.RegisterAttachedReadOnly("ValueString", typeof(string), typeof(NumericUpDown), new PropertyMetadata()); //public static readonly DependencyProperty ValueStringProperty = ValueStringPropertyKey.DependencyProperty;
public string ValueString
{
get { return (string)GetValue(ValueStringProperty); }
t { SetValue(ValueStringProperty, value); }
}
/// <summary>
/// Identifies the Value dependency property.
/// </summary>
public static readonly DependencyProperty ValueStringProperty =
DependencyProperty.Register("ValueString", typeof(string), typeof(NumericUpDown), new FrameworkPropertyMetadata());
private void updateValueString()
{
m_NumberFormatInfo.NumberDecimalDigits = this.DecimalPlaces;
string newValueString = this.Value.ToString("f", m_NumberFormatInfo);
//this.SetValue(ValueStringPropertyKey, newValueString);
ValueString = newValueString;
}
private NumberFormatInfo m_NumberFormatInfo = new NumberFormatInfo();
#endregion
#endregion
#region Events
/// <summary>
/// Identifies the ValueChanged routed event.
/// </summary>
public static readonly RoutedEvent ValueChangedEvent = EventManager.RegisterRoutedEvent(
"ValueChanged", RoutingStrategy.Bubble,
typeof(RoutedPropertyChangedEventHandler<decimal>), typeof(NumericUpDown));
/// <summary>
/// Occurs when the Value property changes.
/// </summary>
public event RoutedPropertyChangedEventHandler<decimal> ValueChanged
{
add { AddHandler(ValueChangedEvent, value); }
remove { RemoveHandler(ValueChangedEvent, value); }
}
#endregion
#region Commands
public static RoutedCommand IncreaCommand
{
get
{
return m_IncreaCommand;
}
}
public static RoutedCommand DecreaCommand
{
get
{
return m_DecreaCommand;
}
}
private static void InitializeCommands()
{
m_IncreaCommand = new RoutedCommand("IncreaCommand", typeof(NumericUpDown));
CommandManager.RegisterClassCommandBinding(typeof(NumericUpDown), new CommandBinding(m_IncreaCommand, OnIncreaCommand)); CommandManager.RegisterClassInputBinding(typeof(NumericUpDown), new InputBinding(m_IncreaCommand, new KeyGesture(Key.Up)));
m_DecreaCommand = new RoutedCommand("DecreaCommand", typeof(NumericUpDown));
CommandManager.RegisterClassCommandBinding(typeof(NumericUpDown), new CommandBinding(m_DecreaCommand, OnDecreaCommand)); CommandManager.RegisterClassInputBinding(typeof(NumericUpDown), new InputBinding(m_DecreaCommand, new KeyGesture(Key.Down)));
}
private static void OnIncreaCommand(object nder, ExecutedRoutedEventArgs e)
{
NumericUpDown control = nder as NumericUpDown;
if (control != null)
{
control.OnIncrea();
}
}
private static void OnDecreaCommand(object nder, ExecutedRoutedEventArgs e)
{
NumericUpDown control = nder as NumericUpDown;
if (control != null)
{
control.OnDecrea();
}
}
protected virtual void OnIncrea()
{
this.Value += Change;
}
protected virtual void OnDecrea()
{
this.Value -= Change;
}
private static RoutedCommand m_IncreaCommand;
private static RoutedCommand m_DecreaCommand;
小精灵的魔法汤#endregion
#region Automation
protected override AutomationPeer OnCreateAutomationPeer()
{
return new NumericUpDownAutomationPeer(this);
}
#endregion
金针菇功效
/// <summary>
/// This is a class handler for MouLeftButtonDown event.
/// The purpo of this handle is to move input focus to NumericUpDown when ur presd
/
// mou left button on any part of slider that is not focusable.
/// </summary>
/// <param name="nder"></param>
/// <param name="e"></param>
private static void OnMouLeftButtonDown(object nder, MouButtonEventArgs e)
{
NumericUpDown control = (NumericUpDown)nder;
// When someone click on a part in the NumericUpDown and it's not focusable
// NumericUpDown needs to take the focus in order to process keyboard correctly
if (!control.IsKeyboardFocusWithin)
{
e.Handled = control.Focus() || e.Handled;
}
}
private const decimal DefaultMinValue = 0,
DefaultValue = DefaultMinValue,
DefaultMaxValue = 100,
DefaultChange = 1;
private const int DefaultDecimalPlaces = 0;
}
public class NumericUpDownAutomationPeer : FrameworkElementAutomationPeer, IRangeValueProvider
{
public NumericUpDownAutomationPeer(NumericUpDown control)
: ba(control)
{
}