Skip to main content
All docs
V24.1

Use the MVVM Framework to Avoid Code-Behind

  • 5 minutes to read

This topic describes the most common scenarios where the DevExpress MVVM Framework can help you avoid code-behind and maintain a clean MVVM pattern in your application.

Process UI Element Events in the View Model

You can specify a View Model command that is executed when a UI element raises an event. To do this, create a command in your View Model and implement one of the techniques below.

Use the EventToCommand Behavior

Assign an EventToCommand behavior to the UI element. In this behavior, specify the EventName / Event property and bind the created command to the Command property:

<UserControl>
    <!-- ... -->
    <dxmvvm:Interaction.Behaviors>
        <dxmvvm:EventToCommand EventName="Loaded" Command="{Binding InitializeCommand}"/>
    </dxmvvm:Interaction.Behaviors>
</UserControl>
public class ViewModel : ViewModelBase {
    [Command]
    public void Initialize() {
        // ...
    }
}

View Example: How to Use EventToCommand

Use the CommandParameter property to pass a parameter to the command. The PassEventArgsToCommand and EventArgsConverter properties allow you to pass event arguments to the command.

Use Built-in Command Properties

The DevExpress Data Grid contains command properties that correspond to events. This is one of the ways how we extend MVVM support. If the UI element contains a command property (for example, the TableView.RowDoubleClickCommand for the TableView.RowDoubleClick event), bind this property to your View Model command:

<dxg:GridControl.View>
    <dxg:TableView RowDoubleClickCommand="{Binding RowDoubleClickCommand}"/>
</dxg:GridControl.View>
public class ViewModel : ViewModelBase {
    // ...
    [Command]
    public void RowDoubleClick(RowClickArgs args) {
        DXMessageBox.Show("Row double click: " + ((DataItem)args.Item).Name);
    }
}

View Example: Handle Row Double-clicks in an MVVM Application

Refer to the following help topic for the complete command list: Data Grid Command API.

Handle Events Outside of the View Model

You can maintain an MVVM pattern even if you cannot process UI element events in the View Model. For example, you may need to access properties of event arguments (e.Handled, e.Cancel, and so on).

Create a Behavior class and attach it to the UI element. Override the OnAttached method and subscribe to the event. Unsubscribe from the event in the overloaded OnDetaching method:

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

View Example: Create a Custom Attached Behavior

Refer to the following help topic for more information: Behaviors.

Handle Events in the View

The DXEvent extension allows you to create a simple event handler in the View:

<dxg:TableView ...
               CompleteRecordDragDrop="{DXEvent Handler='@args.Handled = true'}"/> 

Refer to the following help topic for more information on the DXEvent syntax: Language Specification.

Call UI Element Methods from the View Model

  1. Implement a Service that calls the UI element’s methods:

    public interface IGridUpdateService {
        void BeginUpdate();
        void EndUpdate();
    }
    
    public class GridUpdateService : ServiceBase, IGridUpdateService {
        GridControl GridControl => AssociatedObject as GridControl;
    
        public void BeginUpdate() {
            Dispatcher.Invoke(new Action(() => {
                if (GridControl != null) {
                    GridControl.BeginDataUpdate();
                }
            }));
        }
    
        public void EndUpdate() {
            Dispatcher.Invoke(new Action(() => {
                if (GridControl != null) {
                    GridControl.EndDataUpdate();
                }
            }));
        }
    }
    
  2. Attach this service to the UI element:

    <dxg:GridControl>
        <!-- ... -->
        <dxmvvm:Interaction.Behaviors>
            <local:GridUpdateService />
        </dxmvvm:Interaction.Behaviors>
    </dxg:GridControl>
    
  3. In the View Model, obtain the service and call the service’s methods:

    public class ViewModel : ViewModelBase {
        //...
        public IGridUpdateService GridUpdateService { get { return GetService<IGridUpdateService>(); } }
    
        void TimerCallback(object state) {
            lock(SyncRoot) {
                if(GridUpdateService != null) {
                    GridUpdateService.BeginUpdate();
                    foreach(DataItem item in Source) {
                        item.Value = random.Next(100);
                    }
                    GridUpdateService.EndUpdate();
                }
            }
        }
    }
    

View Example: Update Data in a Separate Thread

Refer to the following help topic for more information: Create a Custom Service.

See Also