How to handle dynamic instance (Window) with SimpleIoc Container
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 toViewModel)ViewModel(has reference toModel)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:
- 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. - 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
SimpleIocfor starter by injectingViewinstance toViewModelconstructor as interface and proceed to register them onViewModelLocator
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.
- What are the merit/demerit of my approach?
- 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
add a comment |
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 toViewModel)ViewModel(has reference toModel)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:
- 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. - 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
SimpleIocfor starter by injectingViewinstance toViewModelconstructor as interface and proceed to register them onViewModelLocator
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.
- What are the merit/demerit of my approach?
- 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
add a comment |
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 toViewModel)ViewModel(has reference toModel)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:
- 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. - 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
SimpleIocfor starter by injectingViewinstance toViewModelconstructor as interface and proceed to register them onViewModelLocator
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.
- What are the merit/demerit of my approach?
- 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
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 toViewModel)ViewModel(has reference toModel)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:
- 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. - 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
SimpleIocfor starter by injectingViewinstance toViewModelconstructor as interface and proceed to register them onViewModelLocator
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.
- What are the merit/demerit of my approach?
- 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
mvvm mvvm-light ioc-container
edited Nov 28 '18 at 9:02
Suwandy
asked Nov 28 '18 at 8:31
SuwandySuwandy
314
314
add a comment |
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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