ViewModelManager and Register Type with name

Topics: Issues / bugs
Aug 23, 2012 at 7:31 AM

Create here a new Discussion based on the two discussions called in subject.

At the moment I have my own viewmodelmanager. And I registered two instances of them in the unitycontainer with name.

The first viewmodelmanager is for the profiles. When I change the profile I delete every model and viemodel in this viewmodelmanager

The second viewmodelmanager is for the other models and viewmodel. Which I don't whant to delete when the profile is changed.

That was the reason why i need Register Type with name and delete everything in the viewmodelmanager.

Maybe you have a better solution for me?

Coordinator
Aug 23, 2012 at 11:15 AM

Yes, add a SupportsProfile property to the view models and use a single view model manager. When you change a profile, reset the ones with SupportsProfile == true.

Aug 23, 2012 at 12:40 PM

Ok. And how can I delete in the viewmodelmanager with a linq statement?

Coordinator
Aug 23, 2012 at 1:44 PM

Just provide an enumerable method to retrieve all items? You did you use a custom viewmodelmanager, right?

Aug 23, 2012 at 2:15 PM

Yes but I wan't to use the viewmodelmanager of catel.

Thats why i asked how to delete all relations in the viewmodelmanager of catel. Or in this case how to delete special relations.

Coordinator
Aug 24, 2012 at 11:20 AM

Sorry, I still don't get it. Say you want to clear the relations, what should happen for you?

1) Remove all models from all view models (this might cause an *extreme* data reload if you are using nested user controls)?

2) Reload view models?

3) What else?

I foresee lots of issues, so unless I am not exactly sure what you mean, I cannot help you out. Can you provide a small example app so I can get my head around it?

Aug 24, 2012 at 12:41 PM

Hello. Ok. Next try. :-)

When I load an profile I generate models from database. Also generate viewmodels and relations in the ViewModelmanager.
When I change the profile I generate again models. Other ones.

So I don't need the old models and viewmodels any more, and override the models in my list with the new ones. But everything ist also stored in the viewmodelmanager. I don't need them anymore.

So I have to delete the viewmodels and the models in the viewmodelmanager.

Hope you understand.

Sep 6, 2012 at 6:53 AM

Hello. Not clear?

Coordinator
Sep 6, 2012 at 7:32 AM

No time yet, still on the todo list, but lots and lots of work, so please be patient.

Sep 14, 2012 at 8:47 AM

Maybe you can help me in an other way.

Have my on ViewModelManager. I add there my models + viewmodel.

Now I delete everything in the viewmodelmanager. So the problem is that the viewmodels are still alive. I think catel ist still using them. How can I delete the viewmodels.

Sep 14, 2012 at 12:35 PM

???

I added a Button to my view for test and call this

        private void OnCloseThisExecute()
        {
            var dispatcherService = GetService<IDispatcherService>();
            dispatcherService.BeginInvoke(() => CloseViewModel(true));
        }

But nothing happens. The destructor of  viewmodel is not called??? Whats wrong?

Sep 14, 2012 at 1:05 PM

Added a repro: http://catel.codeplex.com/workitem/7198

Coordinator
Sep 14, 2012 at 4:18 PM

Thanks for the repro, now I understand.

The issue is that you are trying to close a view model of a user control. So, the user control view model closes, but then what? If you intention is to close the window, you should:

1) Use the INavigationService to close the complete app

2) USe the view model of the data window to close the window, or subscribe to child view models and manage it that way. A user control can not close a window, it is not "aware" of a window state, it's just a user control with a view model.

Sep 17, 2012 at 7:01 AM
Edited Sep 17, 2012 at 7:14 AM

No.

I don't want to close the window or the complete app. I just wan't to delete the viewmodels. When I call CloseViewModel, the view model closes but it's still alive. The destructor is not called.

Try to explain in an other way.

I use the technic for nested user controls

My window have a listView. Every Item of this listview has its own model and viewmodel. The models are in an ObservableCollection. So now I change the profile in may app and i have to load new models out of the database and delete the old ones. So I clear the ObservableCollection.

But how to delete the viewmodels?

---

Take your example of the house with the rooms.

You wan't new furniture. So you have to delete all beds, tables and chairs. So you can clear the ObservableCollection<Models.Bed> Beds. But how to delete the BedViewModels?

Sep 24, 2012 at 7:33 AM

Hello again.

Any solution?

Coordinator
Sep 24, 2012 at 5:00 PM

Not yet, we are very busy, and also implementing features for paying customers, so we will implement this as soon as we get to this. Of course, you can always create a fork and help us (and yourself of course) out ;-)

Sep 25, 2012 at 1:52 PM

Thats ok. Just Asked. Not that there is a solution but i don't found it. When you understand my problem and think about a solution thats ok for the moment.

Coordinator
Nov 2, 2012 at 5:54 PM

There is no need to manually delete view models from memory. The view model management is done via the ViewModelManager. The view models are closed, but still in memory until garbage collected. That the view models are in memory can mean several things:

1) You subscribed to events inside the VM, but you did not unsubscribe (means that something is preventing the VM to be GC-ed).

2) The GC has not collected yet. You can force it by calling GC.Collect just to test this.

Internally, Catel uses weak references for everything. Each view model in Catel is unique. It also has a UniqueIdentifier property which you can use. If you want to do all VM-management manually, you might want to use that property.

In other words, you shouldn't have to take care of the deletion of the VMs, Catel takes care of this for you. The datacontext (model) changes, the old vm gets closed, the new one loads, the old one is removed from memory.

As a proof, I will add an improved example of the example that shows you exactly what is going on.

Coordinator
Nov 2, 2012 at 6:00 PM

I updated the issue with a new example and a screenshot. I hope your worries are now solved.

Nov 28, 2012 at 3:32 PM

Hello again.

I testet the example.  But i did not work. The first time I click on the button only the constructor is called. The second time the applictaion not respondig anymore.
Whats wrong?

Jan 27, 2013 at 2:33 PM
Edited Jan 27, 2013 at 2:34 PM

Hallo,

I came across a similar issue. The first instance of a vm type can't be collectd by GC!

But I don't like this, because we have very huge vm and I don't want to hold it all the time in memory. So I looked at the catel code and I think the problem (the first I found) is the

private static readonly Dictionary<Type, ViewModelMetadata> _metaData

 

in the ViewModelBase. The ViewModelMetadata.PropertyDescriptors have reference to the first viewmodel, so it can't be collected. In the the static metadata dictionary is no need for the propertyDescriptor to hold the reference to an instance, or is it?

 

Maybe this can be changed to get the first vm free, too?

Coordinator
Jan 27, 2013 at 4:43 PM

The field is static, so it shouldn't keep any view model in memory.

I have checked out the property descriptors itself and you are right. It contains an instance to the VM. So, in face it keeps the first instance of a specific VM type in memory. I will check what I can do to get rid of the reference to the VM.

Coordinator
Jan 27, 2013 at 6:41 PM

I think I was able to fix this issue. Will release a new nightly build now. Please let me know whether the issue is now fixed.

Jan 28, 2013 at 11:05 AM

Yes, solved. Thx.