What i did
I have HomeViewModel and SellsViewModel.
In the HomeViewModel, I have property "SellID"
In the constructor of SellViewModel, i am able to Resolve reference of HomeViewModel and stored it in m_objHomeViewModel variable in SellViewModel
In the XAML of SellViewModel, i have a textbox which shows "SellID", this textbox is bound to "m_objHomeViewModel.SellID"
What i am getting doing this
Doing this, whenever user selects difference "Sell" on HomeViewModel, automatically my SellViewModel picks it up and shows changes in SellView.
Question
As XAML textbox in SellView is bound to a property in HomeViewModel, changes are getting reflected on UI immediately
But i am not able catch any event (Such as property change) in SellViewModel, catching such event i want to load other values for the selected "SellID" from database.
I am not using Event Agreegator. If used, i can easily subscribed to event in SellViewModel published by HomeViewModel
Q1: How to do it without using Event Agreegator?
Q2: If in XAML, TextBox is bound to property m_objHomeViewModel.SellID, will it create memory leakage?
Q3: If in the HomeViewModel, i get reference to SellViewModel (Using container.resolve) and call a public property or method of SellViewModel whenever "SellID" property in HomeViewModel is modified. Is it a good programming practice? Here i think it will create tight coupling between HomeViewModel and SellViewModel
Please suggest on this...
Regards
A1: If I understand your design, your SellVM will need to manually subscribe to the PropertyChanged event of your HomeVM. If the SellId property of your HomeVM raises PropertyChanged, then your SellVM will see that and respond accordingly.
A2: Without seeing the entire application, simply databinding to a property won't cause a memory leak. As long as the UI is displayed, the HomeVM will be in memory, but .NET does a pretty good job of recognizing when it is no longer needed and cleaning up the memory. The answer to this is highly dependent on your overall design, but the simple act of binding the SellID from the HomeVM through the SellVM won't, on its own, cause a memory leak.
A3: This sounds a little strange - Without understanding the full architecture, it seems that the SellID should belong to the SellVM, and when the users switches SellID, the HomeVM loads the SellVM with the appropriate SellID. This seems more OO and allows you to separate concerns. This way everything about the "Sell" (sale?) is encapsulated in the SellVM and the HomeVM is strictly responsible for coordination (loading the correct child VMs). But this is based on what little I can gather about your overall design.
Related
I just want to ask if it's OK to access the ViewModel's data in the View backend?
Basically I just need a check to see if a ViewModel's property is set (which gets set when the user selects something), and if it's not I'll just redirect the user to another View telling him he needs to select something first. Is this a poor-design practice or is it OK, just for a minor check like this? Really don't want to implement a static class and extrapolate the data to it, and check it instead.
Another question tightly related to this, is can I call a method from the View (when the View is closing), that unregisters that particular ViewModel from the IoC container (this ViewModel isn't singleton). The alternative is to send a message from the View to the ViewModel when the View is closing, and when the ViewModel gets that message it unregisters itself. The problem I'm trying to solve with this is that, every time that ViewModel is requested it has to be a new one, but my IoC container caches them, making my program a memory hog. All of the ViewModels get released on application exit, meaning x ViewModels will still exist in the cache even though they're most likely not needed.
Basically I just need a check to see if a ViewModel's property is set (which gets set when the user selects something), and if it's not I'll just redirect the user to another View telling him he needs to select something first. Is this a poor-design practice or is it OK, just for a minor check like this?
It does not seem to be wrong to check the value of some ViewModel property and reflect the changes on the View side. The View state could be "bound" to the ViewModel state by the WPF data binding mechanism: Binding, Triggers (Trigger, DataTrigger, EventTrigger), Commands (including EventToCommand), etc.
But sometimes it is useful to handle ViewModel state change by the ViewModel itself using UI Services. For example, IWindowService interface can be introduced to allow to open windows from the context of the ViewModel implementation.
Another question tightly related to this, is can I call a method from the View (when the View is closing), that unregisters that particular ViewModel from the IoC container (this ViewModel isn't singleton).
...
The problem I'm trying to solve with this is that, every time that ViewModel is requested it has to be a new one, but my IoC container caches them, making my program a memory hog. All of the ViewModels get released on application exit, meaning x ViewModels will still exist in the cache even though they're most likely not needed.
It seems to be strange that the described dependency container "cache effect" exists when the registration is specified as "resolve per call behavior" (not "singleton behavior"). Please check that the registration is specified as "resolve per call behavior" (for example, PerResolveLifetimeManager in terms of Unity Container Lifetime Managers).
Update
The ViewModel lifetime problem exists because SimpleIoC container is used.
I would like to recommend using another dependency injection container (with appropriate lifetime management) to make the implementation less complex and error-prone.
But, if there is a strong need to use SimpleIoC container, some kind of the ViewModel lifetime management can be implemented using:
SimpleIoc.Default.GetInstance<ViewModel>(key); method call to resolve an instance of ViewModel;
SimpleIoc.Default.Unregister(key); to un-register the instance when it is no longer needed (Closed event, etc).
The implementation can be found here: answer #1, answer #2.
If I have a model which is pretty much a readonly collection and dispayed on a grid, where the user selects a row.
Do I need to have INotifyPropertyChanged always implemented on the model? Is there a performance benefit of implementing vs not?
I would like to know if performance is impacted by UI trying to use something like
var x = Model as INotifyPropertyChanged;
which it wouldn't have used otherwise.
If you are using the model in any data bindings, then yes, you should implement INotifyPropertyChanged even if it is completely immutable. The reason has nothing to do with performance, but to avoid a memory leak.
A Binding will always try to register for change notifications, and if you do not implement INotifyPropertyChanged or expose discrete change events of the form [Property]Changed, it will register through the PropertyDescriptor API. The default, reflection-based PropertyDescriptor implementation uses a global subscription table, and if for some reason the Binding does not unsubscribe cleanly, your view model will be kept alive indefinitely. This is in contrast to the weak event pattern used when bindings subscribe to INotifyPropertyChanged notifications. Bindings at runtime generally clean up after themselves, but the Xaml designer is notorious for leaking under these circumstances, causing your designer process's memory consumption to rise steadily as you work.
If you are just displaying in on a DataGrid and not expecting any UI interaction that'll change the value of the Model then you do not have to implement INPC.
WPF is tied to the INPC mechanism to update the UI from the backing Model. You don't need it if you load it once and won't change again. However, INPC can be pretty handy and you need to implement it if say a business logic that requires you to update something to a different row then you can basically subscribe the other model's PropertyChangedEvent to do something to the other row when a property changed is raised.
There is no performance benefit of implementing it.
My MVVM app has a number of views that inherit from a base user control, which exposes an "ID" property. In the XAML this is bound to an ID property on the view's underlying view model, simply:
Id="{Binding Path=Id}"
The view model implements INotifyPropertyChanged, and its ID is set in the constructor. The ID is used to uniquely identify each view/view model, and is primarily used by a "desktop manager" to manage the user controls within the main window, rather like an MDI app. When my app starts I instantiate the various view models and their views, and assign the view models to the views' DataContext. I then pass the views to the desktop manager which places them on its canvas, positions them, etc.
The problem I have is that the view's ID is still null at this point, and only seems to get bound to the data context some time later (when the UI is rendered perhaps?). I have tried forcing the binding like this, but it doesn't help:-
var bindingExpression = widget.GetBindingExpression(DesktopElement.IdProperty);
bindingExpression.UpdateTarget();
It's not the end of the world, as I can pass the desktop manager my view and the ID from the view model, but it feels a little hacky. I was curious to know at what point in the control/window lifecycle the binding occurs, and whether there was some other way to force the binding to happen?
Thanks in advance
Andy
In order to understand how bindings are transferred, you need to understand the Dispatcher. Basically, it is a priority queue. Things like layout, bindings, rendering, input, etc. are placed in the queue at different priorities.
Now, from the sound of it, you never yield execution back to the Dispatcher. This means that Binding values can't transfer (when you manually call UpdateTarget you are just scheduling this on the Dispatcher). So, in short, you need to let the Dispatcher execute the queued operations before you finish initializing.
The easiest way to do this is to call BeginInvoke at a lower DispatcherPriority on a method to finish initialization. Because of the nature of how the layout system works, it can be tricky sometimes to pick the right priority, but you'll probably be okay if you go with DispatcherPriority.Loaded.
My suggestion would be to have an interface that your View Models implement, which exposes the Id property. You can then have your Desktop Manager grab the Id from the DataContext by casting it to the appropriate interface. This is likely a cleaner separation of responsibilities, as your Desktop Manager should probably know as little about the concrete View as possible (for the sake of testability.)
Ok, following on from yesterday I've added a new layer of complexity. We still have a theoretical Model class, ViewModel and View. This time my Model has a Threading.Timer (Chosen specifically to get timer callbacks on the "wrong" thread.
The Model has an ObservableCollection. The Timer callback adds items to the collection.
The ViewModel simply passes the collection to the View which contains a listbox bound to the collection.
This doesn't work.
The model also exposes a string which is updated in the same timer callback.
This too is exposed via the viewmodel and bound to a TextBox.
This does work.
I've seen hints in my googling that updating collections doesn't make INotifyCollectionChanged work as expected. I get a total implosion, not even an exception, just immediate termination of the application.
So there are two questions:
One relates to our discussion yesterday. I'm using INotifyPropertyChanged and ObservableCollections in my Model because they are the thing upon which the view does work. It still makes sense to me to use these mechanisms to notify my viewmodel, or what ever that the underlying model has changed. So how do I deal with updates occuring on a different thread?
Second, what is happening that makes INotifyPropertyChanged work with the binding? I'm binding a string property to a DependencyProperty called Text, so is it the DependencyProperty system that marshals my change back to the UI thread? Edit: And can I rely on it, i.e. does it do this because they expect me to talk to it cross-thread, or is it just a catch all that I shouldn't rely on?
The ListBox is bound through ItemsSource="{Binding ObsCollection}". When this crashes the application. Actually, at first I started the timer when the Model was created which happened when the Window's DataContext was set, so it would actually bomb Visual Studio...
Thanks
WPF controls have thread-affinity, what this means is that their properties can only be modified from the UI thread. Therefore, if you update a property value from a Timer (other than a DispatcherTimer), you will have to marshal this update onto the UI thread. This is perfomed via the dispatcher:
Application.Current.Dispatcher.BeginInvoke(
DispatcherPriority.Normal,
new Action(() => // update your control here));
The databinding framework does not ensure that updates are marshalled onto the UI thread, therefore, if you update your model from a different thread, this will cause issues. therefore you need to use the same pattern as above. In other words, if you are adding objections to your observable collection, this add must be performed via the Dispatcher.
This problem is quite prevalent in WPF. I think the best option is to have your own ObservableCollection<> subclass that takes care of dispatching event notifications to the UI thread automatically.
And since the wheel has already been invented, I 'm going to simply refer you to the answer to this question: ObservableCollection and threading.
I have a WPF application based on PRISM that utilizes the MVVM pattern.
I have noticed that occasionally my view models, views and everything connected to them will hang around long after their intended lifespan.
One leak involved subscribing to CollectionChanged on a collection belonging to an injected service, another involved not calling the Stop method on a DispatcherTimer, and yet another required a collection be cleared of it's items.
I feel using a CompositePresentationEvent is probably preferable to subscribing to CollectionChanged, but in the other scenarios I am leaning towards implementing IDisposable and have the views call the Dispose method on the view models.
But then something needs to tell the view when to call Dispose on the view model, which gets even less attractive when the complexity of the views increase, and they start including child views.
What do you think is the best approach to handling view models, to ensure they don't leak memory?
Thanks in advance
Ian
I can tell you that I've experienced 100% of the pain you have experienced. We are memory leak brothers, I think.
Unfortunately the only thing I've figured out to do here is something very similar to what you are thinking.
What we've done is create an attached property that a view can apply to itself to bind a handler to the ViewModel:
<UserControl ...
common:LifecycleManagement.CloseHandler="{Binding CloseAction}">
...
</UserControl>
Then our ViewModel just has a method on it of type Action:
public MyVM : ViewModel
{
public Action CloseAction
{
get { return CloseActionInternal; }
}
private void CloseActionInternal()
{
//TODO: stop timers, cleanup, etc;
}
}
When my close method fires (we have a few ways to do this... it's a TabControl UI with "X" on the tab headers, that kind of thing), I simply check to see if this view has registered itself with the AttachedProperty. If so, I call the method referenced there.
It's a pretty roundabout way of simply checking to see if the DataContext of a View is an IDisposable, but it felt better at the time. The problem with checking the DataContext is you might have sub view models that also need this control. You'd either have to make sure your viewmodels chain forward this dispose call or check all of the views in the graph and see if their datacontexts are IDisposable (ugh).
I sort of feel like there is something missing here. There are a few other frameworks that attempt to mitigate this scenario in other ways. You might take a look at Caliburn. It has a system for handling this where a ViewModel is aware of all sub view models and this enables it to automatically chain things forward. In particular, there is an interface called ISupportCustomShutdown (I think that's what it's called) that helps mitigate this problem.
The best thing I've done, however, is make sure and use good memory leak tools like Redgate Memory Profiler that help you visualize the object graph and find the root object. If you were able to identify that DispatchTimer issue, I imagine you are already doing this.
Edit: I forgot one important thing. There is a potential memory leak caused by one of the event handlers in DelegateCommand. Here's a thread about it on Codeplex that explains it. http://compositewpf.codeplex.com/WorkItem/View.aspx?WorkItemId=4065
The latest version of the Prism (v2.1) has this fixed. (http://www.microsoft.com/downloads/details.aspx?FamilyID=387c7a59-b217-4318-ad1b-cbc2ea453f40&displaylang=en).
My findings so far...
In addition to PRISM, Unity, WPF and MVVM we are also using Entity Framework and the Xceed data grid. Memory profiling was done using dotTrace.
I ended up implementing IDisposable on a base class for my view models with the Dispose(bool) method being declared virtual allowing sub classes the chance to clean up as well.
As each view model in our application gets a child container from Unity we dispose it as well, in our case this ensure that EF's ObjectContext went out of scope. This was our major source of memory leaks.
The view model is disposed within an explicit CloseView(UserControl) method on a base controller class. It looks for an IDisposable on the DataContext of the view and calls Dispose on it.
The Xceed data grid seems to be causing a fair share of the leaks, especially in long running views. Any view that refreshes the data grid's ItemSource by assiging a new collection should call Clear() on the existing collection before assigning the new one.
Be careful with Entity Framework and avoid any long running object contexts. It's very unforgiving when it comes to large collections, even though you have removed the collection if tracking is turned on, it will hold a reference to every item in the collection even though your no longer hanging on to them.
If you don't need to update the entity retrieve it with MergeOption.NoTracking, especially in long lived views that bind to collections.
Avoid views with a long life, don't hold onto them within a region when they are not visibile, this will cause you grief especially if they refresh their data at regular intervals when they are visible.
When using CellContentTemplates on the Xceed Column don't use dynamic resources as the resource will hold a reference to the cell, which in turn keep the entire view alive.
When using CellEditor on the Xceed Column and the resource is stored in an external resource dictionary add x:Shared="False" to the resource containing the CellEditor, once again the resource will hold a reference to the cell, using x:Shared="False" ensures you get a fresh copy each time, with the old one being removed correctly.
Be careful when binding the DelegateCommand to items within the Exceed data grid, if you have a case such as a delete button on the row which binds to a command, be sure to clear the collection containing the ItemsSource before closing the view. If you're refreshing the collection you also need to reinitialize the command as well as the command will hold a reference to each row.