I have an application that was implemented using the Telerik RadGridView control and Caliburn.Micro MVVM framework. Because of some performance problems, I needed to implement the Telerik VirtualQueryableCollectionView in place of the direct control-to-ObservableCollection binding that was being used. The original code has the ItemsSouce property of the RadGridView was bound to the Prices property of the view model. I had to eliminate that binding and this in the code-behind:
public PricingView(PricingViewModel vm)
{
InitializeComponent();
var dataView = new VirtualQueryableCollectionView()
{ LoadSize=20, VirtualItemCount = vm.Prices.Count };
dataView.ItemsLoading += (sender, e) =>
{
var view = sender as VirtualQueryableCollectionView;
if (dataView != null)
{
view.Load(e.StartIndex, vm.Prices.Skip(e.StartIndex).Take(e.ItemCount));
}
};
this.PricesGridView.ItemsSource = dataView;
}
Since this code only deals with UI specific functionality and it is specific the the view implementation, I am comfortable that this code belongs in the code-behind rather than the ViewModel as it would be a departure from ther MVVM pattern to put a reference to VirtualQueryableCollectionView in the ViewModel. The part that I am not happy with is passing the reference to the ViewModel into the constructor of the View. Is there a good way to get the reference in the code-behind without having to pass the reference in the constructor?
Or is there a better way to do all of this?
My application is implemented with MVVM Light, in my case I used the VirtualQueryableCollectionView class in the ViewModel instead the View.
I did so because I think this class is very similar to the ObservableCollection although it is not part of the core classes.
Actually, VirtualQueryableCollectionView is not limited to the Telerik controls but many other standard controls like the ListView.
The fetch is in my case implemented in the Model.
void MainViewModel()
{
this.Traces = new VirtualQueryableCollectionView<MyEntityClass>()
{
// ViewModel also manages the LoadSize
LoadSize = this.PageSize,
VirtualItemCount = myModel.TotalCount
};
this.Traces.ItemsLoading += (s, args) =>
{
this.Traces.Load(args.StartIndex,
myModel.FetchRange(args.StartIndex, args.ItemCount));
};
}
Not sure what "performance problems" means, but I'm going to assume that means that when you fill the collection from the UI thread it blocks the application long enough it appears unresponsive.
There are two common solutions for this. First is to simply fill your collection from a background thread.
The naive implementation is to simply push the loading onto a ThreadPool thread, then use the Dispatcher to marshall the calls to add items to the ObservableCollection onto the UI thread.
A nicer approach (one that doesn't involve the ViewModel at all) is to use asynchronous bindings. You configure the fallback to some value that indicates to the user you are loading. Sometimes (depending on the situation) you can use a PriorityBinding to gradually fill your UI.
Other alternatives are to load and cache your data beforehand while displaying a splash screen. They're a bit different in WPF, it isn't like the old "display this form for a bit while I do work, then show the main form" mode of winforms. And, of course, there is always the classic data pagination. Its tough to code, but effective. Actually, I should say its tough in the UI. Its easy now in code (database.Skip(pageNumber * pageSize).Take(pageSize)).
Related
I've recently started to delve into MVVM architectural pattern. I've understood large parts of it but still few doubts remain regarding how much responsibility ViewModel should take on behalf of View.
In other words, how dumb should View be?
For example, for simple state coordination like clearing TextView after user presses SubmitButton. This kind of state coordination requires no more than one-liner to implement using some of the popular data-binding frameworks.
For example in pseudo-ReactiveCocoa:
textView.text <~ submitButton.pressed.map { _ in "" }
However, Martin Fowler wrote in his Presentation Model,
The Presentation Model contains the logic that says that the composer field is only enabled if the check box is checked, so the when the view updates itself from the Presentation Model, the composer field control changes its enablement state
which suggests that even the simple logic like clearing out TextView after pressing Button should be encapsulated inside ViewModel.
Such design choice leads to something like this (again, in pseudo-ReactiveCocoa):
// In View
viewModel.submitButtonPressed <~ submitButton.pressed
textView.text <~ viewModel.textViewText
// In ViewModel
textViewText <~ viewModel.submitButtonPressed.map { _ in "" }
Although it leads to better encapsulation of logics while assuming view with the job of binding only (making it dumb), it does make code a lot more verbose and lead to tighter coupling between View and ViewModel (by requiring ViewModel to be aware of SubmitButton).
I'm still new to MVVM pattern in general and learning stuff every day.
How much responsibility should ViewModel take?
In other words, must View be completely dumb and only handle simple binding (connect its UI elements to bindable property provided by ViewModel) or is it okay for View to handle fairly simple logic like the above?
On a side note, is tight coupling between View and ViewModel okay in MVVM?
In general, the ViewModel takes all responsibility. More specifically, in your scenario, the ViewModel wouldn't know about the submitButton, but rather the View would know that the ViewModel exposes a command (an ICommand) called SubmitCommand, and have the submitButton bind to that command.
Sometimes it can get a bit more involved to completely separate the actions and corresponding logic, for instance when there's no binding available for a command for a specific event. But in those cases a fairly simple attached behavior (i.e. InvokeCommandAction and friends, see the documentation) can bridge that gap to coax flow so the logic can go in to the ViewModel.
Very rarely, there are scenarios (of which none come to mind currently) where it gets so involved that I just skip the whole idea, and separate as much as possible, rather than to have to work out three months later exactly what the hell is going on. But those cases are rare indeed.
In other words, must View be completely dumb and only handle simple binding
It's quite good, when view contains data bindings only, but IRL complex views can contain some view-specific logic. E.g., since single view model could be connected to a several views, focus management is a view's prerogative. Another sample is a logic like "hide element A if element B is disabled", or "change color from A to B if button is checked", etc.
XAML frameworks provide several techniques to make view logic more well-composed: commands, triggers, attached behaviors, value converters. But sometimes you actually need code-behind.
For example, for simple state coordination like clearing TextView
after user presses SubmitButton
To be more clear. This is not a view logic, and must be placed in view model:
public class ViewModel
{
private string someText;
public string SomeText
{
get { return someText; }
set
{
if (someText != value)
{
someText = value;
OnPropertyChanged();
}
}
}
private ICommand submitCommand;
public ICommand SumbitCommand
{
if (submitCommand == null)
{
submitCommand = new RelayCommand(() =>
{
// do submit
// clear text
SomeProperty = null;
});
}
return submitCommand;
}
}
XAML:
<TextBox x:Name="SomeTextBox" Text="{Binding SomeText}"/>
<Button Content="Submit" Command="{Binding SubmitCommand}">
But this is a view logic:
public MyWindow()
{
InitializeComponent();
// SomeTextBox should have initial focus
Loaded += (sender, args) => SomeTextBox.Focus();
}
is tight coupling between View and ViewModel okay in MVVM?
Ideally all components should be loosely coupled, but view must know about view model properties to perform data binding.
I am re-factoring an old winforms project into using MVVM via ReactiveUI. The binding part works great so far except the Grid.Datasource = ReactiveList doesn't seem to give any update on changing/adding/deleting.
I just wanted to confirm here, since the DataGridView.Datasource support databinding list only, ReactiveUI.ReactiveList will not work here? or there could be some possible get arounds.
I've just been struggling with this, the approach I've come up with is to wrap a ReactiveList on the ViewModel with a ReactiveDerivedBindingList.
I've created a BindingSource based on the item ViewModel class for design time support, then I replace this at runtime:
private void CreateDerivedBindings()
{
this.Articles = this.ViewModel.Articles.CreateDerivedBindingList(x => x);
this.ViewModel.Articles.ItemChanged.Subscribe(_ => this.Articles.Reset());
//this.Articles.ChangeTrackingEnabled = true;
this.articlesDataGridView.DataSource = this.Articles;
}
private IReactiveDerivedBindingList<ArticleViewModel> Articles { get; set; }
Subscribing to ItemChanged of the underlying ReactiveList (which has ChangeTrackingEnabled turned on) enables items in the grid to update as they are changed. Setting ChangeTrackingEnabled on the derived binding list didn't do anything. This is a brute force approach, I'd guess causing a full refresh of the grid, maybe there is a more finessed approach.
A simpler approach could be to use a ReactiveBindingList on the ViewModel, but I've not tried this as the class is winforms specific and I'm aiming for a ViewModel which could be reused with WPF.
ReactiveList supports INotifyCollectionChanged, I don't know of any other way that lists can signal they have changed. I could be misinformed about Winforms Grid though!
I'm working on a WPF project that's a mishmash of code-behind xaml/xaml.cs and a few not-quite ViewModels as well.
(Disclaimer: Until recently I've had very little in the way of WPF experience. I can design and lay-out a Window or UserControl fairly proficiently, and I think I get the hang of separating an MVVM ViewModel from the View and doing binding wire-ups, but that's the limit of my experience with WPF at present.)
I've been tasked with adding some new features to the program, such that it looks like converting it to use MVVM properly first is going to be necessary.
I'll demonstrate a specific problem I'm facing:
There is a View called SettingsWindow.xaml that I'm working with. It's a set of textboxes, labels and whatnot. I've stripped-out all of the View data into a ViewModel class which resembles something like this:
class SettingsViewModel : ViewModelBase {
private String _outputDirectory;
public String OutputDirectory {
get { return _outputDirectory; }
set { SetValue( () => this.OutputDirectory, ref _outputDirectory, value) ); }
}
// `SetValue` calls `PropertyChanged` and does other common-tasks.
// Repeat for other properties, like "Int32 Timeout" and "Color FontColor"
}
In the original ViewModel class there were 2 methods: ReadFromRegistry and SaveToRegistry. The ReadFromRegistry method was called by the ViewModel's constructor, and the SaveToRegistry method was called by MainWindow.xaml.cs's code-behind like so:
private void Settings_Click(Object sender, RoutedEventArgs e) {
SettingsViewModel model = new SettingsViewModel(); // loads from registry via constructor
SettingsWindow window = new SettingsWindow();
window.Owner = this;
window.DataContext = model;
if( dialog.ShowDialog() == true ) {
model.SaveToRegistry();
}
}
...but this seems wrong to me. I thought a ViewModel should consist only of an observable data bag for binding purposes, it should not be responsible for self-population or persistence, which is the responsibility of the controller or some other orchestrator.
I've done a few days' worth of reading about MVVM, and none of the articles I've read mention a controller or where the logic for opening child-windows or saving state should go. I've seen some articles that do put that code in the ViewModels, others continue to use code-behind for this, others abstract away everything and use IService-based solutions, which is OTT for me.
Given this is a conversion project where I'll convert each Window/View individually over-time I can't really overhaul it, but where can I go from here? What does a Controller in MVVM look-like, exactly? (My apologies for the vague terminology, it's 3am :) ).
My aim with the refactoring is to separate concerns; testability is not an objective nor would it be implemented.
I personally disagree with putting much in my ViewModels beyond the stuff that is pertinent to the View (it is, after all, a model of a View!)
So I use a Controller paradigm whereby when the View tells the ViewModel to perform some action (via a Command usually) and the ViewModel uses a Command class to perfrom actions, such as saving the data, instantiating new View/Viewmodel pairs etc.
I also actually separate my ViewModel and ViewData (the ViewModel 'contains' the ViewData) so the ViewData is puirely dealing with the data, the ViewModel with some logic and command handling etc.
I wrote about it here
What you need is called Commanding in WPF.
Basically you bind Button.Command to a ICommand property in your ViewModel and when Button is clicked you get a notification in ViewModel without using code behind and casing DataContext or whathever hacks you tried.
http://msdn.microsoft.com/en-us/library/ms752308.aspx
Right, sticking with the MVVM focus for the minute, there are a small number of scenarios where threading may occur:
As usual, for simplicity we have a Model class, ViewModel class and View class.
The Model has a Collection and a string property.
1) User triggers long running background task. View triggers ViewModel. Can easily be managed by ViewModel using, for example, BackgroundWorker
2) Thread updates Model, ViewModel notified by Model of changes.
Previously we've discussed using INotifyChanged to notify changes from Model to ViewModel. The DependencyProperty system appears to marshal these to the correct thread for you.
For ObservableCollections this does not work. Therefore should my model's public face be single threaded (Don't like, why should the Model know about threads) or would I replicate some parts of the Model (For example the Collection above) in the ViewModel to ensure that amendments are made on the correct thread?
I think I've sort of answered my own question. Perhaps not. My Model does know about threads, so perhaps it's only polite to markshal them back using the IMarshalInvoker idea mooted earlier by Colin?
Some of my problem here is that I consider MVVM to be yet another MVC variant, and historically I've been happy to use terms like MVP, MP, MVC pretty much interchangeably because I knew what worked with the GUI technology (usually winforms) on the V end. When I say MVVM I'm specifically looking for practical advice on what works for WPF and WPF specific foibles. I hope that explains the nature of my questions and why I'm asking them.
I don't think it's a very good idea to go all-out and implement collections in your Model as ObservableCollection, as this is "polluting" your Model in a way that's only useful to WPF.
INotifyPropertyChanged is OK because:
There are many scenarios where having the ability to "listen in" is useful.
It can be utilized from pretty much any .NET code, not just WPF.
It doesn't give you any trouble if you want to serialize your Model.
So, I suggest to not have your model know about threads. Make your ViewModel know about threads, like this:
class Model {
List<Widget> Widgets { get; private set; }
}
class ModelViewModel {
ObservableCollection<Widget> Widgets { get; private set; }
ModelViewModel(Model model) {
this.Widgets = new ObservableCollection<Widget>(model.Widgets);
}
}
If Widget is a reference type and implements INotifyPropertyChanged (which would be about 100% of the time), this gets you most of the way:
Changes to any widget will be made to model itself and will reflect upon bindings immediately
Updates to the collection will reflect upon bindings immediately
There's still the problem that updates to the collection (adding and removing items) will not be made to model directly. But that can be arranged:
ModelViewModel(Model model) {
this.Widgets = new ObservableCollection<Widget>(model.Widgets);
this.Widgets.CollectionChanged += this.PropagateChangesToModel;
}
void PropagateChangesToModel(object sender, NotifyCollectionChangedEventArgs e) {
// do what the name says :)
}
Finally, you need to make ObservableCollection play well with being updated from a worker thread. This is a really common issue with WPF, and I refer you to the answer to this question for a solution: ObservableCollection and threading.
I have a few questions regarding to building WPF MVVM applications.
1) I'm using ICollectionView objects for databound controls such as ListView and ComboBox. I found this was the simplest way of gaining access to/tracking the selected item of these controls. What is the best way to replace the contents of ICollectionView? Currently I'm doing it like so:
private ICollectionView _files;
public ICollectionView Files {
get { return _files; }
}
void _service_GetFilesCompleted(IList<SomeFile> files) {
this.IsProcessing = false;
_files = CollectionViewSource.GetDefaultView(files);
_files.CurrentChanged += new EventHandler(FileSelectionChanged);
OnPropertyChanged("Files");
}
I didn't know whether it was necessary to reattach the handler every time I refresh the list of files?
2) Now that I've got my head round it, I am starting to like the MVVM pattern. However, one concept I'm not completely sure about is how to send notifications back down to the view. Currently I am doing this by binding to properties on my ViewModel. For example, in the above code I have an "IsProcessing" property that I use to determine whether to display a ProgressBar. Is this the recommended approach?
3) Following on from 2) - there doesn't seem to be a standard way to handle exceptions in an MVVM application. One thought I had was to have one method on my ViewModel base class that handled exceptions. I could then inject an IMessagingService that was responsible for relaying any error messages. A concrete implementation of this could use MessageBox.
4) I have a few tasks that I want to perform asynchronously. Rather than adding this logic directly in my service I created a decorator service that runs the underlying service methods on a new thread. It exposes a number of events that my ViewModel can then subscribe to. I have listed the code below. I understand that BackgroundWorker is a safer option but did not know whether it was suitable for running multiple asynchronous tasks at once?:
public void BeginGetFiles()
{
ThreadStart thread = () => {
var result = _serviceClient.GetUserFiles(username, password);
GetFilesCompleted(result.Files);
};
new Thread(thread).Start();
}
Finally, I realize that there are a number of MVVM frameworks projects that handle some of these requirements. However, I want to understand how to achieve the above using built-in functionality.
Thanks
If you have ListViews and ComboBoxes, you should really be considering an ObservableCollection<> to bind to these controls. Adding and removing items from the collection will automatically notify the control the property has changed.
If you're doing background processing, you can look at the BackgroundWorker or DispatcherTimer to handle updates to the UI. These both have the capability of acting on the UI thread, and can be thread safe.
To get the selected item from a combo box, expose an INotifyCollectionChanged object such as ObservableCollection and bind it to the itemsource, then create another property for the current item and binding ComboBox.SelectedItem (or ComboBox.SelectedValue if required) to it. You will need to manage the selection when updating the collection.
On the face of it, ICollectionView seems like the obvious choice but the WPF implementation really forces your hand on some threading code that you really shouldn't be troubled with.
I used ICollectionView and CollectionViewSource recently (for filtering) and have become frustrated with how many dispatcher issues have crept in. Today I am probably going to revert to the method i describe above.