canton7 / Stylet

A very lightweight but powerful ViewModel-First MVVM framework for WPF for .NET Framework and .NET Core, inspired by Caliburn.Micro.
MIT License
990 stars 143 forks source link

Problem handling accessing IWindowManager in ViewModel #112

Closed sbrodieDecor closed 4 years ago

sbrodieDecor commented 4 years ago

VS 2019 Project, MVVM pattern, data model using EntityFrameworkCore, WPF UI, .Net Core 3.1. When I add IWindowManager windowManager in the constructor of my view model, I keep getting error at runtime I am having problems resolving. I am painfully new to WPF/MVVM/#C but 25+ years WinForms VB/VB.Net:

using Stylet;
using LibraryModels.Model;
using System.Collections.ObjectModel;
using System.Linq;
using System.Diagnostics;
using System.Windows.Controls;

namespace Library2020.ViewModel
{
    class LookupsViewModel : Screen
    {

        private readonly IWindowManager windowManager;`

        public LookupsViewModel(IWindowManager windowManager)
        {
            this.windowManager = windowManager;

            this.Initialize();
        }

          private void Initialize()
        {

            // Initialize commands

            //Load data
            this.LoadData();

        }

        public void TopicSelected(object sender, SelectionChangedEventArgs e)
        {

            windowManager.ShowMessageBox("Sample",
                "Sample",
                System.Windows.MessageBoxButton.OK,
                System.Windows.MessageBoxImage.Information);

        }
}
canton7 commented 4 years ago

What is the error you get?

sbrodieDecor commented 4 years ago

Thank you for the response, here is the whole blurb:

System.Reflection.TargetInvocationException
  HResult=0x80131604
  Message=Exception has been thrown by the target of an invocation.
  Source=System.Private.CoreLib
  StackTrace:
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
   at Stylet.ViewManager.InitializeView(UIElement view, Type viewType) in /_/Stylet/ViewManager.cs:line 331
   at Stylet.ViewManager.CreateViewForModel(Object model) in /_/Stylet/ViewManager.cs:line 315
   at Stylet.ViewManager.CreateAndBindViewForModel(Object model) in /_/Stylet/ViewManager.cs:line 224
   at Stylet.ViewManager.CreateAndBindViewForModelIfNecessary(Object model) in /_/Stylet/ViewManager.cs:line 211
   at Stylet.WindowManager.CreateWindow(Object viewModel, Boolean isDialog, IViewAware ownerViewModel) in /_/Stylet/WindowManager.cs:line 163
   at Stylet.WindowManager.ShowWindow(Object viewModel, IViewAware ownerViewModel) in /_/Stylet/WindowManager.cs:line 102
   at Stylet.WindowManager.ShowWindow(Object viewModel) in /_/Stylet/WindowManager.cs:line 92
   at Stylet.BootstrapperBase.DisplayRootView(Object rootViewModel) in /_/Stylet/BootstrapperBase.cs:line 100
   at Stylet.Bootstrapper`1.Launch() in /_/Stylet/Bootstrapper.cs:line 92
   at Stylet.BootstrapperBase.Start(String[] args) in /_/Stylet/BootstrapperBase.cs:line 81
   at Stylet.BootstrapperBase.<Setup>b__9_0(Object o, StartupEventArgs e) in /_/Stylet/BootstrapperBase.cs:line 48
   at System.Windows.Application.OnStartup(StartupEventArgs e)
   at System.Windows.Application.<.ctor>b__1_0(Object unused)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.DispatcherOperation.InvokeImpl()
   at System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state)
   at MS.Internal.CulturePreservingExecutionContext.CallbackWrapper(Object obj)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at MS.Internal.CulturePreservingExecutionContext.Run(CulturePreservingExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Windows.Threading.DispatcherOperation.Invoke()
   at System.Windows.Threading.Dispatcher.ProcessQueue()
   at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
   at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
   at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
   at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
   at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
   at System.Windows.Threading.Dispatcher.Run()
   at System.Windows.Application.RunDispatcher(Object ignore)
   at System.Windows.Application.RunInternal(Window window)
   at System.Windows.Application.Run()
   at Library2020.App.Main()

  This exception was originally thrown at this call stack:
    System.DefaultBinder.BindToMethod(System.Reflection.BindingFlags, System.Reflection.MethodBase[], ref object[], System.Reflection.ParameterModifier[], System.Globalization.CultureInfo, string[], out object)
    MS.Internal.Xaml.Runtime.DynamicMethodRuntime.CreateInstanceWithCtor(System.Type, object[])
    MS.Internal.Xaml.Runtime.DynamicMethodRuntime.CreateInstanceWithCtor(System.Xaml.XamlType, object[])
    MS.Internal.Xaml.Runtime.ClrObjectRuntime.CreateInstance(System.Xaml.XamlType, object[])
    MS.Internal.Xaml.Runtime.PartialTrustTolerantRuntime.CreateInstance(System.Xaml.XamlType, object[])
    System.Xaml.XamlObjectWriter.Logic_CreateAndAssignToParentStart(MS.Internal.Xaml.Context.ObjectWriterContext)
    System.Xaml.XamlObjectWriter.WriteEndObject()
    System.Xaml.XamlWriter.WriteNode(System.Xaml.XamlReader)
    System.Windows.Markup.WpfXamlLoader.TransformNodes(System.Xaml.XamlReader, System.Xaml.XamlObjectWriter, bool, bool, bool, System.Xaml.IXamlLineInfo, System.Xaml.IXamlLineInfoConsumer, MS.Internal.Xaml.Context.XamlContextStack<System.Windows.Markup.WpfXamlFrame>, System.Windows.Markup.IStyleConnector)
    System.Windows.Markup.WpfXamlLoader.Load(System.Xaml.XamlReader, System.Xaml.IXamlObjectWriterFactory, bool, object, System.Xaml.XamlObjectWriterSettings, System.Uri)
    ...
    [Call Stack Truncated]
Inner Exception 1:
NullReferenceException: Object reference not set to an instance of an object.
canton7 commented 4 years ago

Something in your view's InitializeComponent method is throwing a NullReferenceException. Nothing to do with MVVM, Stylet, or IWindowManager I'm afraid.

sbrodieDecor commented 4 years ago

Thanks again. If I remove model constructor: public LookupsViewModel(IWindowManager windowManager)

then, use an empty constructor: public LookupsViewModel()

Comment the following out of the constructor: //this.windowManager = windowManager;

And remove the following out of a method in my ViewModel: //windowManager.ShowMessageBox("Sample", // "Sample", // System.Windows.MessageBoxButton.OK, // System.Windows.MessageBoxImage.Information);

Everything then works. But, I am without WindowManager features I need such as ShowMessageBox and the ability to show modal and non-modal dialogs.

Would appreciate any thoughts.

Shane

canton7 commented 4 years ago

I'd:

  1. Tell VS to break when NRE's are thrown, and see what exactly is throwing it
  2. Just comment out the line windowManager.ShowMessageBox(...), see if that helps
  3. Put a breakpoint in TopicSelected, see whether it's being called from InitializeComponent

Is there any other relevant code which you haven't shown?

canton7 commented 4 years ago

The exception is very definitely being thrown as a result of loading XAML, though

sbrodieDecor commented 4 years ago

Very strange, thank you very much Antony. Will try that and see where it gets me.

Shane

sbrodieDecor commented 4 years ago

Antony, thank you for setting on the right track. I thing I was mixing my methodologies a bit. I removed the following from my XAML:

    <Window.DataContext>
        <ViewModel:LookupsViewModel/>
    </Window.DataContext>

I also removed an attribute from the Window XAML that did not apply in this particular case:

WindowStartupLocation="CenterOwner"

Now everything is working as expected. I just need to do much more reading on IoC, Actions, Commands.

Thank you for your improvement of the Caliburn Micro framework. I stumbled onto your work while searching for a 'working' framework for .Net Core 3.1.

Cheers

Shane

canton7 commented 4 years ago

Glad you solved it! It's odd that <ViewModel:LookupsViewModel/> would throw an NRE, but there you have it I guess.

sbrodieDecor commented 4 years ago

I think it threw that because there was no parameter-less constructor only the LookupsViewModel(IWindowManager windowManager) version

Shane