Инициализированный объект становится нулевым в ViewModel после нажатия кнопки

#c# #wpf #mvvm #castle-windsor

#c# #wpf #mvvm #замок-Виндзор

Вопрос:

Я сталкиваюсь с проблемой, при которой объект, инициализированный с использованием IoC (CastleWindsor) в MainViewModel, становится нулевым, как только я нажимаю кнопку в форме WPF.

У меня есть этот код в MainWindow.xaml.cs

 var iocContainer = WindContainer.WindsorContainer;//This is IoCcontainer and working okay
  iocContainer.Install(new IoCInstaller());

 var mainWindowViewModel = iocContainer.Resolve<MainWindowViewModel>("MainWindowViewModel");
 mainWindowViewModel.Initialize(iocContainer);
 DataContext = mainWindowViewModel;
  

и метод Initialize() в MainWindowViewModel выглядит следующим образом:

 public void Initialize(WindsorContainer windsorContainer)
        {
            Logger.Debug("Initializing main view model");
            iocContainer = windsorContainer;
            myManager = iocContainer.Resolve<IMyManager>("MyManager");
            _dataManager = iocContainer.Resolve<IDataManager>("DataManager");
            _dataManager.Initialize();
         }
  

Все работает нормально, но когда я нажимаю кнопку и выполняю команду в этот момент, iocContainer, _dataManager и MyManager становятся нулевыми. Следующий код также находится в MainWindowViewModel.

 private ICommand _clickCommandForBttnA;
        public ICommand ClickCommandForBttnA
        {
            get
            {
                return _clickCommandForBttnA ?? (_clickCommandForBttnA = new CommandHandlerForBttnA(() => MyActionForBttnA(), _canExecute));
            }
        }

        public void MyActionForBttnA()
        {
            Logger.Debug("Option A is clicked");
            if (_dataManager.SomeData.Equals("myData"))//Here _dataManager is null after clicking button
            {
                BackgroundColorBttnA = Colors.Blue;
                BackgroundColorBttnB = _allButtonInitialColor;
                BackgroundColorBttnC = _allButtonInitialColor;
                BackgroundColorBttnD = _allButtonInitialColor;
                BackgroundColorBttnConfirm = _allButtonInitialColor;
            }
        }
  

Обработчик команды для кнопки

 public class CommandHandlerForBttnA : ICommand
    {
        private Action _action;
        private bool _canExecute;
        public CommandHandlerForBttnA(Action action, bool canExecute)
        {
            _action = action;
            _canExecute = canExecute;
        }

        public bool CanExecute(object parameter)
        {
            return _canExecute;
        }

        public event EventHandler CanExecuteChanged;

        public void Execute(object parameter)
        {
            _action();
        }
    }
  

Любая причина / предложение, почему это происходит?

Комментарии:

1. Либо ClickCommandForBttnA, привязанный к кнопке, относится к неинициализированному экземпляру MainWindowViewModel (другими словами: экземпляр, отличный от того, который вы создаете там во фрагменте кода из вашего MainWindow.xaml.cs); или что-то где-то в вашем коде возвращает _dataManager / MyManager обратно в null . Вам решать, что там происходит. Просмотрите и проанализируйте свой код и используйте отладчик, чтобы увидеть, что происходит в вашей программе (установите точку останова в конструкторе MainViewModel и установите точки останова для любых назначений _dataManager / MyManager в вашем коде …)

2. Я согласен с тем, что сказал @elgonzo. Для проверки вы можете превратить _dataManager в свойство с резервным полем (сохраняя имя) и установив точку останова в установщике. Если это вызвано, ваш стек сообщит вам, где.

3. Вы уверены, что экземпляр view model, выполняющий команду, является тем же экземпляром view model, который был возвращен CastleWindsor? При разрешении из контейнера IoC по имени вы не совсем получаете синглтон, поскольку вы должны иметь возможность получить другой экземпляр указанного типа с другим именем. Пожалуйста, добавьте код, в котором вы выполняете регистрацию MainViewModel.

Ответ №1:

Я не знаком с Castlewinds или библиотекой, но, возможно, мои сомнения направят вас к решению.

Я не знаю и не могу найти в Castlewinds или документации о:

var iocContainer = WindContainer.WindsorContainer;//This is IoCcontainer and working okay

Это ваш код? Может быть, здесь скрыто что-то существенное? У меня есть опасения, что контейнер может быть удален вовремя, когда вы нажимаете кнопку.

Кстати, вы используете DI странным образом. На мой взгляд, вам не следует передавать контейнер для просмотра модели. Модель представления должна иметь конструктор со всеми зависимостями в качестве параметров. Затем, когда вы регистрируете зависимости в контейнере IoC и при следующем вызове Resolve для модели представления, контейнер разрешит объект со всеми зависимостями.