ButtonとTextBoxで構成されたNumericUpDownを作ったんだが、
どうもデータバインドが効いてないっぽい。
手動設定すれば動くんだが、何か規格違反があるのかな?
<UserControl x:Class="WasaWasa.Controls.NumericUpDown"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ws="clr-namespace:WasaWasa.Converters;assembly=WasaWasa.Converters"
MinWidth="50" MinHeight="20">
<UserControl.Resources>
<ws:IsDecimalRule x:Key="isDecimalRule"/>
<ws:DecimalRangeValidationRule x:Key="decimalRangeValidationRule"/>
</UserControl.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="16"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="16"/>
</Grid.ColumnDefinitions>
<Button Name="btnDown" Grid.Column="0" Margin="0">-</Button>
<TextBox Name="txtValue" Grid.Column="1" TextAlignment="Right" Margin="0">
<Binding x:Name="binding" Mode="TwoWay" Path="Value" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<StaticResource ResourceKey="isDecimalRule" />
<StaticResource ResourceKey="decimalRangeValidationRule" />
</Binding.ValidationRules>
</Binding>
</TextBox>
<Button Name="btnUp" Grid.Column="2" Margin="0">+</Button>
</Grid>
</UserControl>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;
using WasaWasa.Converters;
namespace WasaWasa.Controls
{
/// <summary>
/// NumericUpDown.xaml の相互作用ロジック
/// </summary>
//TODO:MinValueとMaxValueとStepValueを依存プロパティ化する
public partial class NumericUpDown : UserControl, INotifyPropertyChanged
{
#region INotifyPropertyChanged メンバ
public event PropertyChangedEventHandler PropertyChanged;
#endregion
private static ValidationRule integerRule = new DecimalInInt32ValidationRule();
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("Value", typeof(decimal), typeof(NumericUpDown),
new PropertyMetadata(new PropertyChangedCallback(delegate(DependencyObject p, DependencyPropertyChangedEventArgs e)
{
if ((p as NumericUpDown).PropertyChanged != null)
(p as NumericUpDown).PropertyChanged((p as NumericUpDown), new PropertyChangedEventArgs("Value"));
})));
public static readonly DependencyProperty IsIntegerOnlyProperty =
DependencyProperty.Register("IsIntegerOnly", typeof(bool), typeof(NumericUpDown),
new PropertyMetadata(new PropertyChangedCallback(delegate(DependencyObject p, DependencyPropertyChangedEventArgs e)
{
NumericUpDown ctrl = p as NumericUpDown;
bool value = (bool)e.NewValue;
bool oldValue = (bool)e.OldValue;
if (value)
{
if (oldValue)
return;
ctrl.AddValidationRule(NumericUpDown.integerRule);
}
else
{
if (!oldValue)
return;
ctrl.RemoveValidationRule(NumericUpDown.integerRule);
}
})));
public static readonly DependencyProperty MinValueProperty =
DependencyProperty.Register("MinValue", typeof(decimal), typeof(NumericUpDown),
new PropertyMetadata(decimal.MinValue, new PropertyChangedCallback(delegate(DependencyObject p, DependencyPropertyChangedEventArgs e)
{
((p as NumericUpDown).FindResource("decimalRangeValidationRule") as DecimalRangeValidationRule).MinValue = (decimal)e.NewValue;
if ((p as NumericUpDown).Value < (decimal)e.NewValue)
(p as NumericUpDown).Value = (decimal)e.NewValue;
})));
public static readonly DependencyProperty MaxValueProperty =
DependencyProperty.Register("MaxValue", typeof(decimal), typeof(NumericUpDown),
new PropertyMetadata(decimal.MaxValue, new PropertyChangedCallback(delegate(DependencyObject p, DependencyPropertyChangedEventArgs e)
{
((p as NumericUpDown).FindResource("decimalRangeValidationRule") as DecimalRangeValidationRule).MaxValue = (decimal)e.NewValue;
if ((p as NumericUpDown).Value > (decimal)e.NewValue)
(p as NumericUpDown).Value = (decimal)e.NewValue;
})));
public static readonly DependencyProperty StepValueProperty =
DependencyProperty.Register("StepValue", typeof(decimal), typeof(NumericUpDown),
new PropertyMetadata(1M), new ValidateValueCallback(delegate(object o)
{
return (decimal)o > 0;
}));
public bool IsIntegerOnly
{
get { return (bool)GetValue(IsIntegerOnlyProperty); }
set
{
SetValue(IsIntegerOnlyProperty, value);
PropertyChanged(this, new PropertyChangedEventArgs(ValueProperty.Name));
}
}
public decimal Value
{
get { return (decimal)GetValue(ValueProperty); }
set
{
if (value < MinValue)
value = MinValue;
if (MaxValue < MaxValue)
value = MinValue;
SetValue(ValueProperty, value);
}
}
public decimal MinValue
{
get { return (decimal)GetValue(MinValueProperty); }
set
{
SetValue(MinValueProperty, value);
}
}
public decimal MaxValue
{
get { return (decimal)GetValue(MaxValueProperty); }
set
{
SetValue(MinValueProperty, value);
}
}
public decimal StepValue
{
get { return (decimal)GetValue(StepValueProperty); }
set
{
SetValue(StepValueProperty, value);
}
}
public NumericUpDown()
{
InitializeComponent();
DataContext = this;
btnUp.Click += new RoutedEventHandler(delegate(object sender, RoutedEventArgs e)
{
Value += StepValue;
});
btnDown.Click += new RoutedEventHandler(delegate(object sender, RoutedEventArgs e)
{
Value -= StepValue;
});
}
public void AddValidationRule(ValidationRule rule)
{
binding.ValidationRules.Add(rule);
}
public void RemoveValidationRule(ValidationRule rule)
{
binding.ValidationRules.Remove(rule);
}
}
}