Skip to main content

DevExpress v24.2 Update — Your Feedback Matters

Our What's New in v24.2 webpage includes product-specific surveys. Your response to our survey questions will help us measure product satisfaction for features released in this major update and help us refine our plans for our next major release.

Take the survey Not interested

Create a Custom Service

  • 4 minutes to read

This topic describes how to create a custom service if predefined services do not suit your requirements.

Note

If you need to implement the logic that should access a UI element in the View Model code, you can use the UIObjectService instead.

Follow the steps below to create a custom service, attach it to a control, and access this service in the View Model:

  1. Create a service interface with methods that should be called from the View Model:

    public interface IGridUpdateService {
        void BeginUpdate();
        void EndUpdate();
    }
    
  2. Create a ServiceBase class descendant that implements your interface:

    using DevExpress.Mvvm.UI;
    // ...
    public class GridUpdateService : ServiceBase, IGridUpdateService {
        public void BeginUpdate() {
            // ...
        }
        public void EndUpdate() {
            // ...
        }
    }
    
  3. Use the AssociatedObject property to access the associated control:

    using DevExpress.Xpf.Grid;
    // ...
    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();
                }
            }));
        }
    }
    

    In this example, the Dispatcher object is used to call methods of the associated control in the UI thread.

  4. Add your service to the Behaviors collection to attach it to a control:

    <Window ...
            xmlns:dxg="http://schemas.devexpress.com/winfx/2008/xaml/grid"
            xmlns:local="clr-namespace:DXGridThreads"
            xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm">
        <Window.DataContext>
            <local:ViewModel />
        </Window.DataContext>
        <dxg:GridControl AutoGenerateColumns="AddNew" 
                         ItemsSource="{Binding Source}">
            <dxmvvm:Interaction.Behaviors>
                <local:GridUpdateService/>
            </dxmvvm:Interaction.Behaviors>
        </dxg:GridControl>
    </Window>
    
  5. Access your service in the View Model:

    using DevExpress.Mvvm;
    // ...
    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();
                }
            }
        }
    }
    
  6. (Optional) Add a DependencyProperty to your service. This property is set at the View level and you can use its value within the service:

    public class GridUpdateService : ServiceBase, IGridUpdateService {
        public static readonly DependencyProperty UpdatedTextProperty =
            DependencyProperty.Register("UpdatedText", typeof(string), typeof(GridUpdateService), new PropertyMetadata("Updated"));
    
        public string UpdatedText {
            get { return (string)GetValue(UpdatedTextProperty); }
            set { SetValue(UpdatedTextProperty, value); }
        }
        // ...
    }
    
    <dxmvvm:Interaction.Behaviors>
        <local:GridUpdateService UpdatedText="Modified"/>
    </dxmvvm:Interaction.Behaviors>
    
  7. (Optional) Override OnAttached and OnDetaching methods to subscribe and unsubscribe from associated control events:

    public class GridUpdateService : ServiceBase, IGridUpdateService {
        GridControl GridControl => AssociatedObject as GridControl;
    
        protected override void OnAttached() {
            base.OnAttached();
            GridControl.CustomColumnDisplayText += GridControl_CustomColumnDisplayText;
        }
    
        private void GridControl_CustomColumnDisplayText(object sender, CustomColumnDisplayTextEventArgs e) {
            // ...
        }
    
        protected override void OnDetaching() {
            GridControl.CustomColumnDisplayText -= GridControl_CustomColumnDisplayText;
            base.OnDetaching();
        }
    }
    

The complete sample project is available in the following GitHub repository:

View Example: Data Grid for WPF - How to Update Data in a Separate Thread

See Also