How to unsibcribe events when I delete a ViewModel?
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
add a comment |
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
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
add a comment |
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
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
c# .net
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
add a comment |
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
add a comment |
1 Answer
1
active
oldest
votes
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.
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 defaultnull
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
add a comment |
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%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
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.
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 defaultnull
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
add a comment |
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.
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 defaultnull
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
add a comment |
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.
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.
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 defaultnull
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
add a comment |
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 defaultnull
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
add a comment |
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%2f53280187%2fhow-to-unsibcribe-events-when-i-delete-a-viewmodel%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
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