Back to Devexpress

Services in Generated View Models

wpf-17447-mvvm-framework-services-services-in-generated-view-models.md

latest6.5 KB
Original Source

Services in Generated View Models

  • Apr 08, 2024
  • 3 minutes to read

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

Services in POCO

xaml
<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>
csharp
using DevExpress.Mvvm.POCO;
...
public class ViewModel {
    public IMessageBoxService MessageBoxService { get { return this.GetService<IMessageBoxService>(); } }
}
vb
Imports DevExpress.Mvvm.POCO
...
Public Class ViewModel
    Public ReadOnly Property MessageBoxService() As IMessageBoxService
        Get
            Return Me.GetService(Of IMessageBoxService)()
        End Get
    End Property
End Class

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.

xaml
<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>
csharp
public class ViewModel {
        [ServiceProperty(Key = "service1")]
        public virtual IMessageBoxService MessageBoxService1 { get { return null; } }
        [ServiceProperty(Key = "service2")]
        public virtual IMessageBoxService MessageBoxService2 { get { return null; } }
    }
vb
Public Class ViewModel
    <ServiceProperty(Key := "service1")> _
    Public Overridable ReadOnly Property MessageBoxService1 As IMessageBoxService
        Get
            Return Nothing
        End Get
    End Property
    <ServiceProperty(Key := "service2")> _
    Public Overridable ReadOnly Property MessageBoxService2 As IMessageBoxService
        Get
            Return Nothing
        End Get
    End Property
End Class

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.

csharp
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"); } }
}
vb
Imports DevExpress.Mvvm.POCO
...
Public Class ViewModel
    Public ReadOnly Property MessageBoxService1() As IMessageBoxService
        Get
            Return Me.GetService(Of IMessageBoxService)("service1")
        End Get
    End Property
    Public ReadOnly Property MessageBoxService2() As IMessageBoxService
        Get
            Return Me.GetService(Of IMessageBoxService)("service1")
        End Get
    End Property
End Class

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.

csharp
[GenerateViewModel(ImplementISupportServices = true)]
public partial class ServicesViewModel {
    IMessageBoxService MessageBoxService => ServiceContainer.GetService<IMessageBoxService>(ServiceSearchMode.PreferParents);
    [GenerateCommand]
    void ShowMessage() => MessageBoxService.ShowMessage("Message");
}
csharp
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);
}