How to unsibcribe events when I delete a ViewModel?












1















I have a ViewModel that it has some events to notify actions to anothers viewModels.



I have few events, but I will ask about one them, that it is this:



public event MyEventEventHandler MyEvent;
private void OnMyEvent(MyType param)
{
MyEventEvent?.Invoke(param);
}


In a intermediate ViewModel, I relation a second view model that has a method to subscribe to this event. I do in this way:



MainViewModel myMainViewmodel = new MyViewModel();
SecondViewModel mySecondViewModel = new SecondViewModel();
myMainViewmodel.MyEvent += mySecondViewmodel.handleEvent;


In this case, it is to open a dialog, so the main view model is the dialog and the second view model is which calls to the dialog, so when I finish to open the dialog, how the second view model still is subcribed to the main ViewModel, the main ViewModel would not be recollected by the garbage collector.



My doubt is where I should unsubscribe the event, in the disponse of the main ViewModel or the finally block in the intermediate view model?



I was thinking if there would be someway to access to the collection of subcribers in the main ViewModel, so in the dipose I could do something like MyEvent.clear() or something like that to unsubcribe all the events, instead to unsubscribe one by one all of the in the finally block in the intermediate ViewModel.



In general, I would like to know the best way to unsubscribe events when I related two ViewModels.



Thanks.










share|improve this question























  • how about setting the event to null in Dispose() method?

    – Umair M
    Nov 13 '18 at 11:46











  • In MVVM you shouldn't do it but make usage of Messenger instead. Thus you would avoid handling relatively expensive ressources like events.

    – sprinter252
    Nov 13 '18 at 11:50
















1















I have a ViewModel that it has some events to notify actions to anothers viewModels.



I have few events, but I will ask about one them, that it is this:



public event MyEventEventHandler MyEvent;
private void OnMyEvent(MyType param)
{
MyEventEvent?.Invoke(param);
}


In a intermediate ViewModel, I relation a second view model that has a method to subscribe to this event. I do in this way:



MainViewModel myMainViewmodel = new MyViewModel();
SecondViewModel mySecondViewModel = new SecondViewModel();
myMainViewmodel.MyEvent += mySecondViewmodel.handleEvent;


In this case, it is to open a dialog, so the main view model is the dialog and the second view model is which calls to the dialog, so when I finish to open the dialog, how the second view model still is subcribed to the main ViewModel, the main ViewModel would not be recollected by the garbage collector.



My doubt is where I should unsubscribe the event, in the disponse of the main ViewModel or the finally block in the intermediate view model?



I was thinking if there would be someway to access to the collection of subcribers in the main ViewModel, so in the dipose I could do something like MyEvent.clear() or something like that to unsubcribe all the events, instead to unsubscribe one by one all of the in the finally block in the intermediate ViewModel.



In general, I would like to know the best way to unsubscribe events when I related two ViewModels.



Thanks.










share|improve this question























  • how about setting the event to null in Dispose() method?

    – Umair M
    Nov 13 '18 at 11:46











  • In MVVM you shouldn't do it but make usage of Messenger instead. Thus you would avoid handling relatively expensive ressources like events.

    – sprinter252
    Nov 13 '18 at 11:50














1












1








1


1






I have a ViewModel that it has some events to notify actions to anothers viewModels.



I have few events, but I will ask about one them, that it is this:



public event MyEventEventHandler MyEvent;
private void OnMyEvent(MyType param)
{
MyEventEvent?.Invoke(param);
}


In a intermediate ViewModel, I relation a second view model that has a method to subscribe to this event. I do in this way:



MainViewModel myMainViewmodel = new MyViewModel();
SecondViewModel mySecondViewModel = new SecondViewModel();
myMainViewmodel.MyEvent += mySecondViewmodel.handleEvent;


In this case, it is to open a dialog, so the main view model is the dialog and the second view model is which calls to the dialog, so when I finish to open the dialog, how the second view model still is subcribed to the main ViewModel, the main ViewModel would not be recollected by the garbage collector.



My doubt is where I should unsubscribe the event, in the disponse of the main ViewModel or the finally block in the intermediate view model?



I was thinking if there would be someway to access to the collection of subcribers in the main ViewModel, so in the dipose I could do something like MyEvent.clear() or something like that to unsubcribe all the events, instead to unsubscribe one by one all of the in the finally block in the intermediate ViewModel.



In general, I would like to know the best way to unsubscribe events when I related two ViewModels.



Thanks.










share|improve this question














I have a ViewModel that it has some events to notify actions to anothers viewModels.



I have few events, but I will ask about one them, that it is this:



public event MyEventEventHandler MyEvent;
private void OnMyEvent(MyType param)
{
MyEventEvent?.Invoke(param);
}


In a intermediate ViewModel, I relation a second view model that has a method to subscribe to this event. I do in this way:



MainViewModel myMainViewmodel = new MyViewModel();
SecondViewModel mySecondViewModel = new SecondViewModel();
myMainViewmodel.MyEvent += mySecondViewmodel.handleEvent;


In this case, it is to open a dialog, so the main view model is the dialog and the second view model is which calls to the dialog, so when I finish to open the dialog, how the second view model still is subcribed to the main ViewModel, the main ViewModel would not be recollected by the garbage collector.



My doubt is where I should unsubscribe the event, in the disponse of the main ViewModel or the finally block in the intermediate view model?



I was thinking if there would be someway to access to the collection of subcribers in the main ViewModel, so in the dipose I could do something like MyEvent.clear() or something like that to unsubcribe all the events, instead to unsubscribe one by one all of the in the finally block in the intermediate ViewModel.



In general, I would like to know the best way to unsubscribe events when I related two ViewModels.



Thanks.







c# .net






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Nov 13 '18 at 11:36









Álvaro GarcíaÁlvaro García

6,3111861116




6,3111861116













  • how about setting the event to null in Dispose() method?

    – Umair M
    Nov 13 '18 at 11:46











  • In MVVM you shouldn't do it but make usage of Messenger instead. Thus you would avoid handling relatively expensive ressources like events.

    – sprinter252
    Nov 13 '18 at 11:50



















  • how about setting the event to null in Dispose() method?

    – Umair M
    Nov 13 '18 at 11:46











  • In MVVM you shouldn't do it but make usage of Messenger instead. Thus you would avoid handling relatively expensive ressources like events.

    – sprinter252
    Nov 13 '18 at 11:50

















how about setting the event to null in Dispose() method?

– Umair M
Nov 13 '18 at 11:46





how about setting the event to null in Dispose() method?

– Umair M
Nov 13 '18 at 11:46













In MVVM you shouldn't do it but make usage of Messenger instead. Thus you would avoid handling relatively expensive ressources like events.

– sprinter252
Nov 13 '18 at 11:50





In MVVM you shouldn't do it but make usage of Messenger instead. Thus you would avoid handling relatively expensive ressources like events.

– sprinter252
Nov 13 '18 at 11:50












1 Answer
1






active

oldest

votes


















0














You shouldn't make a type IDisposable only for one purpose of being able to unsubscribe from events. IDisposable means, a type contains unmanaged resources or instances of other IDisposable types.



If your view-model already implements IDisposable, you can of course unsubscribe from events there.



If not, you can create a CleanUp (or similar) method and unsubscribe there.



There's a very neat solution I use for such things. I call them one-shot event handlers (or auto-unsubscribing event handlers). This is where the new feature of C#7 "local functions" helps.



void IntermediateViewModel_CreateViewModels()
{
MainViewModel myMainViewmodel = new MyViewModel();
SecondViewModel mySecondViewModel = new SecondViewModel();
myMainViewmodel.MyEvent += LocalEventHandler;

void LocalEventHandler(object sender, EventArgs e)
{
// unsubscribe --> no memory leaks!
myMainViewmodel.MyEvent -= LocalEventHandler;
mySecondViewmodel.handleEvent(sender, e);
}
}


With such approach, when the MainViewModel.MyEvent fires, the local function LocalEventHandler is executed as event handler. You can unsubscribe from the event right away in that local function, so that there's no reference anymore (no memory leak, the view-model can be GCed).



From your use case I understood that you want to create a dialog view-model, display it using a view, and then immediately get rid of that view-model. Then, my sample perfectly fits to your requirements.






share|improve this answer


























  • You could have the same self-unsubscribing event handlers without local methods, simply use captured local variable to store lambda (event handler).

    – Sinatr
    Nov 13 '18 at 12:11











  • Yes, but it doesn't look so neat then. You have to assign a default null value to the lambda variable to be able to capture it. Local functions make all this look a lot nicer.

    – dymanoid
    Nov 13 '18 at 12:12













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%2f53280187%2fhow-to-unsibcribe-events-when-i-delete-a-viewmodel%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









0














You shouldn't make a type IDisposable only for one purpose of being able to unsubscribe from events. IDisposable means, a type contains unmanaged resources or instances of other IDisposable types.



If your view-model already implements IDisposable, you can of course unsubscribe from events there.



If not, you can create a CleanUp (or similar) method and unsubscribe there.



There's a very neat solution I use for such things. I call them one-shot event handlers (or auto-unsubscribing event handlers). This is where the new feature of C#7 "local functions" helps.



void IntermediateViewModel_CreateViewModels()
{
MainViewModel myMainViewmodel = new MyViewModel();
SecondViewModel mySecondViewModel = new SecondViewModel();
myMainViewmodel.MyEvent += LocalEventHandler;

void LocalEventHandler(object sender, EventArgs e)
{
// unsubscribe --> no memory leaks!
myMainViewmodel.MyEvent -= LocalEventHandler;
mySecondViewmodel.handleEvent(sender, e);
}
}


With such approach, when the MainViewModel.MyEvent fires, the local function LocalEventHandler is executed as event handler. You can unsubscribe from the event right away in that local function, so that there's no reference anymore (no memory leak, the view-model can be GCed).



From your use case I understood that you want to create a dialog view-model, display it using a view, and then immediately get rid of that view-model. Then, my sample perfectly fits to your requirements.






share|improve this answer


























  • You could have the same self-unsubscribing event handlers without local methods, simply use captured local variable to store lambda (event handler).

    – Sinatr
    Nov 13 '18 at 12:11











  • Yes, but it doesn't look so neat then. You have to assign a default null value to the lambda variable to be able to capture it. Local functions make all this look a lot nicer.

    – dymanoid
    Nov 13 '18 at 12:12


















0














You shouldn't make a type IDisposable only for one purpose of being able to unsubscribe from events. IDisposable means, a type contains unmanaged resources or instances of other IDisposable types.



If your view-model already implements IDisposable, you can of course unsubscribe from events there.



If not, you can create a CleanUp (or similar) method and unsubscribe there.



There's a very neat solution I use for such things. I call them one-shot event handlers (or auto-unsubscribing event handlers). This is where the new feature of C#7 "local functions" helps.



void IntermediateViewModel_CreateViewModels()
{
MainViewModel myMainViewmodel = new MyViewModel();
SecondViewModel mySecondViewModel = new SecondViewModel();
myMainViewmodel.MyEvent += LocalEventHandler;

void LocalEventHandler(object sender, EventArgs e)
{
// unsubscribe --> no memory leaks!
myMainViewmodel.MyEvent -= LocalEventHandler;
mySecondViewmodel.handleEvent(sender, e);
}
}


With such approach, when the MainViewModel.MyEvent fires, the local function LocalEventHandler is executed as event handler. You can unsubscribe from the event right away in that local function, so that there's no reference anymore (no memory leak, the view-model can be GCed).



From your use case I understood that you want to create a dialog view-model, display it using a view, and then immediately get rid of that view-model. Then, my sample perfectly fits to your requirements.






share|improve this answer


























  • You could have the same self-unsubscribing event handlers without local methods, simply use captured local variable to store lambda (event handler).

    – Sinatr
    Nov 13 '18 at 12:11











  • Yes, but it doesn't look so neat then. You have to assign a default null value to the lambda variable to be able to capture it. Local functions make all this look a lot nicer.

    – dymanoid
    Nov 13 '18 at 12:12
















0












0








0







You shouldn't make a type IDisposable only for one purpose of being able to unsubscribe from events. IDisposable means, a type contains unmanaged resources or instances of other IDisposable types.



If your view-model already implements IDisposable, you can of course unsubscribe from events there.



If not, you can create a CleanUp (or similar) method and unsubscribe there.



There's a very neat solution I use for such things. I call them one-shot event handlers (or auto-unsubscribing event handlers). This is where the new feature of C#7 "local functions" helps.



void IntermediateViewModel_CreateViewModels()
{
MainViewModel myMainViewmodel = new MyViewModel();
SecondViewModel mySecondViewModel = new SecondViewModel();
myMainViewmodel.MyEvent += LocalEventHandler;

void LocalEventHandler(object sender, EventArgs e)
{
// unsubscribe --> no memory leaks!
myMainViewmodel.MyEvent -= LocalEventHandler;
mySecondViewmodel.handleEvent(sender, e);
}
}


With such approach, when the MainViewModel.MyEvent fires, the local function LocalEventHandler is executed as event handler. You can unsubscribe from the event right away in that local function, so that there's no reference anymore (no memory leak, the view-model can be GCed).



From your use case I understood that you want to create a dialog view-model, display it using a view, and then immediately get rid of that view-model. Then, my sample perfectly fits to your requirements.






share|improve this answer















You shouldn't make a type IDisposable only for one purpose of being able to unsubscribe from events. IDisposable means, a type contains unmanaged resources or instances of other IDisposable types.



If your view-model already implements IDisposable, you can of course unsubscribe from events there.



If not, you can create a CleanUp (or similar) method and unsubscribe there.



There's a very neat solution I use for such things. I call them one-shot event handlers (or auto-unsubscribing event handlers). This is where the new feature of C#7 "local functions" helps.



void IntermediateViewModel_CreateViewModels()
{
MainViewModel myMainViewmodel = new MyViewModel();
SecondViewModel mySecondViewModel = new SecondViewModel();
myMainViewmodel.MyEvent += LocalEventHandler;

void LocalEventHandler(object sender, EventArgs e)
{
// unsubscribe --> no memory leaks!
myMainViewmodel.MyEvent -= LocalEventHandler;
mySecondViewmodel.handleEvent(sender, e);
}
}


With such approach, when the MainViewModel.MyEvent fires, the local function LocalEventHandler is executed as event handler. You can unsubscribe from the event right away in that local function, so that there's no reference anymore (no memory leak, the view-model can be GCed).



From your use case I understood that you want to create a dialog view-model, display it using a view, and then immediately get rid of that view-model. Then, my sample perfectly fits to your requirements.







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 13 '18 at 12:13

























answered Nov 13 '18 at 12:06









dymanoiddymanoid

8,99722047




8,99722047













  • You could have the same self-unsubscribing event handlers without local methods, simply use captured local variable to store lambda (event handler).

    – Sinatr
    Nov 13 '18 at 12:11











  • Yes, but it doesn't look so neat then. You have to assign a default null value to the lambda variable to be able to capture it. Local functions make all this look a lot nicer.

    – dymanoid
    Nov 13 '18 at 12:12





















  • You could have the same self-unsubscribing event handlers without local methods, simply use captured local variable to store lambda (event handler).

    – Sinatr
    Nov 13 '18 at 12:11











  • Yes, but it doesn't look so neat then. You have to assign a default null value to the lambda variable to be able to capture it. Local functions make all this look a lot nicer.

    – dymanoid
    Nov 13 '18 at 12:12



















You could have the same self-unsubscribing event handlers without local methods, simply use captured local variable to store lambda (event handler).

– Sinatr
Nov 13 '18 at 12:11





You could have the same self-unsubscribing event handlers without local methods, simply use captured local variable to store lambda (event handler).

– Sinatr
Nov 13 '18 at 12:11













Yes, but it doesn't look so neat then. You have to assign a default null value to the lambda variable to be able to capture it. Local functions make all this look a lot nicer.

– dymanoid
Nov 13 '18 at 12:12







Yes, but it doesn't look so neat then. You have to assign a default null value to the lambda variable to be able to capture it. Local functions make all this look a lot nicer.

– dymanoid
Nov 13 '18 at 12:12




















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%2f53280187%2fhow-to-unsibcribe-events-when-i-delete-a-viewmodel%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

Bressuire

Vorschmack

Quarantine