How to handle dynamic instance (Window) with SimpleIoc Container












0















i'm new to MVVM and IoC. I use ViewModel-first approach for this project. My project assemblies organization look like this:




View (has reference to ViewModel)
ViewModel (has reference to Model)
Model




Worked fine at the beginning, until i need a Login view. Login run on program startup. On successful login MainWindow will be shown and Login has to close itself. The reverse can be done with LogoutCommand from MainWindow.



The main obstacle i'm facing is instantiating a View (Window) for a given ViewModel type, while ViewModel has no knowledge of its View. On search for the answer, i've found:




  1. Mediator/Messenger pattern. Which i found very convenient, i used this pattern for showing dialog MessageBox. But only for that purpose, i'm not comfortable using this pattern for handling object instantiation.

  2. Dependency Injection. A new concept to me. But i can see a real benefit of decoupling service constructor knowledge out of consumer class. Hence i tried MVVM-Light SimpleIoc for starter by injecting View instance to ViewModel constructor as interface and proceed to register them on ViewModelLocator


SimpleIoc.Default.Register<IMainWindowView, MainWindow>();  
SimpleIoc.Default.Register<ILoginView, Login>();
SimpleIoc.Default.Register<LoginVM>();
SimpleIoc.Default.Register<MainWindowVM>();


On successful login, the MainWindow shown and Login closed. But when i logout of MainWindow to show Login again, i encountered InvalidOperationException Cannot set Visibility or call Show, ShowDialog, or WindowInteropHelper.EnsureHandle after a Window has closed. So i thought i need to "clean up" the instance created by SimpleIoC by unregistering it on Window Closing event.



public class ViewModelBaseEx : ViewModelBase
{
protected SimpleIoc Ioc
{
get { return SimpleIoc.Default; }
}

protected virtual void Unregister<T>() where T : class
{
Cleanup();

if (Ioc.IsRegistered<T>())
{
// Attempt to remove instance
Ioc.Unregister<T>();

// If i still need to show this window again,
// shouldn't i need to have this instance available? (not sure)
Ioc.Register<T>();
}
}
}


Alas, the above workaround didn't work and now i don't know what to do.




  1. What are the merit/demerit of my approach?

  2. How to handle dynamic instance with IoC container?




UPDATE



Register after unregister seems necessary as the type cannot be found if left only unregistered. As for the problem, it seems i also need to unregister the View type too. So i add a bit of code-behind in the View (Window)



private void MainWindow_Closed(object sender, EventArgs e)
{
SimpleIoc.Default.Unregister<IMainWindowView>();
SimpleIoc.Default.Register<IMainWindowView, MainWindow>();
}


Works fine so far, is this approach acceptable?










share|improve this question





























    0















    i'm new to MVVM and IoC. I use ViewModel-first approach for this project. My project assemblies organization look like this:




    View (has reference to ViewModel)
    ViewModel (has reference to Model)
    Model




    Worked fine at the beginning, until i need a Login view. Login run on program startup. On successful login MainWindow will be shown and Login has to close itself. The reverse can be done with LogoutCommand from MainWindow.



    The main obstacle i'm facing is instantiating a View (Window) for a given ViewModel type, while ViewModel has no knowledge of its View. On search for the answer, i've found:




    1. Mediator/Messenger pattern. Which i found very convenient, i used this pattern for showing dialog MessageBox. But only for that purpose, i'm not comfortable using this pattern for handling object instantiation.

    2. Dependency Injection. A new concept to me. But i can see a real benefit of decoupling service constructor knowledge out of consumer class. Hence i tried MVVM-Light SimpleIoc for starter by injecting View instance to ViewModel constructor as interface and proceed to register them on ViewModelLocator


    SimpleIoc.Default.Register<IMainWindowView, MainWindow>();  
    SimpleIoc.Default.Register<ILoginView, Login>();
    SimpleIoc.Default.Register<LoginVM>();
    SimpleIoc.Default.Register<MainWindowVM>();


    On successful login, the MainWindow shown and Login closed. But when i logout of MainWindow to show Login again, i encountered InvalidOperationException Cannot set Visibility or call Show, ShowDialog, or WindowInteropHelper.EnsureHandle after a Window has closed. So i thought i need to "clean up" the instance created by SimpleIoC by unregistering it on Window Closing event.



    public class ViewModelBaseEx : ViewModelBase
    {
    protected SimpleIoc Ioc
    {
    get { return SimpleIoc.Default; }
    }

    protected virtual void Unregister<T>() where T : class
    {
    Cleanup();

    if (Ioc.IsRegistered<T>())
    {
    // Attempt to remove instance
    Ioc.Unregister<T>();

    // If i still need to show this window again,
    // shouldn't i need to have this instance available? (not sure)
    Ioc.Register<T>();
    }
    }
    }


    Alas, the above workaround didn't work and now i don't know what to do.




    1. What are the merit/demerit of my approach?

    2. How to handle dynamic instance with IoC container?




    UPDATE



    Register after unregister seems necessary as the type cannot be found if left only unregistered. As for the problem, it seems i also need to unregister the View type too. So i add a bit of code-behind in the View (Window)



    private void MainWindow_Closed(object sender, EventArgs e)
    {
    SimpleIoc.Default.Unregister<IMainWindowView>();
    SimpleIoc.Default.Register<IMainWindowView, MainWindow>();
    }


    Works fine so far, is this approach acceptable?










    share|improve this question



























      0












      0








      0








      i'm new to MVVM and IoC. I use ViewModel-first approach for this project. My project assemblies organization look like this:




      View (has reference to ViewModel)
      ViewModel (has reference to Model)
      Model




      Worked fine at the beginning, until i need a Login view. Login run on program startup. On successful login MainWindow will be shown and Login has to close itself. The reverse can be done with LogoutCommand from MainWindow.



      The main obstacle i'm facing is instantiating a View (Window) for a given ViewModel type, while ViewModel has no knowledge of its View. On search for the answer, i've found:




      1. Mediator/Messenger pattern. Which i found very convenient, i used this pattern for showing dialog MessageBox. But only for that purpose, i'm not comfortable using this pattern for handling object instantiation.

      2. Dependency Injection. A new concept to me. But i can see a real benefit of decoupling service constructor knowledge out of consumer class. Hence i tried MVVM-Light SimpleIoc for starter by injecting View instance to ViewModel constructor as interface and proceed to register them on ViewModelLocator


      SimpleIoc.Default.Register<IMainWindowView, MainWindow>();  
      SimpleIoc.Default.Register<ILoginView, Login>();
      SimpleIoc.Default.Register<LoginVM>();
      SimpleIoc.Default.Register<MainWindowVM>();


      On successful login, the MainWindow shown and Login closed. But when i logout of MainWindow to show Login again, i encountered InvalidOperationException Cannot set Visibility or call Show, ShowDialog, or WindowInteropHelper.EnsureHandle after a Window has closed. So i thought i need to "clean up" the instance created by SimpleIoC by unregistering it on Window Closing event.



      public class ViewModelBaseEx : ViewModelBase
      {
      protected SimpleIoc Ioc
      {
      get { return SimpleIoc.Default; }
      }

      protected virtual void Unregister<T>() where T : class
      {
      Cleanup();

      if (Ioc.IsRegistered<T>())
      {
      // Attempt to remove instance
      Ioc.Unregister<T>();

      // If i still need to show this window again,
      // shouldn't i need to have this instance available? (not sure)
      Ioc.Register<T>();
      }
      }
      }


      Alas, the above workaround didn't work and now i don't know what to do.




      1. What are the merit/demerit of my approach?

      2. How to handle dynamic instance with IoC container?




      UPDATE



      Register after unregister seems necessary as the type cannot be found if left only unregistered. As for the problem, it seems i also need to unregister the View type too. So i add a bit of code-behind in the View (Window)



      private void MainWindow_Closed(object sender, EventArgs e)
      {
      SimpleIoc.Default.Unregister<IMainWindowView>();
      SimpleIoc.Default.Register<IMainWindowView, MainWindow>();
      }


      Works fine so far, is this approach acceptable?










      share|improve this question
















      i'm new to MVVM and IoC. I use ViewModel-first approach for this project. My project assemblies organization look like this:




      View (has reference to ViewModel)
      ViewModel (has reference to Model)
      Model




      Worked fine at the beginning, until i need a Login view. Login run on program startup. On successful login MainWindow will be shown and Login has to close itself. The reverse can be done with LogoutCommand from MainWindow.



      The main obstacle i'm facing is instantiating a View (Window) for a given ViewModel type, while ViewModel has no knowledge of its View. On search for the answer, i've found:




      1. Mediator/Messenger pattern. Which i found very convenient, i used this pattern for showing dialog MessageBox. But only for that purpose, i'm not comfortable using this pattern for handling object instantiation.

      2. Dependency Injection. A new concept to me. But i can see a real benefit of decoupling service constructor knowledge out of consumer class. Hence i tried MVVM-Light SimpleIoc for starter by injecting View instance to ViewModel constructor as interface and proceed to register them on ViewModelLocator


      SimpleIoc.Default.Register<IMainWindowView, MainWindow>();  
      SimpleIoc.Default.Register<ILoginView, Login>();
      SimpleIoc.Default.Register<LoginVM>();
      SimpleIoc.Default.Register<MainWindowVM>();


      On successful login, the MainWindow shown and Login closed. But when i logout of MainWindow to show Login again, i encountered InvalidOperationException Cannot set Visibility or call Show, ShowDialog, or WindowInteropHelper.EnsureHandle after a Window has closed. So i thought i need to "clean up" the instance created by SimpleIoC by unregistering it on Window Closing event.



      public class ViewModelBaseEx : ViewModelBase
      {
      protected SimpleIoc Ioc
      {
      get { return SimpleIoc.Default; }
      }

      protected virtual void Unregister<T>() where T : class
      {
      Cleanup();

      if (Ioc.IsRegistered<T>())
      {
      // Attempt to remove instance
      Ioc.Unregister<T>();

      // If i still need to show this window again,
      // shouldn't i need to have this instance available? (not sure)
      Ioc.Register<T>();
      }
      }
      }


      Alas, the above workaround didn't work and now i don't know what to do.




      1. What are the merit/demerit of my approach?

      2. How to handle dynamic instance with IoC container?




      UPDATE



      Register after unregister seems necessary as the type cannot be found if left only unregistered. As for the problem, it seems i also need to unregister the View type too. So i add a bit of code-behind in the View (Window)



      private void MainWindow_Closed(object sender, EventArgs e)
      {
      SimpleIoc.Default.Unregister<IMainWindowView>();
      SimpleIoc.Default.Register<IMainWindowView, MainWindow>();
      }


      Works fine so far, is this approach acceptable?







      mvvm mvvm-light ioc-container






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 28 '18 at 9:02







      Suwandy

















      asked Nov 28 '18 at 8:31









      SuwandySuwandy

      314




      314
























          0






          active

          oldest

          votes











          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53515150%2fhow-to-handle-dynamic-instance-window-with-simpleioc-container%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          0






          active

          oldest

          votes








          0






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes
















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53515150%2fhow-to-handle-dynamic-instance-window-with-simpleioc-container%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Lallio

          Futebolista

          Jornalista