The "You cannot use a disposed object" message is straightforward to explain. Your code is trying to use an IDisposable object and the object has already been disposed. That indicates a lifetime management issue in your app. In the CalendarPageViewModel
code you posted I would guess you're getting this when trying to use GraphServiceClient
as that is a disposable object. That means your client is being disposed while your view model is still using it. Now why would it be doing that.
Since you're using DI let's jump to how you're defining the registrations. I notice in your startup that you're defining everything using AddSingleton. That is almost always the wrong answer. A singleton is created once and reused for the life of the application. The only time you should be using this scope is for static data that will not change for the life of the application or in the rare case where you can only have a single instance of the type. Given your registrations I would say that only InteractiveBrowserCredential
should be a singleton. Singletons should only rely on other singletons and hence their lifetime is the life of the app.
In all other cases you should be using AddScoped or AddTransient. This allows new instances to be created as needed. Furthermore the instances will get cleaned up as well. This is critical for types that rely on other types that should be cleaned up. A full discussion of which lifetime to use is covered here. Note that the focus isn't on how many instances you want to create but the lifetime of instances. For example the fact that you only create 1 instance of the main window isn't relevant to the lifetime. What is relevant is that once the window is done being used it should be cleaned up.
So, I would recommend you switch all your registrations to either AddScoped
or AddTransient
except for the static data like your credential options. I suspect this will solve your exception. Note that if you're explicitly disposing of an object that is returned from the service container then you should remove that. For a Windows app you likely have 1 scope so the difference between AddScoped
and AddTransient
are not as critical. Ultimately you are just asking the question "should I get a new instance for each call (transient) or the same instance for each call in the same scope (scoped)?"