Skip to main content

Services in Generated View Models

  • 3 minutes to read

Runtime-generated POCO View Models and View Models Generated at Compile Time can work with Services.

Services in POCO

<UserControl x:Class="ViewModelBaseSample.View" 
             xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm" 
             xmlns:dx="http://schemas.devexpress.com/winfx/2008/xaml/core"
             xmlns:ViewModels="clr-namespace:ViewModelBaseSample.ViewModels"
             DataContext="{dxmvvm:ViewModelSource ViewModel:ViewModel}"  ...> 
    <dxmvvm:Interaction.Behaviors>
        <dx:DXMessageBoxService/>
    </dxmvvm:Interaction.Behaviors>
    ...
</UserControl>
using DevExpress.Mvvm.POCO;
...
public class ViewModel {
    public IMessageBoxService MessageBoxService { get { return this.GetService<IMessageBoxService>(); } }
}

To control the generation of service properties, use the ServiceProperty attribute or Fluent API. For instance, you can define several services of the same type and access a specific service by its name.

<UserControl x:Class="ViewModelBaseSample.View" 
             xmlns:dxmvvm="http://schemas.devexpress.com/winfx/2008/xaml/mvvm" 
             xmlns:dx="http://schemas.devexpress.com/winfx/2008/xaml/core"
             xmlns:ViewModels="clr-namespace:ViewModelBaseSample.ViewModels"
             DataContext="{dxmvvm:ViewModelSource ViewModel:ViewModel}"  ...> 
    <dxmvvm:Interaction.Behaviors>
        <dx:DXMessageBoxService x:Name="service1"/>
        <dx:DXMessageBoxService x:Name="service2"/>
    </dxmvvm:Interaction.Behaviors>
    ...
</UserControl>
public class ViewModel {
        [ServiceProperty(Key = "service1")]
        public virtual IMessageBoxService MessageBoxService1 { get { return null; } }
        [ServiceProperty(Key = "service2")]
        public virtual IMessageBoxService MessageBoxService2 { get { return null; } }
    }

Alternatively, you can manually define properties to access services. To do so, define a non-virtual property and use one of POCOViewModelExtensionsGetService extension methods as shown in the code snippet below.

using DevExpress.Mvvm.POCO;
...
public class ViewModel {
    public IMessageBoxService MessageBoxService1 { get { return this.GetService<IMessageBoxService>("service1"); } }
    public IMessageBoxService MessageBoxService2 { get { return this.GetService<IMessageBoxService>("service2"); } }
}

View Models can be related to each other with the parent-child relationship. This is achieved with the ISupportParentViewModel interface that is automatically implemented when you create a POCO object with the ViewModelSource class. You can pass the main View Model to the child using the ISupportParentViewModel.ParentViewModel property. This allows the child View Model to access Services that are registered for the main View Model. Please review the following topic for more information about this mechanism: ViewModel relationships (ISupportParentViewModel).

Here is an example that demonstrates the use of services when POCO View Models are related to each other with the parent-child relationship: DXMessageBoxService.

Services in View Models Generated at Compile Time

To use Services in View Models Generated at Compile Time, set the ImplementISupportServices property of the GenerateViewModel attribute to true.

[GenerateViewModel(ImplementISupportServices = true)]
public partial class ServicesViewModel {
    IMessageBoxService MessageBoxService => ServiceContainer.GetService<IMessageBoxService>(ServiceSearchMode.PreferParents);
    [GenerateCommand]
    void ShowMessage() => MessageBoxService.ShowMessage("Message");
}
partial class ServicesViewModel : INotifyPropertyChanged, ISupportServices {
    public event PropertyChangedEventHandler? PropertyChanged;
    IServiceContainer? serviceContainer;
    protected IServiceContainer ServiceContainer { get => serviceContainer ??= new ServiceContainer(this); }
    IServiceContainer ISupportServices.ServiceContainer { get => ServiceContainer; }
    protected T? GetService<T>() where T : class => ServiceContainer.GetService<T>();
    protected T GetRequiredService<T>() where T : class => ServiceContainer.GetRequiredService<T>();

    protected void RaisePropertyChanged(PropertyChangedEventArgs e) => PropertyChanged?.Invoke(this, e);

    DelegateCommand? showMessageCommand;
    public DelegateCommand ShowMessageCommand => showMessageCommand ??= new DelegateCommand(ShowMessage, null, true);
}