Search code examples
c#wpfmvvmprism

How can I can method from another viewmodel


I have HomeViewModel and MainViewModel. I want to call method TestEvent of MainViewModel in HomeViewModel but I don't know how to do it? Anyone can help me. I tried to use Prism but I alway get error when I pass IEventAggregator parameter in MainViewModel.

Exception thrown: 'System.MissingMethodException' in System.Xaml.dll
Exception thrown: 'System.Xaml.XamlObjectWriterException' in System.Xaml.dll
Exception thrown: 'System.NullReferenceException' in System.Private.CoreLib.dll
Object reference not set to an instance of an object.

This is my MainViewModel

using Learning.Core;
using Learning.EventRegister;
using Learning.MVVM.Model;
using Prism.Events;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;

namespace Learning.MVVM.ViewModel
{
    public class MainViewModel: ObservableObject
    {
        public RelayCommand HomeViewConmmand { get; set; }
        public RelayCommand DiscoveryViewConmmand { get; set; }
        public RelayCommand TestCommand { get; set; }

        public HomeViewModel HomeVM { get; set; }
        public DiscoveryViewModel DiscoveryVM { get; set; }
        public RoomViewModel RoomVM { get; set; }

        private object _currentView;
        private object _rightView;

        IEventAggregator _eventAggregator;

        public object CurrentView
        {
            get { return _currentView; }
            set { 
                _currentView = value;
                OnPropertyChanged();
            }
        }

        public object RightView
        {
            get { return _rightView; }
            set
            {
                _rightView = value;
                OnPropertyChanged();
            }
        }

        public MainViewModel(IEventAggregator ea) {
            HomeVM = new HomeViewModel();
            DiscoveryVM = new DiscoveryViewModel();
            RoomVM = new RoomViewModel();
            CurrentView = HomeVM;
            RightView = RoomVM;

            HomeViewConmmand = new RelayCommand(o =>
            {
                CurrentView = HomeVM;
            });

            DiscoveryViewConmmand = new RelayCommand(o =>
            {
                CurrentView = DiscoveryVM;
            });

            TestCommand = new RelayCommand(o =>
            {
                MessageBox.Show("Clicked");
            });
        }

        public void TestEvent(string message)
        {
            MessageBox.Show(message);
        }
    }
}

This is my HomeViewModel. If I pass IEventAggregator in contructor of HomeViewModel, I also get error like MainViewModel

using Learning.Core;
using Learning.EventRegister;
using Learning.MVVM.Model;
using Prism.Events;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;

namespace Learning.MVVM.ViewModel
{
    public class HomeViewModel
    {
        // Data
        public List<Room> rooms { get; }

        // Command
        private RelayCommand openRoomCommand;

        //IEventAggregator 
        IEventAggregator _eventAggregator;

        public RelayCommand NotifyCommand { get; set; }

        public HomeViewModel()
        {
            openRoomCommand = new RelayCommand(o =>
            {
                Room cur_room = (Room)o;
                cur_room.IsActive = true;
            });

            rooms = new List<Room>();
            Room room1 = new Room
            {
                Name = "1",
                IsActive = false,
            };
            Room room2 = new Room
            {
                Name = "2",
                IsActive = false,
            };
            Room room3 = new Room
            {
                Name = "3",
                IsActive = false,
            };
            Room room4 = new Room
            {
                Name = "4",
                IsActive = false,
            };

            rooms.Add(room1);
            rooms.Add(room2);
            rooms.Add(room3);
            rooms.Add(room4);
        }

        public void SendEvent()
        {
            //_eventAggregator.GetEvent<CommandSendEvent>().Publish("Something happening");
        }

        public RelayCommand OpenRoomCommand { get => openRoomCommand; }
    }
}


Solution

  • You have 3 ways to execute a method belonging to a viewmodel from another view model:

    1. you declare this method static in MainViewModel and so its easy to call this method from any viewmodel (Not the best, but that exists...)

    2. you add an instance of MainViewModel in HomeViewModel constructor by Dependecy injection, you find lot of tutorial to understant the injection.

    3. You could use Messaging between ViewModel (IEventAggregator), same than point 2, you have to inject an instance of IEventAggragor in the homeViewModel and MainViewModel constructors, then after MainViewModel have to subscribe to an event which will execute the method you want, this event will be activated by HomeViewModel