Search code examples
c#wpfmvvmmvvm-light

How to write a nested class that binds with a ViewModel class?


I have the page which should have some view models. I have decided to try Nested classes. I use MVVM Light for my project.

I have written the VM, that inherits from ViewModelBase and the nested class.

I have used the example of the Microsoft docs (nested example):

    public class UserMainViewModel : ViewModelBase
    {
        public UserMainViewModel()
        {

        }

        private Page _mainContent;

        public Page MainContent
        {
            get => _mainContent;
            private set => Set(ref _mainContent, value);
        }   

        public UserVM UserManager
        {
            get
            {
                return new UserVM(new UserMainViewModel());
            }
        }

        public class UserVM
        {
            private UserMainViewModel _viewModel;

            public UserVM(UserMainViewModel viewModel)
            {
                _viewModel = viewModel;
            }

            private RelayCommand _getInfoPageCommand;
            public RelayCommand GetInfoPageCommand
            {
                get
                {
                    return _getInfoPageCommand
                        ?? (_getInfoPageCommand = new RelayCommand(() =>
                        {
                            _viewModel.MainContent = new GetUserInfo();
                        }));
                }
            }
        }
    }

My ViewLocator:

     public ViewModelLocator()
        {
            ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
            SimpleIoc.Default.Register<UserMainViewModel>();
        }

    public UserMainViewModel UserMainContext => ServiceLocator.Current.GetInstance<UserMainViewModel>();

View context

    DataContext="{Binding UserMainContext, Source={StaticResource Locator}}"

Element View for example

    <Button Content="Profile" Command="{Binding UserManager.GetInfoPageCommand}"/>

But it doesn't work when I click the button. Nothing happens.

Am I having the right idea by using nested classes? Could anyone tell me why it doesn't work?


Solution

  • You should create one UserVM and pass the current instance of UserMainViewModel to it instead of creating a new one each time the property is called:

    private UserVM _userVm;
    public UserVM UserManager
    {
        get
        {
            if (_userVm == null)
                _userVm = new UserVM(this);
            return _userVm;
        }
    }