Search code examples
c#wpfmvvmmodal-dialogautofac

Is there a way to pass existing view model as a data context to recently opened dialog window, when using autofac?


I have a project, using Autofac. There is created a BootStrapper file that is called on application run:

public class BootStrapper
    {
        public IContainer BootStrap()
        {
            var builder = new ContainerBuilder();

            builder.RegisterType<FileDataServices>()
              .As<IFileDataServices>().SingleInstance();

            builder.RegisterType<ScrapDataServices>()
              .As<IScrapDataServices>().SingleInstance();

            builder.RegisterType<MessageDialogService>()
              .As<IMessageDialogService>().SingleInstance();

            builder.RegisterType<MainWindow>().AsSelf();
            builder.RegisterType<MainViewModel>().AsSelf();

            return builder.Build();
        }
    }

And the class is called by App.xaml.cs`

public partial class App : Application
    {
        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);
            var bootStrapper = new BootStrapper();
            var container = bootStrapper.BootStrap();
            var mainWindow = container.Resolve<MainWindow>();
            mainWindow.Show();
        }
    }

When the MainWindow is created, constructor creates instance of MainViewModel, that I want to use later:

public partial class MainWindow : Window
    {
        private MainViewModel _viewModel;
        public MainWindow(MainViewModel viewModel)
        {
            InitializeComponent();
            _viewModel = viewModel;
            DataContext = _viewModel;
        }
    }

In MainViewModel there is created UpdateWindow via simple MessageDialogService:

var result = _messageDialogService.ShowUpdateWindow();

And the MessageDialogService by itself:

public class MessageDialogService : IMessageDialogService
    {
        public MessageDialogResult ShowUpdateWindow()
        {
            return new UpdateWindow()
            {
                WindowStartupLocation = WindowStartupLocation.CenterOwner,
                Owner = App.Current.MainWindow
            }.ShowDialog().GetValueOrDefault()
              ? MessageDialogResult.Update //if DialogResult = true;
              : MessageDialogResult.Cancel; //if DialogResult = false;
        }
    }

On creation I need to pass the existing instance of MainViewModel to the UpdateWindow as a DataContext. And I do not know how. Right now I only managed to create a new instance of the MainViewModel on creation of UpdateWindow, but it is not my goal, because in this window I am having controls that I need them to have binded with ViewModel created by MainWindow. Is there any way or approach to do that?

Currently I have only this:

public partial class UpdateWindow : Window
    {
        public UpdateWindow()
        {
            var bootStrapper = new BootStrapper();
            var container = bootStrapper.BootStrap();
            var vm = container.Resolve<MainViewModel>();
            InitializeComponent();
            DataContext = vm;
        }

        private void ButtonUpdate_Click(object sender, RoutedEventArgs e)
        {
            DialogResult = true;
        }
    }

Solution

  • You need to make sure you're resolving MainWindowViewModel.

    Register MainwindowViewModel as a singleton using

    builder.RegisterType<MainViewModel>().AsSelf().SingleInstance();
    

    Then add a variable of type MainWindowViewModel to the ctor of wherever you want to use it.

    Resolve that - UpdateWindow is it?

    The container should provide the same instance of MainWindowViewmodel it gave you for mainwindow.