James Harcourt
James Harcourt

Reputation: 6379

Problems related to View Models created from XAML

As the title suggest, this question is specifically looking for solutions (or ways to avoid) the problems I have experienced with an application which creates view models directly from XAML (no code references to the objects).

This is a mature, functioning and fully MVVM app - and in various areas visual objects are typically added to portions of the main XAML window, or popup windows, like so:

<viewModels:MyViewModel MyDependencyProperty="{Binding}" />

In these cases, the instance of the ViewModel is created with parameterless construction and we sometimes initialise dependency properties as shown above.

The main XAML window has a DataContext of the primary view model - the ApplicationViewModel. Mostly all our views are resource dictionaries with styles defining various templates for the view model target types. These are pulled into merged dictionaries in our skin XAML files.

Problem 1

At times, other objects around the application need to interact with the ApplicationViewModel. At the point of instantiation, however, no reference is available in XAML or otherwise - leading to overuse of a static ApplicationViewModel instance (not good).

Problem 2

Quite often our XAML-instantiated objects will have event hooks and visual elements which require explicit unhooking / disposal. Our visual tree is extremely large and complicated and because we don't have any references in code to our view models there is a constant overhead of managing the disposal and avoiding memory growth - and throwing away the main window along with any view model or visual element which may cause it to remain in memory - is a constant challenge.

I'm not asking for any code here, more for descriptions of your approaches to / experiences of these problems.

I cannot supply code for a variety of reasons - the main one being that there is far too much needed to demonstrate!

UPDATE

Just for information, another important thing about the application is the constant creation of new ViewModel items which represent rich items which appear in a number of constantly rolling lists which are available in tabs. From each of these lists, there are numerous command operations, popup dialogs and other functions which require downstream ViewModel creation (which is currently on-demand). These lists support various touch gestures, including flick/momentum scrolling, slideout menus, touch expansion and drag drop not to mention having rich displays involving vector images and animations!

Upvotes: 1

Views: 184

Answers (1)

Contango
Contango

Reputation: 80272

Having worked on something which sounds like it is of similar complexity, I can offer some recommendations to make your application fast, responsive and memory efficient:

  • If you want fast application performance, and less obscure bugs popping up in 3rd party components, use hide/show rather than create/destroy of the visual tree. This will dramatically speed things up. Creating a visual tree is a very CPU intensive process, so try to favour hiding it and showing it on demand, rather than creating it on demand then destroying it. If something is collapsed, the WPF runtime is very, very good at ignoring any updates related to it, so it uses negligible CPU time. This may lead to you creating a large chunk of XAML which controls the visibility of lots of sub blocks of visible XAML, and it will also lead to lightning fast application performance. We tend to use DataTemplates to keep everything modular so the the complexity is manageable.
  • Use Dependency Injection (DI) to create as many of the ViewModels as you can on application startup. This means that all of the dependencies between the ViewModels are automatically worked out for you. This means that the visual tree for the View is created once, then hidden, and the matching ViewModel is created once, then never created again. All of the Model classes are created once, then never disposed of or created again. I recommend Unity, but any form of DI will do. Avoid using MEF as your main DI mechanism as Unity is better suited for this task. Sometimes it is unavoidable to have auto created classes (such as when a 3rd party component creates new ViewModel classes automatically when the user adds something to a list), but in general these classes are small so this doesn't affect performance.
  • I wouldn't recommend using event hooks. This leads to too much coupling between the ViewModels. Instead, use Reactive Extensions (RX) to pass events between ViewModels. Have a common class which has a Subject. One ViewModel can send events using OnNext, and the other ViewModel can receive events using Subscribe. However, only use this as a last resort: try to construct the object hierarchy so the ViewModels can reference each other without having to resort to event passing.
  • Finally, use async/await whoever you can to shift processing off the main GUI thread (I'm sure you do this already).

Upvotes: 1

Related Questions