I've just finished watching "Practical MVVM by Joel Cochran" video explaining MVVM, and i didn't understand a key problem.
In the video Joel explaining that the View is unaware of the ViewModel, but still the button is bound to a command within the ViewModel, so every time the button get pressed, the command action is performed.
My question is how the View is unaware of the ViewModel if I need to specifically bind the button to the ViewModel command like:
private ICommand _searchByNameCommand;
public ICommand SearchByNameCommand
{
get
{
if (_searchByNameCommand == null)
{
_searchByNameCommand = new RelayCommand(
p => this.LoadRealEstateCollectionByName(),
p => { return !String.IsNullOrEmpty(this.SearchOwnerName); }
);
}
return _searchByNameCommand;
}
}
And in the xaml:
<Button Content="Search"
Grid.Column="2"
VerticalAlignment="Center"
Command="{Binding SearchByNameCommand, Mode=OneWay}" />
SearchByNameCommand is defined in the ModelView.
The answer is the following:
Using MVVM, a view is tightly coupled to a view-model via it's DataContext.
The reason why the view is tightly coupled to its view-model is because the view must specify the specific names of observable properties and commands that are contained within its DataContext. That function alone introduces tight coupling.
RANT:
I'm not sure if I agree with a view being completely ignorant of its view-model dependency.
Think about it. A view is bound to the state and operations of its data context (aka view-model). In other words, it is tightly coupled to the state of the view-model but not the view-model its self?
What's the point?
So how useful is it to hide the view-model from the view if the view relies completely on its Data Context (i.e. the observable state and the exposed commands of the view-model)?
I think you somewhat misunderstood what "being unaware" actually means in this context. In winforms programming, when you had a button and wanted to subscribe to the click event, you had to attach an event handler, for instance
myButton.Click += new EventHandler(myButton_Click);
As you can see, that's the tight coupling. You're coupling specific instances together.
With commands in WPF however, there's a pretty big difference, because you don't say this instance handles this. You're saying I have these methods and properties (ViewModel) and I need these things to work properly (View). You can swap instances as you like, as long as they provide the things needed for proper functioning of the view. BUT, you don't care about attaching/detaching handlers, setting manually text values etc. That's all taken care by binding that happens automatically for you. Your View doesn't really know about the specific instance. All it knows is what data and actions it works with. ViewModel doesn't really care either how those data are displayed or dealt with.
That's why I don't actually agree with Scott Nimrod's answer. This is not tight coupling, but rather loose coupling (at least in my opinion). Tight coupling would be when you couldn't change one without affecting the other and that's obviously false in MVVM. That's the point actually, to have things coupled as least as possible. If you want to see tightly coupled components, look at winforms.
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'm working on PRISM application with modules, MVVM and so on. I understand PRISM pretty good now and I understand value of MVVM. All those things good to deliver business value which comes from testability, "uniformity" and so on.
But now I'm stuck with certain interaction issues. I already spent hours and hours trying to see how I set focus in Silverlight via MVVM. All this additional behaviors, attached properties, triggers. It just seems like bunch of junk code with MVVM being root cause.
For example, I need to create Lookup control which is basically textbox with button and popup window. This control itself needs lot of focus control, it needs to overlay view over parent (popups) and so on. It seems to be pretty easy to create it with code-behind, stick it into separate library and move on. My business forms will use this control inside my nice MVVM PRISM.
So, question is.. Is it justified to use code-behind in isolated islands like controls and keep MVVM and TDD for actual code that brings business value?
Is there line where you say "MVVM is not going to be used here" ?
I see absolutely nothing wrong with using Code Behind providing that the code is related to view-specific properties, such as setting Focus. Your ViewModel should never need to know about or care who or what has focus, since that is a View-Specific concept.
Usually I build UserControls in two ways: they are either built for a specific Model or ViewModel, or they are meant to be generic and have their values provided by whoever calls them.
In the case of the former, such as if I wanted a SearchResultsPopup, I would build the UserControl expecting to have something like a SearchResultsViewModel as the DataContext.
For example, my UserControl would expect to find the following properties on it's DataContext, and would use them in bindings to build the View.
ObservableCollection<SearchResult> Results
SearchResult SelectedResult
bool IsOpen
ICommand OkCommand
ICommand CancelCommand
I could then use the UserControl like this:
<local:SearchResultsPopup DataContext="{Binding MySearchResultsVM}" />
In the later situation, where I am creating something generic which can be used by any Model or ViewModel, I would use custom Dependency Properties to provide my UserControl with the values it needs to bind to.
So in this example, I would have DependencyProperties for
bool IsOpen
ICommand OkCommand
ICommand CancelCommand
And my XAML would look something like this:
<local:GenericPopup local:GenericPopup.IsOpen="{Binding IsPopupOpen}"
local:GenericPopup.SaveCommand="{Binding SavePopupCommand}"
local:GenericPopup.CancelCommand="{Binding HidePopupCommand}">
<local:MySearchResultsView ... />
</local:GenericPopup>
In summary, your UserControl is either a reflection of your ViewModel (meaning it becomes a View), or it is provided values by the View. The ViewModel doesn't care either way.
I have a window made up of several user controls and was wondering whether each user control have its own view model or should the window as a whole have only one view model?
Absolutely, positively
NO
Your UserControls should NOT have ViewModels designed specifically for them. This is, in fact, a code smell. It doesn't break your application immediately, but it will cause you pain as you work with it.
A UserControl is simply an easy way to create a Control using composition. UserControls are still Controls, and therefore should solely be concerned with matters of UI.
When you create a ViewModel for your UserControl, you are either placing business or UI logic there. It is incorrect to use ViewModels to contain UI logic, so if that is your goal, ditch your VM and place the code in that control's codebehind. If you're placing business logic in the UserControl, most likely you are using it to segregate parts of your application rather than to simplify control creation. Controls should be simple and have a single purpose for which they are designed.
When you create a ViewModel for your UserControl, you also break the natural flow of data via the DataContext. This is where you will experience the most pain. To demonstrate, consider this simple example.
We have a ViewModel that contains People, each being an instance of the Person type.
public class ViewModel
{
public IEnumerable<Person> People { get; private set; }
public ViewModel()
{
People = PeopleService.StaticDependenciesSuckToo.GetPeople();
}
}
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
To show a list of people in our window is trivial.
<Window x:Class="YoureDoingItWrong.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:l="clr-namespace:YoureDoingItWrong"
Title="Derp">
<Window.DataContext>
<l:ViewModel />
</Window.DataContext>
<Window.Resources>
<DataTemplate DataType="{x:Type l:Person}">
<l:PersonView />
</DataTemplate>
</Window.Resources>
<ListView ItemsSource="{Binding People}" />
</Window>
The list automatically picks up the correct item template for the Person and uses the PersonView to display the person's information to the user.
What is PersonView? It is a UserControl that is designed to display the person's information. It's a display control for a person, similarly to how the TextBlock is a display control for text. It is designed to bind against a Person, and as such works smoothly. Note in the window above how the ListView transfers each Person instance to a PersonView where it becomes the DataContext for this subtree of the visual.
<UserControl x:Class="YoureDoingItWrong.PersonView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel>
<Label>Name</Label>
<TextBlock Text="{Binding Name}" />
<Label>Age</Label>
<TextBlock Text="{Binding Age}" />
</StackPanel>
</UserControl>
For this to work smoothly, the ViewModel of the UserControl must be an instance of the Type it is designed for. When you break this by doing stupid stuff like
public PersonView()
{
InitializeComponent();
this.DataContext = this; // omfg
}
or
public PersonView()
{
InitializeComponent();
this.DataContext = new PersonViewViewModel();
}
you've broken the simplicity of the model. Usually in these instances you end up with abhorrent workarounds, the most common of which is creating a pseudo-DataContext property for what your DataContext should actually be. And now you can't bind one to the other, so you end up with awful hacks like
public partial class PersonView : UserControl
{
public PersonView()
{
InitializeComponent();
var vm = PersonViewViewModel();
// JUST KILL ME NOW, GET IT OVER WITH
vm.PropertyChanged = (o, e) =>
{
if(e.Name == "Age" && MyRealDataContext != null)
MyRealDataContext.Age = vm.PersonAge;
};
this.DataContext = vm;
}
public static readonly DependencyProperty MyRealDataContextProperty =
DependencyProperty.Register(
"MyRealDataContext",
typeof(Person),
typeof(PersonView),
new UIPropertyMetadata());
public Person MyRealDataContext
{
get { return (Person)GetValue(MyRealDataContextProperty); }
set { SetValue(MyRealDataContextProperty, value); }
}
}
You should think of a UserControl as nothing more than a more complex control. Does the TextBox have its own ViewModel? No. You bind your VM's property to the Text property of the control, and the control shows your text in its UI.
MVVM doesn't stand for "No Codebehind". Put your UI logic for your user control in the codebehind. If it is so complex that you need business logic inside the user control, that suggests it is too encompassing. Simplify!
Think of UserControls in MVVM like this--For each model, you have a UserControl, and it is designed to present the data in that model to the user. You can use it anywhere you want to show the user that model. Does it need a button? Expose an ICommand property on your UserControl and let your business logic bind to it. Does your business logic need to know something going on inside? Add a routed event.
Normally, in WPF, if you find yourself asking why it hurts to do something, it's because you shouldn't do it.
This is not a yes or no question. It depends on whether having extra view models affords you better maintainability or testability. There's no point adding view models if it doesn't gain you anything. You'll need to gauge whether the overhead is worth it to your particular use case.
[should] each user control have its own ViewModel or should the window as a whole have only one ViewModel?
Unfortunately, the highest-voted answer to this question is misleading, and based on comments I've exchanged in other questions, providing poor guidance to people trying to learn WPF. That answer replies:
Your UserControls should NOT have ViewModels designed specifically for them.
The problem is, that's not the question that was asked.
I would agree with the general sentiment that when you write a UserControl, the public API of the control should not involve creating also a view model type that is specifically designed to be used for that control. The client code must be able to use whatever view model it wants.
But, that does not preclude the idea that "each user control [might] have its own ViewMomdel". There are at least two obvious scenarios I can think of where the answer to that would be "yes, a view model for each user control":
The user control is part of a data template in an items presenter (e.g. ItemsControl). In this case, the view model will correspond to each individual data element, and there will be a one-to-one correspondence between the view model object and the user control that presents that view model object.In this scenario, the view model object is not "designed specifically for them" (so no contradiction with the questionable answer), but it certainly is the case that each user control has its own view model (making the answer to the actual question "yes, each user control may have its own view model").
The user control's implementation benefits from, or even requires, a view model data structure specifically designed for the user control. This view model data structure would not be exposed to the client code; it's an implementation detail, and as such would be hidden from the client code using the user control. But, that certainly still would be a view model data structure "designed specifically for" that user control.This scenario is clearly not problematic at all, which directly contradicts the claim that "Your UserControls should NOT have ViewModels designed specifically for them."
Now, I don't believe it was ever the intent of the author of that answer to rule out either of these scenarios. But the problem is, people who are trying to learn WPF may not have enough context to recognize the difference, and thus may incorrectly generalize with respect to user controls and view models, based on this emphatic, highly-upvoted, and misleading answer.
It is my hope that by presenting this alternative view point as a point of clarification, and answering the original question in a less narrow-viewed way, those who found this question while learning more about WPF will have better context, and a better idea and when a view model might be implemented specific to a user control and when it should not be.
I would say that each user control should have its own ViewModel, because that would allow you to reuse the ViewModel/UserControl pair in new constellations in the future.
As I understand it, your window is a Composite of user controls, so you can always create a ViewModel that composes all the separate ViewModels for each of the user controls. This will give you the best of both worlds.
I'd be inclined toward a viewmodel.
Bear in mind that all of these patterns are designed to fragment your code to make it more maintainable in the future. Including MVVM. The view has certain responsibilities, so too the viewmodel, so too the model. A fresh developer can come in, can recognise this pattern, will have a better idea where to find and maintain things. Better than if it were a heap of spaghetti.
So, within that, if you have logic which correctly pertains to the usercontrol, which correctly belongs in the vm, then why not?
But there is a caveat here. Bear in mind what a UserControl is. It's something that is a tiny snippet of UI that can be reused from place to place. Your vm should be the same - reusable. The last thing you want to end up with is a vm which behaves one way in one scenario, and a different way in another scenario.
Note, no technology talked. I'm just talking about the logical structure of the pattern.
I guess your application is doing some sort of view composition, so if you make your user controls to have its own view model, you'll have more freedom to embed them in other host windows without changing the window global view model.
As an added bonus, your application will be more suited to evolve to a more architecturally-sound composition model as that provided by Prism or Caliburn frameworks, if the application requirements arise.
I have begun creating a wpf mvvm app. It seems a vital ingredient to the ViewModel is a bunch of ICommands to have a loosely coupled way of allowing the view to interact with the viewmodel.
My question is this, why can't I bind directly to a method?
I have used Josh Smith's RelayCommand implementation of ICommand that allows you to inject delgates into an ICommand object, but really, is there some easier way to allow a button push to call a method in the viewmodel?
I'm new to MVVM, I believe I need some enlightenment
You can't bind directly to a method because Button (for example) doesn't have a property that accepts a delegate. Instead, it has a Command property of type ICommand. A RelayCommand (aka DelegateCommand) is just an ICommand that wraps delegates.
I see no technical reason why it wouldn't be possible for the view to bind to specific methods on the view model by way of a markup extension:
<Button Command="{ViewModelMethod SomeMethodName}"/>
However, this would be slower and would increase the coupling between the view and view model. If the view knows only about a property on the view model of type ICommand, the implementation of that command could change completely (or methods could be renamed) without the view being aware.
I completely disagree.
The speed of invocation bears no relevance: commands are user interactions, they never require speed.
Argument about coupling is flawed too. How come {Binding MyProperty} is not coupling but {ViewMethod MyMethod} is?
Requirement of having specially crafted 'Commands' to be wrapped around methods is a silly one. Commands might be useful implementation under the cover, but we already have methods in C# and replacing them with something big and bulky is not right.
And that thing about MarkupExtension and Binding, it really is difficult. But it can be done. Actually, it is done, you can have a look at MethodCall project on CodePlex:
http://methodcallthing.codeplex.com/
You can use binding to choose 'this' for the method, and can use binding to fetch arguments. And all those are live, i.e. being calculated at the time the command is invoked. Another bonus feature is push-out result of method call, you can use binding for that too (OneWayToSource).
ICommand gives you CanExecute, which is needed for control enabling. A simple delegate does not. ICommand is the way to go.
Apparently Microsoft needed a Command to be something first-class, probably because they felt having the CanExecute was necessary for most applications. I disagree and think the CanExecute should have just been another DependencyProperty that you would bind to a property of your viewmodel, but hey, what do I know?
Possibly they also thought that there was a need to decouple the implementation of a command from the control's datacontext. Yet again this seems unnecessary to me because the logic should live near the data that is being operated on, as is a fundamental principal of OO.
Personally I avoid using commands in MVVM because of the mess you have to create to implement them. I just let the view's code-behind delegate events up to the viewmodel.
Due to the way in which the title of this question is worded, readers might arrive here looking for an alternative to ICommand, instead of just a way to bind a UI action directly to a method of a viewModel. (Which is of little value, since it leaves open the question of what to do with the 'CanExecute` part.)
The use of ICommand is problematic in and of itself because it is defined in Windows.Input, which means that in order to declare ICommands in your ViewModels you have to reference WPF and the kitchen sink from within your application logic, and once you have done that, any noob might notice that MessageBox and a vast array of other GUI functionality is available, and might start making use of it, resulting in a terrible mess of mixed application logic and presentation logic.
So, if you want to get rid of using System.Windows, then you need to get rid of ICommand, and if you want to get rid of ICommand, then you might be happy to know the following:
WPF (specifically, the XAML designer) does not require your viewModels to statically expose instances of the ICommand interface.
By statically here I mean that the designer does not need to be able to prove, during design time, using reflection, that your command objects implement the ICommand interface; instead, WPF checks at runtime to make sure that UI actions are bound to objects which do in fact turn out to implement ICommand.
So, in your viewModels (application logic) instead of the ICommand interface of WPF you can be using some Command interface of your own device, and all you need to ensure is that the class that you will be instantiating at runtime to implement your Command interface also implements ICommand to keep WPF happy. This way you can avoid including ICommand from within your ViewModels, and subsequently you might be able to avoid having to reference System.Windows in your application logic.
I've decoupled events in this WPF application in the following way.
What is the best way to continue decoupling?
Shell.xaml:
<Button x:Name="btnProcess"
Content="Process"
Margin="10"/>
Bootstrapper.cs:
public void Run()
{
Shell shell = new Shell(new Customer());
shell.Show();
}
Shell.xaml.cs:
public Shell(IPerson person)
{
InitializeComponent();
btnProcess.Click +=new RoutedEventHandler(person.Process);
}
Customer.cs:
public class Customer : IPerson
{
public void Process(object sender, RoutedEventArgs e)
{
Button theButton = (Button)sender;
theButton.Content = "Customer processed.";
}
}
The above code successfully decouples the view Shell from the model Customer:IPerson so that I can swap in e.g. a model Employee:IPerson etc. which handles "Processed" in its own way. That was the first goal.
But now:
how do I decouple the Processed method from talking specifically to a Button, so that it could also talk to a MenuItem or a ListView which fires the event in the view and so that it doesn't even have to be an element at all that calls it, e.g. a unit test class?
how do I alter other elements of the view other than the sender (Button), e.g. how would I alter the status bar in Shell? I see two ways:
I could either build a container which holds all views and inject the container in the Customer upon creation, then the customer can look in the container and manipulate the calling view anyway it wants (although I would have to somehow match the view that sent the event and the view in the container as the same one)
I could somehow send the whole view (Window object) to the Model with the eventargs when firing the event, although the Model would need some way of knowing (via interface) what kinds of regions were available to manipulate at runtime
How would you continue this application in the direction of a more decoupled design?
What pattern is this actually, e.g. MVC, MVP, MVVM? I only see a view (Shell) and a Model (Customer).
How would a Presenter fit in?
How would a ViewModel fit in?
How would a Controller fit in?
I suggest you to implement your event handling using commands instead of classic events.
Its very easy in WPF because the command pattern is already implemented, and you can tell all of your UI inputs (button, menu item...) that their command is [name of your command] and handle all of them in one place.
Cameron MacFarland did a good job here, but I can add a little.
When following M-V-VM, the tools in your box for decoupling are data binding, commands, attached behaviors and interfaces. Data binding should be self evident. You've already gotten a good description of commands, but I'd suggest you avoid RoutedCommand and stick with an ICommand implementation. Attached behaviors are attached DependencyProperty's that subscribe to events on the element they are attached to, and in this scenario would be used to relay event handling to the ViewModel. Interfaces give you the greatest flexibility, but you have to work out how to pass the interface to the ViewModel. The best way to learn all of this right now is to Google and to look at existing M-V-VM frameworks. Here's a list of frameworks:
Prism/Composite WPF (http://www.codeplex.com/CompositeWPF). This one comes from the Microsoft Patterns & Practices group. Lots of good stuff here, but one of the examples of the three things above that you can learn from here is how to use ICommand. Prism includes a DelegateCommand that implements ICommand and simplifies using commands from a ViewModel in M-V-VM.
Caliburn (http://www.codeplex.com/caliburn). Recently released, one of the key things you can learn from this one is how to use attached behaviors, which this library uses for it's "Actions".
Onyx (http://www.codeplex.com/wpfonyx). Disclaimer: I'm the author of this one. This one hasn't been released yet, though the current alpha source is available. This one provides a novel solution to the problem of how to provide interfaces to your ViewModel.
As Chen suggests, i'd look into the Command pattern: Routed commands
A working example from which i learned a lot can be found on Jaime Rodriquez his blog: Southridge
how do I decouple the Processed method from talking specifically to a Button
Commands. Put a command in the IPerson interface and call that command from the Shell's xaml.
how do I alter other elements of the view
Properties and Binding. If you have a property showing the state (processed/not processed) then you can use binding to display that property directly in the xaml.
How would you continue
I'd head more down the MVVM path by creating a ViewModel between the Shell and the IPerson. The ViewModel is designed to have 1) The properties needed for bindings, and 2) any Commands that need executing. The ViewModel is designed to provide the UI with what it needs from the Model.
What pattern is this
Currently? Nothing. I see only two objects, the View and the Model. You don't have a Presenter, Controller or ViewModel.
For WPF I prefer ViewModel. See this question for more info on MVVM.