Skip to main content
All docs
V24.1

DevExpress v24.1 Update — Your Feedback Matters

Our What's New in v24.1 webpage includes product-specific surveys. Your response to our survey questions will help us measure product satisfaction for features released in this major update and help us refine our plans for our next major release.

Take the survey Not interested

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 AtachableServiceProperty =
            DependencyProperty.Register(nameof(AtachableService), typeof(ServiceBase),
            typeof(AttachServiceBehavior), new PropertyMetadata(null, OnAtachableServiceChanged));
    
        static void OnAtachableServiceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
            (e.OldValue as ServiceBase)?.Detach();
            ((AttachServiceBehavior)d).AttachService();
        }
        public ServiceBase AtachableService {
            get => (ServiceBase)GetValue(AtachableServiceProperty);
            set => SetValue(AtachableServiceProperty, value);
        }
    
        protected override void OnAttached() {
            base.OnAttached();
            AttachService();
        }
        protected override void OnDetaching() {
            base.OnDetaching();
            AtachableService?.Detach();
        }
    
        void AttachService() {
            if(AtachableService == null || AssociatedObject == null)
                return;
            if(AtachableService.IsAttached)
                AtachableService.Detach();
            AtachableService.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.