📜 ⬆️ ⬇️

WPF: Using Attached Property and Behavior

Perhaps any WPF developer knows about the Attached Property mechanism, but many have not even heard of Behavior. Although these mechanisms have similar functionalities, they still have completely different meaning, and it is very important to properly distinguish and use them.

Let's remember what these mechanisms are:

Attached Property . This is Dependency Property, which is not declared in the class of the object for which it will be used, but behaves as if it were part of it.
')
It is declared in a separate class, has getter and setter in the form of static methods. You can add a handler to the PropertyChanged event.

public static class UiConfigurator { public static readonly DependencyProperty CustomValueProperty = DependencyProperty.RegisterAttached( "CustomValue", typeof(bool), typeof(UiConfigurator), new PropertyMetadata(false)); public static void SetCustomValue(DependencyObject element, bool value) { element.SetValue(CustomValueProperty, value); } public static bool GetCustomValue(DependencyObject element) { return (bool)element.GetValue(CustomValueProperty); } } 

It is used in the same way as the usual Dependency Property, only it is necessary to specify the class in which it is defined.

 <Button testApp:UiConfigurator.CustomValue="True"/> 

Thanks to the PropertyChanged handler, very often using this mechanism, they try to add some functionality to the UI element. For example, we want to remember the location and size of the window between the launches of the application. Make an Attached Property SaveBounds and add a PropertyChanged handler. If set to true, then execute the code to restore / save the position of the window. Is it correct? Not. Let's see how Microsoft uses this mechanism in its hands. Excellent examples are Grid.Column and DockPanel.Dock. All these properties do not affect the functionality of the object, but simply add some information so that other members of the display tree can interact with it more correctly. The object itself knows nothing about it and should not know it. It follows that in and of itself, using the PropertyChanged event for Attached Property is already a reason to think: am I doing everything correctly? It is necessary only in very rare cases. For example, in this way we can memorize the history of changes in this property, so that if necessary we can conduct a deeper analysis and interact more intellectually. But this is one of the tasks in the category of “once in a lifetime”.

Since Attached Property does not affect the state of the object, then several such properties should not conflict, which means we can hang them on it as long as possible. For example, the same Grid.Column and DockPanel.Dock (although this is somewhat illogical) can be easily combined. Here you have the second clue whether you are using this mechanism correctly: if you can present code that can be written in the target object or anywhere else and that will conflict with your property, you did something wrong.

Behavior . WPF has an abstract template class Behavior. Having made an heir, we can attach it to an object in the display tree. In this class, there are OnAttached and OnDetaching methods that will be called when appropriate.
Below is an example of CloseBehavior, which you can attach to any button and thus make it a button to close the application.

 public class CloseBehavior : Behavior<Button> { protected override void OnAttached() { AssociatedObject.Click += OnClick; } protected override void OnDetaching() { AssociatedObject.Click -= OnClick; } private void OnClick(object sender, RoutedEventArgs e) { Application.Current.Shutdown(); } } 

Added by the following code:

 <Button Content="Close"> <i:Interaction.Behaviors> <testApp:CloseBehavior/> </i:Interaction.Behaviors> </Button> 

Here Behavior already in difference from Attached Property serves for adding of functionality of UI to elements. Any Dependency Property can be added to it, and since it is part of the display tree, Binding works fine here. Since for WPF it is customary to use MVVM, and he, in turn, assumes a minimum of code in the View body, Behavior is just what we need here. These few functional blocks that can not be performed using the standard Binding, can be removed and used everywhere combined with each other.

Not all Behavior objects must be compatible with each other. For example, we can't combine CloseButtonBehavior and HelpButtonBehavior. And this, of course, is normal.

Source: https://habr.com/ru/post/254887/


All Articles