Skip to main content
All docs
V25.1
  • Dependency Injection

    • 3 minutes to read

    Bind a View to a View Model

    To bind a view to a view model, create a MarkupExtension that resolves the correct ViewModel type:

    public class DISource : MarkupExtension {
        public static Func<Type, object, string, object> Resolver { get; set; }
    
        public Type Type { get; set; }
        public object Key { get; set; }
        public string Name { get; set; }
    
        public override object ProvideValue(IServiceProvider serviceProvider) => Resolver?.Invoke(Type, Key, Name);
    }
    

    Register the resolver at the application startup:

    protected override void OnStartup(StartupEventArgs e) {
        base.OnStartup(e);
        DISource.Resolver = Resolve;
    }
    object Resolve(Type type, object key, string name) {
        if(type == null)
            return null;
        if(key != null)
            return Container.ResolveKeyed(key, type);
        if(name != null)
            return Container.ResolveNamed(name, type);
        return Container.Resolve(type);
    }
    

    Specify the DataContext in XAML in the following manner:

    DataContext="{common:DISource Type=common:MainViewModel}"
    

    Examples

    Use POCO View Models with Dependency Injection

    To use a POCO View Model in a Dependency Injection container, utilize the ViewModelSource.GetPOCOType method to register the POCO type generated at runtime:

    container.RegisterType(typeof(IMainViewModel),
                        ViewModelSource.GetPOCOType(typeof(MainViewModel)));
    

    View Example

    Use Services with Dependency Injection

    The recommended technique to use DevExpress services with Dependency Injection varies depending on whether the service has an associated visual element.

    • If the service is attached to a specific visual element, add the following custom AttachServiceBehavior to register it:

      public class AttachServiceBehavior : Behavior<DependencyObject> {
          public static readonly DependencyProperty AttachableServiceProperty =
              DependencyProperty.Register(nameof(AttachableService), typeof(ServiceBase),
              typeof(AttachServiceBehavior), new PropertyMetadata(null, OnAttachableServiceChanged));
      
          static void OnAttachableServiceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
              (e.OldValue as ServiceBase)?.Detach();
              ((AttachServiceBehavior)d).AttachService();
          }
          public ServiceBase AttachableService {
              get => (ServiceBase)GetValue(AttachableServiceProperty);
              set => SetValue(AttachableServiceProperty, value);
          }
      
          protected override void OnAttached() {
              base.OnAttached();
              AttachService();
          }
          protected override void OnDetaching() {
              base.OnDetaching();
              AttachableService?.Detach();
          }
      
          void AttachService() {
              if(AttachableService == null || AssociatedObject == null)
                  return;
              if(AttachableService.IsAttached)
                  AttachableService.Detach();
              AttachableService.Attach(AssociatedObject);
          }
      }
      

      Add a public property that corresponds to the service to the View Model:

      public class MainViewModel {
          public INavigationService NavigationService { get; }
      
          public MainViewModel(INavigationService navigationService) =>
              NavigationService = navigationService;
      }
      

      Use the AttachServiceBehavior to attach the service to a visual element:

      <dxwui:NavigationFrame>
          <dxmvvm:Interaction.Behaviors>
              <common:AttachServiceBehavior Service="{Binding NavigationService}"/>
          </dxmvvm:Interaction.Behaviors>
      </dxwui:NavigationFrame>
      

      View Example

    • If the service does not need to be attached to a specific visual element (such as Message Box Services), you can use the following technique instead:

      1. Register the service in the Dependency Injection container:

        container.RegisterSingleton(typeof(IMessageBoxService), typeof(DXMessageBoxService));
        
      2. Specify the corresponding View Model property:

        public class MainViewModel {
            IMessageBoxService messageBoxService;
            public MainViewModel(IMessageBoxService dialogService) {
                this.messageBoxService = messageBoxService;
            }
        }
        

    Tip

    If you configure the service to work with a specific View, Dependency Injection is not recommended. Use the technique described in the following section instead: Implement Services in Your Application.