I know this is a vague question, but I was so fixated in MVP design, for years, I decided to keep myself up to date and decided to venture to MVVM architecture design, I've been reading alot of blogs, samples and stuffs about the Stream/Observer pattern that MVVM follows, but what is not clear with me(cant find very very simple code) how does MVVM handle ui-events? such as onclick? in MVP, the view and the presenter has a two-way contract to handle such thing
// called by view
presenter.onViewButtonClicked
void onViewButtonClicked() {
// do something here that business logic requires
view.doSomethingAfterPresenterReceivedClickEvent()
}
I know that View in MVVM subscribe's to ViewModel that when something happened to the data(Model) View will react to it
now, how can I tell ViewModel that I clicked something? ( PS : I know that I have to subscribe to ViewModel to listen to any changes when I clicked something ), I just need some guidelines and examples how can I tell VM that I did something intentionally.
I read Microsoft's MVVM documentation and it says something about iCommand, a contract-like something to tell MVVM a UI-event occurred.
would anyone enlighten me please... Thanks in advance
Edit: I forgot to mention, Im not using DataBinding, and due to fair pros and cons, I decided not to.
I am truly not an MVVM expert, but from my knowledge:
The main difference between MVP and MVVM is that in MVP, there is a two way connection between the view and the presenter, which means that the presenter knows about the view (interface) and the view knows about the presenter (interface).
In MVVM on the other hand, this connection is only one way, which means that the view knows about the viewmodel, but the viewmodel doesn't know about the view (since the connection from the viewmodel to the view is handled via observed data).
This allows the viewmodel to be independent of any view or view implementation and allows a single viewmodel to be used by multiple views.
So to (finally) answer your initial question: the way 'onClick' events are handled is basicly the same in MVP and MVVM .. the view notifies the presenter / viewmodel about the event and then:
the presenter sets up the data in the model and calls the according methodes on the view (in MVP)
the viewmodel sets up changed data which automatically triggers a reaction on the view since that data is observed (in MVVM)
Hope this helps :)
Related
We are using Avalonia and ReactiveUI but have run into an issue. Our Model will be updated by an asynchronous thread and we're trying to figure out how to tie it (bind it) correctly to the View. It seems in the MVVM way of thinking the View doesn't interact directly with the Model, only the ViewModel. So do we need a double binding where the ViewModel binds to the Model and the View binds to ViewModel? If so how can this be done?
As a first try our Model inherits from INotifyPropertyChanged and our ViewModel subscribes to it's PropertyChanged event. However, we have to manually add code to switch between all of the possible properties of our Model to update our ViewModels correct property (and thus the View using this.RaiseAndSetIfChanged). It seems like there should be a better way...
Please, excuse the simple question but we are new to MVVM.
Lets say that on all my views, or generally at any time in my app, I want to be able to show an error message popup, and it always looks the same. How do I do that?
First thought is having all my view models extend a base view model which facilitates these things, but after that, do I have this base view model actually create the UI widgets and display them?
thanks,
Mark
If you've got some common functionality that you want to provide across a range of views, then you can implement a base class that inherits from the PhoneApplicationPage, and then derive all your classes from that class instead. The XAML for your pages then looks like this:
<local:BasePage xmlns ...
xmlns:local="clr-namespace:MyNamespace"
x:Class="MyNamespace.MyPage">
However, you will not be able to define common UI components in the XAML for your base page. If you wanted to have common UI components you would have create them manually in the code-behind for the base page, perhaps in a handler for the Loaded event, but I think a better solution would be to provide your common UI in a UserControl, which you then add to each of your pages.
If you want to show a Toast or Message Box, then I would recommend the ToastRequestTrigger and MessageBoxRequestTrigger from the Silverlight Toolkit as described in the patterns & practices WP7 Developer Guide.
you could probably define an event on base view model, which is fired inside view model whenever an error occurs, then in view, you can subscribe to this event and display the popup. You can carry error context in EventArgs of the fired event.
Additionally you could unify the logic for displaying the popup but that's probably another story :)
This is testable and nicely decoupled from the view.
Hope this helps,
Robert
The Data Presentation Widgets in GWT 2.1 seem to have it all sewn up: model, view and presenter. So how does all of this data presentation goodness fit in with MVP? For example; how might I associate presenter (aka Activity) instances with the nodes of a CellTree? And is that even something that I should be trying to do?
EDIT (elaboration):
Where does the TreeViewModel belong? Is it rightly part of the View, or part of the Presenter? And how does one obtain a reference to the ListDataModel for a sub-branch of the tree?
It's OK to give your view a reference to your presenter, and vice versa. If your CellTree needs access to your presenter, define a function like setPresenter in the CellTree.
Another solution would be to create EventHandlers that attach to your view, and then have your presenter listen for those events and respond by calling into the interface of your view. Less coupled, more verbose. I like to create generic interfaces for both my Presenter and my View to keep them totally separate but still avoid having to deal with EventHandlers.
I am doing a silverlight using the MVVM model, and i am finding it hard to do the events handling via MVVM especially that the events handlers are doing lots of changes in the view like enabling and disabling buttons, update media element functions and position. I am still new to the MVVM and i can't Imagen how can i do this. does anyone already know good article to start with or simple approach to understand :) I'll reply with what i may find interesting while i do my search as well. Thanks
1) Understand that there are different "flavors" of MVVM. Strict/hardcore MVVM patterns, although theoretically desires, isn't necessary.
2) Many view events can be handled via Commands. WPF supports this, and i believe Silverlight 4 does as well. A simple view-event to start with would be Button clicks. This allows you to handle the event in the ViewModel (instead of the View's 'code-behind').
3) For things like enabling/disabling view controls/states via the MVVM model, here is an example/explanation:
Xaml controls (say, a Button) is Data-Bound to the ViewModel for whatever property
(in this case, it will be the button's IsEnabled property).
Your ViewModel has an IsButtonEnabled property.
Whenever you change this property in the VM, raise the PropertyChanged notification, and you will see the binded result in the view (the button's IsEnabled state will be updated).
ps - you can do many things via VM properties in this manner: from text, to various property states, color, you can even play animations in the property setters/getters....etc.
Cheers
I'm using MVVM in a WPF app. I'm very new to both. Let me state that I am not a purist in the MVVM pattern, I am trying to use as many best practices as I can but am trying to make what I think are reasonable compromises to make it work in our environment. For example, I am not trying to achieve 0% code in my View code-behind.
I have a couple of questions about best practices.
1) I understand I don't want my VM to know about the attached View, but is it reasonable for the View to have a reference to its VM?
2) If a control in a View opens another View (such as a dialog) should I handle this in the View? It seems wrong to handle it in the VM since then the VM has some knowledge of a specific View.
1) The View has definitely a reference to the ViewModel through the DataContext. And you are allowed to cast the DataContext in your View:
public class ShellView : Window
{
…
public ShellViewModel { get { return DataContext as ShellViewModel; } }
This isn’t a violation with the Model-View-ViewModel pattern.
.
2) You are right. A ViewModel shouldn’t open another View. A better approach is to use Controllers. They are responsible for the Workflow of an application.
If you are interested in more detailed information then you might have a look at the WPF Application Framework (WAF).
1) Here are two simple practices for View's "knowing about" a ViewModel. It's reasonable for a View to know about a ViewModel (for Data Binding) -- but you may not need it in your case. See if either of these approaches help solve your problem. There are other ways, but these should be simple enough:
public View(ViewModel vm)
{
View.DataContext = vm;
}
public Bootstrapper(View v, ViewModel vm)
{
v.DataContext = vm;
//or, if you want it to have no parameters
View v = new View();
ViewModel vm = new ViewModel();
v.DataContext = vm;
}
The first option isn't bad if you have a service location tool, but there is a flavor of MVVM that doesn't like any code in the View's Code-Behind. The second option isn't bad either, should be simple enough for your task.
2.) This question can be a bit of a sticky point in MVVM design. If we are talking about a general Win32 MessageBox, I will often separate that logic into an additional object and put it in the VM. This way tends to a little more clear. (For example, I have selected an item in a ListBox, I have attached a Delete ICommand to that action, and in my ViewModel when this ICommand is Executed, I will poke my MessageBoxObject to ask if the user "wants to really delete" this item). More advanced "Dialogs" would use additional ViewModels and DataTemplates for those ViewModels. I prefer the Mediator approach.
1). The view will need a reference to the view model at some level, since the viewmodel will act as the view's datacontext.
2) One way to handle this is to have a generalized viewmodel representing a dialog, that is owned by the main viewmodel (the one being used as the views datacontext.)
You can use a command to crate a new instance of a dialog viewmodel, which will have a corresponding datatemplate defined in your resources. This template will be set to bind to the dialogviewmodel type.
Quite late, but I think this is tricky enough to deserve lots of different perspectives.
I understand I don't want my VM to know about the attached View, but
is it reasonable for the View to have a reference to its VM?
As already answered, a proper View-ViewModel arrangement involves the ViewModel being assigned as the View's DataContext property. That allows DataBindings to be "automagically" established from declarative XAML, or fine-tuned via code behind.
Sometimes, you'll be tempted to write, in your code behind, something like this:
var dc = DataContext as CleverViewModel;
CleverViewModel.CleverProperty.Add(someValue); // just a simple example
I believe the proper way to achieve this sort of things is NOT to cast DataContext, but instead:
Have some dedicated control in View, for example an ItemsControl with its ItemsSource two-way databound to some property in viewmodel:
<ItemsSource x:Name="cleverControl" Visibility="Collapsed" ItemsSource="{Binding CleverProperty, Mode=TwoWay}"/>
Cast the bound property instead of the whole ViewModel, in code behind:
var collection = (ObservableCollection<double>)cleverControl.ItemsSource;
collection.Add(someValue);
Note the important difference: the second approach in this example doesn't require the View to know the ViewModel type, it only needs a property named CleverProperty of type ObservableCollection<double>. This allows me to have polymorphic or even duck-typed ViewModels.
If a control in a View opens another View (such as a dialog) should I
handle this in the View? It seems wrong to handle it in the VM since
then the VM has some knowledge of a specific View.
This shouldn't happen in strict MVVM, and its not difficult to avoid using DataTemplates. DataTemplates map a given type of DataContext to a given type of view, so anytime the datacontext of a ContentControl changes, its display also changes, provided that you have a DataTemplate for that type:
A control in the view could send a command to the ViewModel, which in turn would update some of its own properties, that would be reflected by the view.
A View could contain another View, outside the knowledge of the ViewModel. In this case, the code behind can manipulate the datacontext of the contained view.
There are more subtleties, but I have been using this approach with good results. Hope this helps someone.
Build Your Own MVVM Framework
I found the approach suggested by Rob Eisenberg very interesting.
Key points:
Convention over configuration
ViewModel first
Which is very similar to ASP.NET MVC philosophy.
I highly recommend watching the video.