Начал осваивать как создавать Behavior.
Первый создал такой для привязки свойств только для чтения
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
public class BindingToReadOnlyPropertyBehavior : Behavior<DependencyObject>
{
public PropertyPath Property { get => binding.Path; set => binding.Path = value; }
private readonly Binding binding = new Binding("") { Mode = BindingMode.OneWay };
protected override void OnAttached()
{
binding.Source = AssociatedObject;
BindingOperations.SetBinding(this, SourceProperty, binding);
}
/// <summary>Приватное свойство для получения данных
/// по заданной привязке</summary>
private object Source
{
get { return (object)GetValue(SourceProperty); }
set { SetValue(SourceProperty, value); }
}
// Using a DependencyProperty as the backing store for Source. This enables animation, styling, binding, etc...
private static readonly DependencyProperty SourceProperty =
DependencyProperty.Register("Source", typeof(object), typeof(BindingToReadOnlyPropertyBehavior), new PropertyMetadata(null, propertyChangedCallback));
/// <summary>Метод обратного вызова для передачи полученного значения
/// в целевую привязку</summary>
/// <param name="d"></param>
/// <param name="e"></param>
private static void propertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
=> ((BindingToReadOnlyPropertyBehavior)d).Target = e.NewValue;
/// <summary>Целевой объект куда должно передаваться значение</summary>
public object Target
{
get { return (object)GetValue(TargetProperty); }
set { SetValue(TargetProperty, value); }
}
// Using a DependencyProperty as the backing store for Target. This enables animation, styling, binding, etc...
public static readonly DependencyProperty TargetProperty =
DependencyProperty.Register("Target", typeof(object), typeof(BindingToReadOnlyPropertyBehavior), new PropertyMetadata(null));
}
Использование
1.
2.
3.
4.
5.
public class VMClass : OnPropertyChangedClass
{
public double Width { get => _width; set { _width = value; OnPropertyChanged(); } }
private double _width;
}
1.
2.
3.
4.
5.
6.
7.
8.
9.
<Window.DataContext>
<local:VMClass/>
</Window.DataContext>
<Grid>
<i:Interaction.Behaviors>
<local:BindingToReadOnlyPropertyBehavior Target="{Binding Width, Mode=TwoWay}" Property="ActualWidth" />
</i:Interaction.Behaviors>
<TextBlock Text="{Binding Width}"/>
</Grid>
Всё работает. Но создавал "в лоб", первый раз - поэтому может не учёл какие нюансы.
Те кто имеет опыт создания прокомментируйте - Какие есть замечания: что следует исправить, убрать, добавить?
Особенные сомнения в отношении приватного свойства Source. Можно ли обойтись без него - получать значение сразу по привязке?