記事のカテゴリー: C#、.NET 9、WPF
自作の添付プロパティを使用するとき、XAMLで指定するBindingModeによって変わる挙動についてまとめてみました。
サンプル
例として、TextBoxのSelectedTextプロパティ(選択範囲の文字を取得、設定するプロパティ)にバインドできるようにする添付ビヘイビアを用意します。OnBindableSelectedTextChangedメソッドでBindingModeを判断して必要な処理だけをする、という内容になっています。実際に動かしてみると、BindingModeがOneWayToSourceの場合は思った通りに動いてくれません。
C#:
- public static class TextBoxExtensions
- {
- // バインドできる SelectedText の添付プロパティ
- public static readonly DependencyProperty BindableSelectedTextProperty = DependencyProperty.RegisterAttached(
- "BindableSelectedText",
- typeof(string),
- typeof(TextBoxExtensions),
- new FrameworkPropertyMetadata(string.Empty, OnBindableSelectedTextChanged));
- public static string GetBindableSelectedText(DependencyObject obj)
- {
- return (string)obj.GetValue(BindableSelectedTextProperty);
- }
- public static void SetBindableSelectedText(DependencyObject obj, string value)
- {
- obj.SetValue(BindableSelectedTextProperty, value);
- }
- private static void OnBindableSelectedTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- if (d is not TextBox textBox)
- {
- return;
- }
- BindingMode mode = BindingOperations.GetBinding(d, BindableSelectedTextProperty).Mode;
- // モードが TwoWay か OneWayToSource なら TextBox のイベントを購読する (ターゲット -> ソース)
- if ((mode == BindingMode.TwoWay) || (mode == BindingMode.OneWayToSource))
- {
- WeakEventManager<TextBox, RoutedEventArgs>.AddHandler(
- textBox, nameof(textBox.SelectionChanged), TextBox_SelectionChanged);
- }
- // モードが OneWayToSource 以外なら TextBox に反映する (ソース -> ターゲット)
- if (mode != BindingMode.OneWayToSource)
- {
- if ((e.NewValue is string text) && (text != textBox.SelectedText))
- {
- textBox.SelectedText = text;
- }
- }
- }
- private static void TextBox_SelectionChanged(object? sender, RoutedEventArgs e)
- {
- if (sender is not TextBox textBox)
- {
- return;
- }
- if (textBox.SelectedText != GetBindableSelectedText(textBox))
- {
- SetBindableSelectedText(textBox, textBox.SelectedText);
- }
- }
- }
XAML:
- <TextBox local:TextBoxExtensions.BindableSelectedText="{Binding SelectedText, Mode=TwoWay}" />
実際の挙動
添付ビヘイビアのOnBindableSelectedTextChangedメソッドをA、TextBox_SelectionChangedメソッドをBとしたとき、BindingModeによって挙動は次のように変わりました。
OneWayToSourceの場合は思った通りの挙動をしません。回避策としては、BindableSelectedText添付プロパティとは別にTextBoxのイベントを購読するための添付プロパティを用意して、そちらからBindableSelectedText添付プロパティの値を変更します(参照先にコードがあります)。
- TwoWay: 思った通りの挙動をする
- Aは呼ばれる
- Bは呼ばれる
- OneWay: 思った通りの挙動をする
- Aは呼ばれる
- Bは呼ばれない(未購読なので当然)
- OneTime: 思った通りの挙動をする
- Aは1回だけ呼ばれる
- Bは呼ばれない(未購読なので当然)
- OneWayToSource: 思った通りの挙動をしない
- Aは呼ばれない
- Bは呼ばれない(未購読なので当然)
0 件のコメント:
コメントを投稿