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:
Create a service interface with methods that should be called from the View Model:
Create a ServiceBase class descendant that implements your interface:
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.
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>
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(); } } } }
(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>
(Optional) Override
OnAttached
andOnDetaching
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: