Quantcast
Channel: Developer Express Inc.
Viewing all articles
Browse latest Browse all 2437

DevExpress MVVM Framework. Behaviors.

$
0
0

OTHER RELATED ARTICLES:

  1. Getting Started with DevExpress MVVM Framework. Commands and View Models.
  2. DevExpress MVVM Framework. Introduction to Services, DXMessageBoxService and DialogService.
  3. DevExpress MVVM Framework. Interaction of ViewModels. IDocumentManagerService.
  4. DevExpress MVVM Framework. Introduction to POCO ViewModels.
  5. DevExpress MVVM Framework. Interaction of ViewModels. Messenger.
  6. DevExpress MVVM Framework. Using Scaffolding Wizards for building Views.
  7. DevExpress MVVM Framework. Data validation. Implementing IDataErrorInfo.
  8. DevExpress MVVM Framework. Using DataAnnotation attributes and DevExpress Fluent API.
  9. THIS POST: DevExpress MVVM Framework. Behaviors.

All the features described in this post are available in both the free and non-free versions of the DevExpress MVVM framework (included in the DevExpress WPF component suite).

The Behavior mechanism extends the capabilities of visual controls. You can implement missing functionality with a custom Behavior and begin using it with ease.

Example. You have a WPF or Silverlight form containing some components. You wish to focus a specific control on startup. This isn’t particularly easy, because we need to handle the Loaded event of the form and call the Focus method for the necessary control.

<Windowx:Class="WpfApplication1.MainWindow" ...>
<Grid>
<StackPanelOrientation="Horizontal"VerticalAlignment="Top">
<TextBoxText="Enter your name: "/>
<TextBoxName="name"Width="200"/>
</StackPanel>
</Grid>
</Window>
publicpartialclass MainWindow : Window {
public MainWindow() {
        InitializeComponent();
        Loaded += OnLoaded;
    }
void OnLoaded(object sender, RoutedEventArgs e) {
        name.Focus();
    }
}

To adhere to the MVVM pattern and keep the code clear, you can implement a custom Behavior to perform the same.

publicclass FocusBehavior : Behavior<FrameworkElement> {
protectedoverridevoid OnAttached() {
base.OnAttached();
        AssociatedObject.Focus();
    }
}

There is no longer a need to handle the Loaded event - everything will now work fine without it. The code is simple and can used in any place in your application.

<StackPanelOrientation="Horizontal"VerticalAlignment="Top">
<TextBoxText="Enter your name: "/>
<TextBoxName="name"Width="200">
<dxmvvm:Interaction.Behaviors>
<local:FocusBehavior/>
</dxmvvm:Interaction.Behaviors>
</TextBox>
</StackPanel>

You can further extend the Behavior by adding dependency properties, events, and other customization options.

 

How do Behaviors work?

The DevExpress.Mvvm.UI.Interactivity.Interaction class implements a Behaviors attached property. This property is read-only and contains a collection of Behaviors. The elements in this collection descend from the AttachableObjectBase class. This class has an AssociatedObject property, 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. When the Behavior is destroyed, an OnDetaching virtual method is called where you can unsubscribe from events.

protectedoverridevoid OnAttached() {
base.OnAttached();
    AssociatedObject.Loaded += OnAssociatedObjectLoaded;
}
protectedoverridevoid OnDetaching() {
    AssociatedObject.Loaded -= OnAssociatedObjectLoaded;
base.OnDetaching();
}

 

Predefined set of Behaviors in DevExpress MVVM Framework

  • Probably, the most useful Behavior is EventToCommand. Here is a simple example of how to use it.
<UserControlx:Class="EventToCommandSample.MainView"
xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm" ...>
<dxmvvm:Interaction.Behaviors>
<dxmvvm:EventToCommandEventName="Loaded"Command="{Binding InitCommand}"/>
</dxmvvm:Interaction.Behaviors>
</UserControl>
 
  • FocusBehavior allows specify a control to be focused on start up.
<StackPanelOrientation="Horizontal"Margin="10">
<TextBlockText="This control is focused on startup: "VerticalAlignment="Center"/>
<TextBoxText="Focus is here">
<dxmvvm:Interaction.Behaviors>
<dxmvvm:FocusBehavior/>
</dxmvvm:Interaction.Behaviors>
</TextBox>
</StackPanel>

FocusBehavior can also be triggered when a specific property is changed or an event occurs.

<StackPanelOrientation="Horizontal"Margin="10">
<TextBlockText="This control is focused on button click: "VerticalAlignment="Center"/>
<TextBoxText="Click the bottom button">
<dxmvvm:Interaction.Behaviors>
<dxmvvm:FocusBehaviorSourceName="button"EventName="Click"/>
</dxmvvm:Interaction.Behaviors>
</TextBox>
<Buttonx:Name="button"Content="Click to focus the TextBox"/>
</StackPanel>
 
  • ValidationErrorsHostBehavior tracks validation errors with ease. For instance:
[POCOViewModel(ImplementIDataErrorInfo=true)]
publicclass MainViewModel {
    [Required]
publicvirtualstring FirstName { get; set; }
    [Required]
publicvirtualstring LastName { get; set; }
}
<UserControl.Resources>
<dxmvvm:BooleanNegationConverterx:Key="BooleanNegationConverter"/>
</UserControl.Resources>
<dxmvvm:Interaction.Behaviors>
<dxmvvm:ValidationErrorsHostBehaviorx:Name="validationErrorsHostBehavior"/>
</dxmvvm:Interaction.Behaviors>
<Grid>
<StackPanelOrientation="Vertical" ...>
<StackPanelOrientation="Horizontal">
<TextBlockText="First Name: " .../>
<TextBoxText="{Binding FirstName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, 
                            NotifyOnValidationError=True, ValidatesOnDataErrors=True}" .../>
</StackPanel>
<StackPanelOrientation="Horizontal">
<TextBlockText="Last Name: " .../>
<TextBoxText="{Binding LastName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, 
                            NotifyOnValidationError=True, ValidatesOnDataErrors=True}" .../>
</StackPanel>
<ButtonContent="Save" ... IsEnabled="{Binding ElementName=validationErrorsHostBehavior, 
                                               Path=HasErrors, Converter={StaticResource BooleanNegationConverter}}"/>
</StackPanel>
</Grid>

The Save button will be disabled until the end-user fills the required fields.

  • ConfirmationBehavior. It’s often required to show a confirmation box before performing an action. For instance, an end-user changes something in a document and closes it. While closing, we need to show the message: “Are you sure to close the document?” For this purposes, there is ConfirmationBehavior.
<ButtonContent="Save"HorizontalAlignment="Center"VerticalAlignment="Center">
<dxmvvm:Interaction.Behaviors>
<dxmvvm:ConfirmationBehaviorCommand="{Binding SaveCommand}"
MessageText="Do you want to save?"MessageButton="YesNo"/>
</dxmvvm:Interaction.Behaviors>
</Button>

To accomplish the same task without ConfirmationBehavior, it’s necessary to use IMessageBoxService from the SaveCommand (I described this approach in a previous post).

  • DependencyPropertyBehavior. Sometimes, the properties that a control provides aren’t dependency properties. For instance, the TextBox.SelectedText property. This means the WPF binding system can’t target this property. In such cases, can use a DependencyPropertyBehavior.
<TextBoxWidth="200"Text="Select some text in this box">
<dxmvvm:Interaction.Behaviors>
<dxmvvm:DependencyPropertyBehaviorPropertyName="SelectedText"
EventName="SelectionChanged"Binding="{Binding SelectedText, Mode=TwoWay}"/>
</dxmvvm:Interaction.Behaviors>
</TextBox>

The above code binds the TextBox.SelectedText property to the SelectedText property of the underlying ViewModel. Notice that the DependencyPropertyBehavior.EventName property is set. When performing updates on the bound properties the behavior will processes the specified event.


Viewing all articles
Browse latest Browse all 2437

Latest Images

Trending Articles



Latest Images