How to: Create a Custom Behavior

  • 7 minutes to read

The DevExpress.Mvvm.UI.Interactivity.Interaction class implements a Behaviors attached property. This property is read-only and contains a collection of Behaviors.

<TextBox Text="Text">
    <dxmvvm:Interaction.Behaviors>
        <local:ValidationBehavior />
        <!--Other Behaviors-->
    </dxmvvm:Interaction.Behaviors>
</TextBox>

All Behaviors descend from the Behavior<T> class. The T parameter sets the type of the associated control. For instance, the Behavior below can only be applied to the TextBox control (or for a control descended from the TextBox control).

public class ValidationBehavior : Behavior<TextBox> {
    ...
}

The Behavior<T> class provides the AssociatedObject property that is set internally once a Behavior is added to the Behaviors collection. After the AssociatedObject property is set, the OnAttached virtual method is invoked. You can override this method to subscribe to AssociatedObject events and initialize properties. When the Behavior is destroyed, an OnDetaching virtual method is called, where you can unsubscribe from events.

Also, behaviors may provide properties and events that you can set or bind in Xaml.

public class ValidationBehavior : Behavior<TextBox> {
    public static readonly DependencyProperty ValidForegroundProperty =
        DependencyProperty.Register("ValidForeground", typeof(Brush), typeof(ValidationBehavior),
        new PropertyMetadata(new SolidColorBrush(Colors.Black), (d, e) => ((ValidationBehavior)d).Update()));
    public static readonly DependencyProperty InvalidForegroundProperty =
        DependencyProperty.Register("InvalidForeground", typeof(Brush), typeof(ValidationBehavior), 
        new PropertyMetadata(new SolidColorBrush(Colors.Red), (d,e) => ((ValidationBehavior)d).Update()));
    public static readonly DependencyProperty InvalidValueProperty =
        DependencyProperty.Register("InvalidValue", typeof(string), typeof(ValidationBehavior),
        new PropertyMetadata(string.Empty, (d, e) => ((ValidationBehavior)d).Update()));
    public Brush ValidForeground {
        get { return (Brush)GetValue(ValidForegroundProperty); }
        set { SetValue(ValidForegroundProperty, value); }
    }
    public Brush InvalidForeground {
        get { return (Brush)GetValue(InvalidForegroundProperty); }
        set { SetValue(InvalidForegroundProperty, value); }
    }
    public string InvalidValue {
        get { return (string)GetValue(InvalidValueProperty); }
        set { SetValue(InvalidValueProperty, value); }
    }

    protected override void OnAttached() {
        base.OnAttached();
        AssociatedObject.TextChanged += OnAssociatedObjectTextChanged;
        Update();
    }
    protected override void OnDetaching() {
        AssociatedObject.TextChanged -= OnAssociatedObjectTextChanged;
        base.OnDetaching();
    }
    void OnAssociatedObjectTextChanged(object sender, TextChangedEventArgs e) {
        Update();
    }
    void Update() {
        if(AssociatedObject == null) return;
        if(AssociatedObject.Text == InvalidValue)
            AssociatedObject.Foreground = InvalidForeground;
        else AssociatedObject.Foreground = ValidForeground;
    }
}
<TextBox Text="Text">
    <dxmvvm:Interaction.Behaviors>
        <Behaviors:ValidationBehavior ValidForeground="{Binding ValidBrush}"
                                      InvalidForeground="{Binding InvalidBrush}"
                                      InvalidValue="{Binding InvalidValue}"/>
    </dxmvvm:Interaction.Behaviors>
</TextBox>

Example

The below example demonstrates a more complex example of how to create a custom Behavior.

Imports DevExpress.Mvvm.DataAnnotations
Imports System.Windows.Media

Namespace Example.ViewModel
    <POCOViewModel> _
    Public Class MainViewModel
        Public Overridable Property InvalidValue() As String
        Public Overridable Property ValidBrush() As Brush
        Public Overridable Property InvalidBrush() As Brush

        Public Sub SetRedValidBrush()
            ValidBrush = New SolidColorBrush(Colors.Red)
        End Sub
        Public Sub SetBlueValidBrush()
            ValidBrush = New SolidColorBrush(Colors.Blue)
        End Sub
        Public Sub SetBlackValidBrush()
            ValidBrush = New SolidColorBrush(Colors.Black)
        End Sub

        Public Sub SetRedInvalidBrush()
            InvalidBrush = New SolidColorBrush(Colors.Red)
        End Sub
        Public Sub SetBlueInvalidBrush()
            InvalidBrush = New SolidColorBrush(Colors.Blue)
        End Sub
        Public Sub SetBlackInvalidBrush()
            InvalidBrush = New SolidColorBrush(Colors.Black)
        End Sub

        Public Sub New()
            InvalidValue = "Error"
            SetBlackValidBrush()
            SetRedInvalidBrush()
        End Sub
    End Class
End Namespace