none
TemplateBindingExpressionをサポートしていないプロパティを、サポート可能にする方法 RRS feed

  • 質問

  • お世話になっております。


    WPFじゃない言語で作られたコントロール(DLL)を使った
    カスタムコントロールを作成中です。
    ※TextBoxのようなコントロールです。

    このコントロールのTextプロパティをバインドさせるため、
    Generic.xamlにて
    <tt:CustomTextBox Text="{TemplateBinding Value }"/>
    のようにしましたが、
    「プロパティ 'Text' は、型 'TemplateBindingExpression' の値をサポートしません。    」
    というエラーでコンパイルが出来ません。


    WPF製じゃないためTemplateBindingExpressionをサポートしていないのが原因だと思うのですが
    このような場合、どうにかTemplateBindingExpressionをサポートしてバインドを実現させる方法はないでしょうか?


    よろしくお願いします。
    2012年10月12日 9:35

回答

  • >> WPF製じゃないためTemplateBindingExpressionをサポートしていないのが原因だと思うのですが
    >> このような場合、どうにかTemplateBindingExpressionをサポートしてバインドを実現させる方法はないでしょうか?

    無理です。Bindingできるのは対象プロパティがDependencyPropertyで定義されている場合だけなので、WinForm用コントロールのプロパティ相手では不可能です。
    (WPFコントロールでもCLRプロパティの場合Bindingできません)

    で、そういう場合はコントロールにコードビハインドを仕込むんですが、カスタムコントロールだとイベントハンドラを直に書けないとか色々面倒なのでユーザーコントロールで実装します。

    <UserControl x:Class="WpfApplication2.CustomTextBox"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms">
        <WindowsFormsHost>
            <wf:TextBox x:Name="textBox" TextChanged="textBox_TextChanged" />
        </WindowsFormsHost>
    </UserControl>
    


        public partial class CustomTextBox : UserControl
        {
            public static readonly DependencyProperty TextProperty 
                = DependencyProperty.Register("Text", 
                                              typeof(string), 
                                              typeof(CustomTextBox), 
                                              new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnTextChanged));
    
            public static void OnTextChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
            {
                CustomTextBox control = (CustomTextBox)sender;
                System.Windows.Forms.TextBox textBox = control.FindName("textBox") as System.Windows.Forms.TextBox;
                if (textBox != null)
                {
                    textBox.Text = (string)e.NewValue;
                }
            }
    
            public string Text
            {
                get { return (string)GetValue(TextProperty); }
                set { SetValue(TextProperty, value); }
            }
            
            public CustomTextBox()
            {
                InitializeComponent();
            }
    
            private void textBox_TextChanged(object sender, EventArgs e)
            {
                if (this.Text != textBox.Text)
                {
                    this.Text = textBox.Text;
                }
            }
        }

    ポイントは
    (1)DependencyPropertyを登録する際にPropertyChangedCallbackを定義し、プロパティ変更時に値をWinFormコントロールへ格納する。
    (2)BindsTwoWayByDefaultを設定して双方向Bindingをデフォにしておく(これは無くても良いですがやっといた方が便利です)。
    (3)WinFormコントロール側の対象プロパティの変更イベントハンドラを作って、変更値を書き戻すようにする。

    ※カスタムコントロールでもできなくはないですが、Load/Unload時にイベントハンドラを登録/削除する、Load時にそのときの値をコントロールに書く処理を別途書かないといけないなど色々煩雑になります。

    以上、参考になれば幸いです。

    • 回答としてマーク sumi_sumi 2012年10月15日 1:20
    2012年10月12日 12:06

すべての返信

  • >> WPF製じゃないためTemplateBindingExpressionをサポートしていないのが原因だと思うのですが
    >> このような場合、どうにかTemplateBindingExpressionをサポートしてバインドを実現させる方法はないでしょうか?

    無理です。Bindingできるのは対象プロパティがDependencyPropertyで定義されている場合だけなので、WinForm用コントロールのプロパティ相手では不可能です。
    (WPFコントロールでもCLRプロパティの場合Bindingできません)

    で、そういう場合はコントロールにコードビハインドを仕込むんですが、カスタムコントロールだとイベントハンドラを直に書けないとか色々面倒なのでユーザーコントロールで実装します。

    <UserControl x:Class="WpfApplication2.CustomTextBox"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms">
        <WindowsFormsHost>
            <wf:TextBox x:Name="textBox" TextChanged="textBox_TextChanged" />
        </WindowsFormsHost>
    </UserControl>
    


        public partial class CustomTextBox : UserControl
        {
            public static readonly DependencyProperty TextProperty 
                = DependencyProperty.Register("Text", 
                                              typeof(string), 
                                              typeof(CustomTextBox), 
                                              new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnTextChanged));
    
            public static void OnTextChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
            {
                CustomTextBox control = (CustomTextBox)sender;
                System.Windows.Forms.TextBox textBox = control.FindName("textBox") as System.Windows.Forms.TextBox;
                if (textBox != null)
                {
                    textBox.Text = (string)e.NewValue;
                }
            }
    
            public string Text
            {
                get { return (string)GetValue(TextProperty); }
                set { SetValue(TextProperty, value); }
            }
            
            public CustomTextBox()
            {
                InitializeComponent();
            }
    
            private void textBox_TextChanged(object sender, EventArgs e)
            {
                if (this.Text != textBox.Text)
                {
                    this.Text = textBox.Text;
                }
            }
        }

    ポイントは
    (1)DependencyPropertyを登録する際にPropertyChangedCallbackを定義し、プロパティ変更時に値をWinFormコントロールへ格納する。
    (2)BindsTwoWayByDefaultを設定して双方向Bindingをデフォにしておく(これは無くても良いですがやっといた方が便利です)。
    (3)WinFormコントロール側の対象プロパティの変更イベントハンドラを作って、変更値を書き戻すようにする。

    ※カスタムコントロールでもできなくはないですが、Load/Unload時にイベントハンドラを登録/削除する、Load時にそのときの値をコントロールに書く処理を別途書かないといけないなど色々煩雑になります。

    以上、参考になれば幸いです。

    • 回答としてマーク sumi_sumi 2012年10月15日 1:20
    2012年10月12日 12:06
  • みっとさま

    いつも有難う御座います。

    親切で分かりやすい説明有難う御座います。

    大事なポイントと、サンプルのおかげで大変理解しやすかったです。

    まだまだ理解が甘いので今から勉強します。

    本当に助かりました。有難う御座いました。
    2012年10月15日 1:23