Search code examples
c#wpfmvvmlight

WPF MVVM - mvvm light doesn't send and register values


AssemblyHelper.cs

namespace TEST.Model.BaseClass
{
    public static class AssemblyHelper
    {
        public static IEnumerable<Type> GetLoadableTypes(Assembly assembly)
        {
            if (assembly == null) throw new ArgumentNullException(nameof(assembly));

            try
            {
                return assembly.GetTypes();
            }
            catch (ReflectionTypeLoadException e)
            {
                return e.Types.Where(t => t != null);
            }
        }

        public static Type GetTypeByClassName(Assembly assembly, string className)
        {
            if (assembly == null) throw new ArgumentNullException(nameof(assembly));

            return AssemblyHelper.GetLoadableTypes(assembly).Where(a => a.Name == className).FirstOrDefault();
        }
    }
}

MainWindowsViewModel.cs

namespace TEST.ViewModel
{
    public class MainWindowViewModel : BaseViewModel
    {
        private DatabaseEntity db;

        private ReadOnlyCollection<LeftNavigation> _LeftNavigation;
        private DispatcherTimer Timer;

                public Assembly Assembly
        {
            get
            {
                return Assembly.GetExecutingAssembly();
            }
        }

        public ReadOnlyCollection<LeftNavigation> LeftNavigation
        {
            get
            {
                if (_LeftNavigation == null)
                {
                    Messenger.Default.Register<string>(this, CheckMessage);
                    //MethodInfo methodInfo = AssemblyHelper.GetTypeByClassName(Assembly, "AddValueViewModel").GetMethod("CallMessenger");
                    //methodInfo.Invoke(AssemblyHelper.GetConstructorByClassName(Assembly, "AddValueViewModel"), null);

                    db = new DatabaseEntity();
                    IQueryable<LeftNavigation> ln = new LeftNavigation(db).GetLeftNavigation();
                    foreach (var o in ln)
                    {
                        o.Command = new BaseCommand(() => OpenOneTab(AssemblyHelper.GetTypeByClassName(Assembly, o.Reference)));
                    }
                    _LeftNavigation = new ReadOnlyCollection<LeftNavigation>(ln.ToList());
                }
                return _LeftNavigation;
            }
        }

        public MainWindowViewModel() {}

        private void CheckMessage(string msg)
        {
            if (msg.Contains(","))
            {
                List<string> msgList = new List<string>(msg.Split(new string[] { "," }, StringSplitOptions.None));
                //Type typeHelper = null;
                //string typeNameHelper = "";

                foreach (var m in msgList)
                {
                    Type type = AssemblyHelper.GetTypeByClassName(Assembly, m);
                    if (type != null)
                    {
                        base.OpenOneTab(AssemblyHelper.GetTypeByClassName(Assembly, m));
                        //typeHelper = type;
                        //typeNameHelper = m;
                        continue;
                    }

                    int value;
                    if (int.TryParse(m, out value))
                    {
                        //MethodInfo methodInfo = typeHelper.GetMethod("CallMessenger");
                        //if (methodInfo != null)
                        //{
                        //    methodInfo.Invoke(AssemblyHelper.GetConstructorByClassName(Assembly, typeNameHelper), null);
                            Messenger.Default.Send(value);
                        //}
                    }
                }
            } else
            {
                base.OpenOneTab(AssemblyHelper.GetTypeByClassName(Assembly, msg));
            }
        }
    }
}

At MainWindowVireModel.cs in CheckMessage I'm retrieving "AddValueViewModel,2" from CategoriesViewModel.cs and here sending and register works fine. First I open a new tab and then want to send a new message with "2" to AddValueViewModel.cs

AddValueViewModel.cs

namespace TEST.ViewModel.Tab
{
    public class AddValueViewModel : JedenViewModel<CategoryValue>
    {
        public AddValueViewModel()
             : base()
        {
            base.DisplayName = "Add Value";
            item = new CategoryValue();
            Messenger.Default.Register<string>(this, CheckMessage2);
        }

        private int _CategoryId;
        public int CategoryId
        {
            get
            {
                return _CategoryId;
            }
            set
            {
                if (_CategoryId != value)
                {
                    _CategoryId = value;
                    OnPropertyChanged(() => _CategoryId);
                }
            }
        }

        private void CheckMessage2(string msg)
        {
            if (msg.Contains(","))
            {
                int value;
                if (int.TryParse(msg, out value)) { CategoryId = value; };
            }
        }

        public override void Save()
        {
            item.CategoryId = CategoryId;
            db.KategoriaWartosc.Add(item);
            db.SaveChanges();
        }

        //public void CallMessenger()
        //{
        //    Messenger.Default.Register<string>(this, CheckMessage2);
        //}
        #endregion Helpers
    }
}

Open tab method

public void OpenOneTab(Type tabType)
{
    dynamic workspace = Workspaces.FirstOrDefault(vm => vm.GetType() == tabType);
    if (workspace == null)
    {
        workspace = Activator.CreateInstance(tabType);
        Workspaces.Add(workspace);
    }
    SetActiveWorkspace(workspace);
}

I'm navigating to AddValueViewModel by button with Command from CategoriesViewModel. When AddValueViewModel tab is opening first time - CheckMessage2 dosent run, but when I close tab and go to AddValueViewModel second time the CheckMessage2 receives the same value as at MainWindowsViewModel - "AddValueViewModel,2"

I tried to use 'Messenger.Default.Unregister(this, CheckMessage); ' and 'Messenger.Reset();' right before sending the value at MainWindowsViewModel but it dosent work

At examples is commented code that was to give me sure that I first call 'register' and then 'send' (invoke method by reflection)

MVVM light is something new to me

Questions: I dont know why at first time I cant receives values at CheckMessage2. At second time if I receives something the data I send is not the data that I expected.


Solution

  • The type of message expected by the view model is of type string

    Messenger.Default.Register<string>
    

    While the type of the message sent is of the type int. So, the view model cannot receive the message.