C#のWPFでDatePickerにIsReadOnlyを追加する

カレンダーを表示させて日付を入力出来るDatePickerコントロール。

でもこれIsReadOnlyプロパティを持ってない。

 

DatePickerを継承したクラスを作成してIsReadOnlyプロパティを持たせてみる。

ソース

    public partial class DatePickerEx : DatePicker
    {
        public static readonly DependencyProperty IsReadOnlyProperty =
            DependencyProperty.Register("IsReadOnly",
                typeof(bool),
                typeof(DatePickerEx),
                new FrameworkPropertyMetadata(false, (d, e) => {(d as DatePickerEx).OnIsReadOnlyPropertyChanged(e); }));
        public bool IsReadOnly
        {
            get { return (bool)GetValue(IsReadOnlyProperty); }
            set { SetValue(IsReadOnlyProperty, value); }
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            OnIsReadOnlyPropertyChangedSub(IsReadOnly);
        }

        private void OnIsReadOnlyPropertyChanged(DependencyPropertyChangedEventArgs e)
        {
            OnIsReadOnlyPropertyChangedSub((bool)e.NewValue);
        }

        private void OnIsReadOnlyPropertyChangedSub(bool isReadOnly)
        {
            if (null != this.Template)
            {
                var textBox = this.Template.FindName("PART_TextBox", this) as DatePickerTextBox;
                if (null != textBox)
                {
                    textBox.IsReadOnly = isReadOnly;
                }

                var button = this.Template.FindName("PART_Button", this) as Button;
                if (null != button)
                {
                    button.Visibility = isReadOnly ? Visibility.Collapsed : Visibility.Visible;
                }
            }
        }
    }

IsReadOnlyプロパティを作る (3~12行目)

データバインディングに対応する為、依存関係プロパティとしてIsReadOnlyを作成する。

DependencyProperty.Registerメソッドを使って

 ”IsReadOnly”という名前の

 bool型のプロパティを

 DatePickerExクラスへ追加し

 初期値をfalseで,値が変わった時にOnIsReadOnlyPropertyChangedメソッドを呼び出す。

 

WPFでコントロールを自作する その1」を参照

 

 

テンプレートが適用されたらReadOnlyを処理する (14~18行目)

OnApplyTemplateメソッドをオーバーライドして、ReadOnlyを制御する。

IsReadOnlyプロパティが変更された時も同様の処理をする為、OnIsReadOnlyPropertyChangedSubメソッドを作成していて、それを呼び出している。

 

 

IsReadOnlyプロパティが変更されたらReadOnlyを処理する (20~23行目)

OnIsReadOnlyPropertyChangedメソッドが呼ばれたら、ReadOnlyを制御する。

テンプレートが適用された時も同様の処理をする為、

OnIsReadOnlyPropertyChangedSubメソッドを作成していて、それを呼び出している。

 

 

ReadOnlyを処理する (25~41行目)

DatePickerはテキスト入力部分がDatePickerTextBoxというコントロールで作られていて、PART_TextBoxという名前が付いている。

また、カレンダーを出すボタンにはPART_Buttonという名前が付けられているので、この名前でコントロールを取ってきて、ReadOnlyを制御する。

 

ちなみに、DatePickerの定義を参照してみると[TemplatePart]属性があって、どのような名前や型が使われているのか知る事が出来る。  

namespace System.Windows.Controls
{
    //
    // 概要:
    //     ユーザーが日付を選択できるコントロールを表します。
    [TemplatePart(Name = "PART_TextBox", Type = typeof(DatePickerTextBox))]
    [TemplatePart(Name = "PART_Button", Type = typeof(Button))]
    [TemplatePart(Name = "PART_Popup", Type = typeof(Popup))]
    [TemplatePart(Name = "PART_Root", Type = typeof(Grid))]
    public class DatePicker : Control
    {
           :
           :
           :