I have recently been looking for a way to bind data in WinForms using MVVM.
I ended up creating a custom implementation of the MVVM pattern.
However, due to the lack of two-way binding, I have decided to give WPF a try.
I already have the Model, which encapsulates the non-ui functionality. For example the Model reads a configuration file, has a few properties, listens for incoming data on a socket, and saves incoming packets if needed.
Some of the Model's properties throws an exception if they are set out of range. I.e. the validation is done in the Model.
How is validation usually done in WPF? I have read a good deal of articles, and there seems to be some consistency in putting validation in the ViewModel. In fact, most articles only use ViewModel and View. Has the Model been buried?
Glad to see your decision to move away from custom implementations of MVVM when so much already exists that just ... works.
WPF is very strong for two way binding and that gives it its' greatest strengths.
The view model is bound to the view and acts as the mechanism to communicate with the data layer. Also Entity Framework (if you are on framework 4.0) will give you a great data layer for populating your entities in your ViewModel. This basically becomes your Model. It gives you an encapsulated form of UnitOfWork as well as Repository patterns.
While your view model in all examples are usually on a one-to-one basis, if the design calls for it you can have view models that span multiple views. I have a "menu" which displays key identifiers from each item in the list and a detail form that shows all fields for editing from the same object. So I span the view between the two.
You can hard code the view model in the xaml binding it to the datacontext or you can use Unity and inject the viewmodel into the view. Unfortunately the injection requires adding one public property for the purpose of setting the datacontext. So you'd have code like this:
public class MyView:Window
{
public MyView(MyViewModel model)
{
InitializeComponent();
ViewModel = model;
}
public MyViewModel ViewModel
{
set{ this.DataContext = value; }
}
}
So the rest is just TwoWay binding for each field and the setter can encapsulate single value editing. Your error message can even be bound to a text field on the form and it displays when the value is not null.
Also if you dig into Unity you will also get a truly great function called Event Aggregation which basically provides a vehicle for publish/subscribe of events and that ties into your ICommand implementation when getting a button click handled.
Related
I've been trying to find the correct approach for this problem I got, using Prism with Xamarin Forms:
I've a model class, Customer, that contains another class, Address as a property. In my view, I show fields from both objects. I would like to have a "save" button, that only gets enabled after you've made some changes to those models.
Now, the button is bound to a Command, with the corresponding CanSave() function, as is normal with DelegateCommands. I'm trying to find an approach where I can end up with a single IsDirty property on my view model, that gets to "true" after any changed to the underlying models.
The MVVM approach
First thing I thought was the "purist" mvvm approach. A "flat" view model, with properties for each visual element, implemented as a Prism BindableObject, where each getter/setter gets/sets values from/to the underlying model classes.
That failed though, since SetProperty<> has a ref parameter, where I can't use properties from my models.
The over-engineered approach [?]
Second thing I thought was that, if my inner models were observables themselves, I could listen for changes from all of them, throughout the tree. Which opens up a whole new world of issues. Do I register property change listeners in my View model ? Do I make inner models observables, and have the parents listen for change events on their children and propagate that ?
Won't that observable models approach quickly become event handler hell ?
The simplest thing
And last, the simplest thing possible. I have a flat observable ViewModel, that only reads/writes values to/from the actual inner hierarchical model upon read & save
What do you guys think ?
Maybe I didn't understand your question right, but I'm wondering why you limit yourself to such a small helper function like SetProperty. It has 4 Lines of code. All it does is checking for equality, setting a value and raising an event.
You could easily create another helper function like this.
MyBindableBase
protected virtual bool SetProperty<T>(Func<T> get, Action<T> set, T value, [CallerMemberName] string propertyName = null)
{
if (object.Equals(get(), value)) return false;
set(value);
OnPropertyChanged(propertyName);
return true;
}
Model
class Model
{
public string Property { get; set; }
}
ViewModel
class ViewModel : BindableBase
{
private Model Model { get; set; }
public string Property
{
get { return Model.Property; }
set { SetProperty(() => Model.Property, x => Model.Property = x, value); }
}
}
I think you can shorten the usage, if you introduce some naming rules for the mapping and/or use reflections.
Well, in the end I went for option 3, the simplest thing I could do.
I was leaning towards returning properties from my model, which would be easy, and using the nullable [?.] syntax it would be null-safe too, but I found that at times I'll have to wrap the actual model properties with something that is more UI-friendly, exposing more/different properties than my actual DB model classes.
So, I went for that, until some other complexity forces me to change my mind again :)
Thanks a lot #Sven-Michael Stübe and #adminSoftDK for the help
First note that I am not referring to any specific framework or technology like XAML.
The question is how to implement the MvvM pattern using ICommand for selection of an item in a list (=clicking a row)?
I have a view model (pseudo code):
class ListViewModel
{
// Items in the list.
public ObservableCollection<T> Items {};
// Command for item selection.
public ICommand ItemSelectedCommand
{
...
}
// Select an item in the list.
public void SelectItem(int index)
{
...
}
// The current selected item.
public T SelectedItem
{
get { ... };
}
}
How would I now connect my UI to that view model "manually"? Say, for instance in an iOS application.
I would probably have a UITableViewController, get an instance of the view model and populate the UITableView contents from it. Then I would trigger the ICommand from the RowSelected() method.
And here comes the thing I don't understand: how does the view model now know which item index was selected? I don't want to call SelectItem() because then I would not need the loosely coupled ICommand at all.
And maybe here we have to look how it is solved in XAML to understand the trick?
Coming from XAML and WPF, there are two options to forward selection changes from the UI to the ViewModel (as I understand your question, you're not asking about the other way around - feedbacking changes in the ViewModel to the UI - here):
Command with payload
The ICommands Execute method has a payload parameter. Executing a command without a payload can be done passing null:
SomeCommand.Execute(null);
In your case, it would make sense to pass the selected item as the parameter in the event handler:
vm.ItemSelectedCommand.Execute(eventArgs.SelectedItem);
or
vm.ItemSelectedCommand.Execute(myList.SelectedItem);
In the command's execution method, you can handle the parameter. Note that your ViewModel property SelectedItem is not directly involved here. If you need the selected index explicitly (which is not the case, usually), I would check the selected item's index in the Items collection.
Binding selected item of list to a ViewModel property
Option B is to 'bind' the selected item of the list to a distinct property on the ViewModel, in your case the SelectedItem property in the event handler of the list:
vm.SelectedItem = myList.SelectedItem;
The command is kind of redundant then, although you could invoke it without a payload after setting SelectedItem on the ViewModel. I would rather handle the change of the selected item in the set accessor of the property on the ViewModel.
Note: XAML and WPF come with quite a lot of infrastructure code out of the box. MVVM doesn't make sense without a proper framework to actually take care of binding UI and ViewModels in a loosely coupled way. You quickly end up with a lot of extra work and little benefit, because you're still maintaining tight dependencies. Bottom line: I recommend getting or writing a proper MVVM framework, before actually implementing it.
I have some doubts about what are the best practices for MVVM using parent-child model relations.
In that specific case there are two models (data classes) called Group and Contact. The group is containing a list of contacts. Both of them are are implementing INotifyPropertyChanged interface.
In the view, there is a treeview displaying the hierarchy using DataTemplate and the associated ViewModel contains an ObservableCollections property.
I am wondering what is the best practice design in this case.... Having one property like above in the ViewModel which is bind to the xaml or createing a ViewModel for each model (like GroupViewModel and ContactViewModel) and instead of ObservableCollections having an List.
What is the best way (design wise)? Shoudl I bind the Model or the ViewModel to the xaml?
I'm afraid, you mixed some things up. The basics of MVVM are
Model - Contains the data the application is working with. It should be kept as simple as possible.
ViewModel - Reflects the state of the application and contains the business logic. It's the business layer.
View - Interprets the ViewModel to provide a visual representation of the business layer and its state.
With this three parts, it's pretty easy to provide separation of concerns and a decoupled architecture. If you want to read more, click here.
Back to your questions:
In that specific case there are two models (data classes) called Group and Contact. The group is containing a list of contacts. Both of them are are implementing INotifyPropertyChanged interface.
That's a bit odd. Usually, you don't need to implement INotifyPropertyChanged in the model classes, since the VM should handle value changes from the view.
But it's imaginable to have that mechanism in the model layer too. But since you don't want to track changes on this layer and IMHO the VM should take care about, you don't need it.
[...] Having one property like above in the ViewModel which is bind to the xaml or createing a ViewModel for each model (like GroupViewModel and ContactViewModel) [...]
Yes, this is usually the approach. For each model class, which should be passed to the view layer, you would create a ViewModel.
[...] and instead of ObservableCollections having an List.
That's definitely a No. If you use a List<T>, the view would not be aware of the changes (add, remove) to collection.
What is the best way (design wise)? Shoudl I bind the Model or the ViewModel to the xaml?
Simply stick to MVVM. The view is aware of the VM, but the VM is not aware of the view. Additionally the VM is aware of the model, but the model isn't aware of it. That implies, that you should always bind the VM to the View.
Edit
The following is totally legit.
public class Address : ViewModelBase // implements INotifiedPropertyChanged a.s.o.
{
public string Street { /* you know what comes here */ }
public string ZipCode { /* ... */ }
public string City { /* ... */ }
/* more properties */
}
public class Person : ViewModelBase
{
public string Name { /* ... */ }
public Address Address { /* ... */ }
}
I started working with the MVVM pattern in a new project.
Everything is ok, but i came to the following problem.
The implementation looks like this:
I have a MainView, the main app window. In this window i have a telerik RadGroupPanel in wich I host the rest of the app views as tabs.
The rest of the viewModels does not know about this RadGroupPanel which is hosted in MainVIew.
How should i correctly add those views to the RadGroupPanel from the commands in the viewModels?
Thanks.
Have you considered injecting your view into the ViewModel using an interface to maintain separation? I know this breaks MVVM but I've successfully used this on a number of WPF projects. I call it MiVVM or Model Interface-to-View ViewModel.
The pattern is simple. Your Usercontrol should have an interface, call it IView. Then in the ViewModel you have a property with a setter of type IMyView, say
public IMyView InjectedView { set { _injectedView = value; } }
Then in the view you create a dependency property called This
public MyUserControl : IMyView
{
public static readonly DependencyProperty ThisProperty =
DependencyProperty.Register("This", typeof(IMyView), typeof(MyUserControl));
public MyUserControl()
{
SetValue(ThisProperty, this);
}
public IMyView This { get { return GetValue(ThisProperty); } set { /* do nothing */ } }
}
finally in Xaml you can inject the view directly into the ViewModel using binding
<MyUserControl This="{Binding InjectedView, Mode=OneWayToSource}"/>
Try it out! I've used this pattern many times and you get an interface to the view injected once on startup. This means you maintain separation (Viewmodel can be tested as IView can be mocked), yet you get around the lack of binding support in many third party controls. Plus, its fast. Did you know binding uses reflection?
There's a demo project showcasing this pattern on the blog link above. I'd advocate trying out the Attached Property implementation of MiVVM if you are using a third party control.
You can have the list of viewmodels that you need to add controls for in an ObservableCollection in your main window viewmodel. You can then bind the ItemsSource of the RadGroupPanel to that collection and use the ItemTemplateSelector and ContentTemplateSelector of the RadGroupPanel to select the right template to use based on the viewmodel that is bound.
in my ASP MVC 2 application I follow the strongly typed view pattern with specific viewmodels.
Im my application viewmodels are responsible for converting between models and viewmodels. My viewmodels I have a static ToViewModel(...) function which creates a new viewmodel for the corresponding model. So far I'm fine with that.
When want I edit a model, I send the created viewmodel over the wire and apply the changes to back to the model. For this purpose I use a static ToModel(...) method (also declared in the view model). Here the stubs for clarification:
public class UserViewModel
{
...
public static void ToViewModel(User user, UserViewModel userViewModel)
{
...
}
public static void toModel(User user, UserViewModel userViewModel)
{
???
}
}
So, now my "Problem":
Some models are complex (more than just strings, ints,...). So persistence logic has to be put somewhere.(With persistence logic I mean the decisions wheater to create a new DB entry or not,... not just rough CRUD - I use repositories for that)
I don't think it's a good idea to put it in my repositories, as repositories (in my understanding) should not be concerned with something that comes from the view.I thought about putting it in the ToModel(...) method but I'm not sure if thats the right approach.
Can you give me a hint?
Lg
warappa
Warappa - we use both a repository pattern and viewmodels as well.
However, we have two additonal layers:
service
task
The service layer deals with stuff like persisting relational data (complex object models) etc. The task layer deals with fancy linq correlations of the data and any extra manipulation that's required in order to present the correct data to the viewmodel.
Outwith the scope of this, we also have a 'filters' class per entity. This allows us to target extension methods per class where required.
simples... :)
In our MVC projects we have a seperate location for Converters.
We have two types of converter, an IConverter and an ITwoWayConverter (a bit more too it than that but I'm keeping it simple).
The ITwoWayConverter contains two primary methods ConvertTo and ConvertFrom which contain the logic for converting a model to a view model and visa versa.
This way you can create specific converts for switching between types such as:
public class ProductToProductViewModelConverter : ITwoWayConverter<Product,ProductViewModel>
We then inject the relevant converters into our controller as needed.
This means that your conversion from one type to another is not limited by a single converter (stored inside the model or wherever).