wpf-17447-mvvm-framework-services-services-in-generated-view-models.md
Runtime-generated POCO View Models and View Models Generated at Compile Time can work with Services.
<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>(); } }
}
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.
<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; } }
}
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 POCOViewModelExtensions ‘ GetService 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"); } }
}
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.
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);
}