東方中央幻視台

瞼の裏に弾幕が飛び交う程度の能力 - 永夜抄Normalはそれなりに難しい。

目次

Blog 利用状況

ニュース

自己紹介

関連サイト

投稿カレンダー

  • スクリプトをダウンロード!

ブログパーツ

Adsense

書庫

日記カテゴリ

[WPF]自作NumericUpDownでバインディングが効かない

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);
        }
    }
}

投稿日時 : 2008年7月6日 15:38

コメントを追加

# re: [WPF]自作NumericUpDownでバインディングが効かない 2008/07/06 16:45 えムナウ

BindableAttribute クラス をどうぞ

>手動設定すれば動くんだが、何か規格違反があるのかな?
手動設定って何?

# re: [WPF]自作NumericUpDownでバインディングが効かない 2008/07/06 16:50 えムナウ

>(p as NumericUpDown).PropertyChanged
CAST と as is をもう一度勉強しなおした方がいいですよ。

# re: [WPF]自作NumericUpDownでバインディングが効かない 2008/07/06 17:56 Hirotow

>DataContext = this;
これが原因だったようです。
txtValue.DataContext = this;
にしたらうまくいきました。

タイトル  
名前  
URL
コメント