I develop WPF MVVM application that uses class which inherits from TriggerAction<UIElement> base class.
public class DropTrigger : TriggerAction<UIElement> {...}
This class handle drop files event and should pass the list of files to the ViewModel bounded class.
In this case, should the DropTrigger class be in View or ViewModel?
If it should be in the view (like I think), how can I execute methods in the MVVM bounded class from DropTrigger class?
Thank you !
I cannot give you a definitive answer without seeing more of your code. The most likely case is you would have an ICommand dependency property on your DropTrigger that you bind to a ViewModel property, then you pass the files in the CommandParameter.
The Trigger is, like the behavior, neither View nor ViewModel. Create a separate project folder containing these classes.
Related
I have a View that contains a GridView object and a ViewModel that the View represents. Now, I'd like to override the controls in that ViewModel so that I keep the same GUI but with different business logic (i.e. contained within the ViewModel). What's the proper way of doing that?
I'd assume it is not as simple as extending the ViewModel since there's the issue with its GUI being represented in the View (which has a XAML component).
Any thoughts?
Thanks.
Edit: Fixed typo
What I tend to do, is create a Base ViewModel Class with the standard UI and Control logic in it.
I then set whichever Functions / Subs I want to control individually to overrideable. But I populate them up with default code, such as The standard Form State (Editting/Adding/Deleting) code. Any I want to force to be Overridden are set to Must Override of course.
Then, I create a Individual View-Based ViewModel, inherit from the Base ViewModel Class, override the methods I require, and set this Individual ViewModel to be the DataContext for the View.
You can switch in which ever ViewModels you like using this method, so long as they all inherit from your base ViewModel class.
I hope this helps!
Please, help me to understand one thing in the MVVM pattern:
For example, I need to display cities on a map.
In ViewModel I have ObservableCollection, that binded to a View ItemsSource.
ObservableCollection contains objects with type "City".
Must "City"-class be inherited from ObservableObject (I use MVVM Toolkit)? Or I should create a wrapper class, inherit it from ObservableObject, in ViewModel create new wrap-objects with data from "City"-objects and add them to the collection?
Thank you!
Assuming that your City class is in your model, and you actually need to know about changes to properties on the city object - then you should create a wrapper for it (i.e. CityViewModel). Your wrapper should listen to events that notify of any changes to the City class, and fire off the relevant Property Change notifications.
Model classes should be designed to fit with the model and should not change to suit your view - the point of having a ViewModel in the first place is to abstract your model from your view. The model should know nothing of the View.
If the properties of your City class dont change, or you dont care if they don change (and you are not a purist) then you could just expose it directly - without inheriting ObservableObject.
(Although I dont use MVVM toolkit, I cant see why in general you would need to inherit ObservableObject just because you are storing the City objects in an ObservableCollection).
The purist view however, is to wrap everything that you bind to and never expose anything from the model directly to the view.
ObservableCollection or ObservableObject has no relation with MVVM model. You can create a MVVM based application without ObservableCollection and ObservableObject (ObservableObject are used when you need to change the values of property of your class but if your application is readonly you dont even need it).
MVVM -
M-Model (business layer) , V-View (GUI), ViewModel- (Context of GUI).
When XAML works on binding. You must need a notification mechanism to notify GUI that something is changed. Now if a collection is changed means you added or removed an item from collection, you need to raise a notification which you dont need if you are working with ObservableCollection. Similarly, if your class City has a property Population which when changes need to notify GUI, that's why need to make an ObservableObject.
Hope it helps..
I had asked a question about mapping multiple view models to a single view (here). I got some good answers but I am still having some trouble applying what I learned there to my particular case.
A brief recap: I want to create a base ItemViewModelBase class that exposes properties that my view will bind to. Then I will create two specific view models, PeopleViewModel and CarsViewModel. Both of these inherit from ItemViewModelBase and implement the appropriate properties. Now, I want to be able to create a single view that will display the appropriate info based on which view model it is bound to. Since both the PeopleViewModel and CarsViewModel expose the same properties and I want the view to look the same for both of these, I only need one view.
One of the answers in my previous question suggested using a DataTemplate:
<DataTemplate DataType="{x:Type ItemViewModelBase}">
//some user control
</DataTemplate>
I am new to using DataTemplates with MVVM (and MVVM in general) so I have a few questions:
Right now ItemViewModelBase is an abstract class and I defined the appropriate properties (ItemName, Items, etc.). My Items property is an ObservableCollection:
public virtual ObservableCollection<???> Items { get; set; }
What would I put as the collection type? The classes that derive from this base class will have different lists (Person, Car). Is the base view model the right place to put the property? I do want all of the derived classes to implement it so it seems so. ANd it doesn't make sense to have Person and Car extend some base object.
Let's say I do not need any customization of my views. I would only need one View in that case. It is not clear how I would set this up. Should I create a DataTemplate for ItemViewModelBase and a single view (user control) to represent it? Right now I use Unity to register my view models and when the view is created, the view model gets injected in the view. How would I differentiate between the different view models when I try to create the view?
Basically, I don't know how to show the appropriate view when using DataTemplates. In my application right now I have a window that contains a tab control defined like this:
<Grid>
<TabControl TabStripPlacement="Left" ItemsSource="{Binding TabItems}"/>
</Grid>
The TabControl's style contains the below setters:
<Setter Property="Header" Value="{Binding Header}"/>
<Setter Property="Content" Value="{Binding Content}"/>
TabItems is defined like so:
public ObservableCollection<ConfigTabItem> TabItems { get; set; }
TabItems.Add(new ConfigTabItem() { Header = "People", ResolveView = (Func<object>)(() => (PeopleView)Container.Resolve(typeof(PeopleView), "peopleView")) });
TabItems.Add(new ConfigTabItem() { Header = "Cars", ResolveView = (Func<object>)(() => (CarsView)ConfigurationModule.Container.Resolve(typeof(CarsView), "carsView")) });
So as it stands right now, I have separate view models and views for People and Cars, and whenever a tab is clicked, the appropriate view is resolved.
I want to change this setup to use the above mentioned base view model class and single view with DataTemplates.
Any sample code/sample would be greatly appreciated, showing a base view model class, some other view model classes extending that base view model, and then being able to show the appropriate view based on the view model (where there is only one generic view).
You are asking too much in a single question IMHO. Try getting your code to work with or without DataTemplates (make it hacky if you need to) and then focus on ONE area of the code that you think needs refinement, and post a question about how to solve a specific problem. I started typing out an answer and it quickly got too complicated to articulate an overall recommendation.
I'm not sure you got good advice in the other question about DataTemplates. I'm also very concerned about how you have the ConfigTabItem set up--it seems to be a parent viewmodel that uses the container (directly, which is not a good practice) to resolve a view, which presumably also has its own viewmodel. This seems needlessly complicated.
Anyway, again, try to distill it down to a few focused questions. In the case that any of it is helpful, my original start at an answer is below (unedited):
First, I'm not sure I understand the answer you were given in your previous question that talks about DataTemplates. If you will always be binding to a ItemViewModelBase, I'm not clear on why you need to specify a DataType (or even a DataTemplate). This is not to say that using a DataTemplate is a bad idea, but I'm not sure I see the necessity of it in this case.
I'm also going to say that I'm not sure I see the necessity of inheritence either. Databinding works at runtime, and outside of switching a DataTemplate based on VM type (which, as I said, I don't think you need), the view doesn't care what it is binding to, so long as the properties it is looking for are found at runtime.
So as a general matter, I would start with ONE concrete implementation of your view model. Get it to bind correctly, and then determine which parts of it you can abstract into a base class or interface if that's the approach you want to take. It's not necessary, but might help make the requirements for binding easier to "enforce"--for example, using the base class or interface will restrict you (or someone else) from changing the name of a property needed for binding.
What would I put as the collection
type? The classes that derive from
this base class will have different
lists (Person, Car). Is the base view
model the right place to put the
property? I do want all of the derived
classes to implement it so it seems
so. ANd it doesn't make sense to have
Person and Car extend some base
object.
If you are going to use a base class or interface for your VM and you want the collection to be a part of it, it can simply be of type ObservableCollection<object>. The items added to it will need to all have property names that match what you reference in your XAML. So you can't have "PersonName" and "CarName" properties if you want only one view; you would need to use something more general like "ItemName" (unless you use DataTemplates with DataTypes--this is where that actually would be useful). Again, you don't need each collection item to inherit from a base type or implement a common interface, unless (again) you want enforcement at compile time.
Look at the Architecture from Microsoft App Studio for universal apps. According to Microsofts App Studio the DataTemplates should live in a DataTemplates Subdirectory under the Views Directory. A Universal app has this directory for both the Windows UI as for the Windows Phone UI so its not in the Shared project because they are not the Same. Don't use the Converge PRISM architecture. Its completely wrong designed! That was not written with a Windows and a Windows Phone architecture in mind but like they call it Converged. It should have been completely redesigned like it works in Microsofts App Studio. Don't look for Dependency Injection its not in it and not needed. Most use Dependency Injection for stub or fake interfaces. The DataContext for design data works now so good with json data that a Dependency Injection component would be overkill.
Hello fellow StackOverflow users (or Stackoverflowers?):
I'm learning-by-coding WPF. I read several articles/saw several screencasts, and coming from a WEB dev background, I fired up VS2010 and started doing a sample application that would help me learn the basics.
I read some about MVVM too, and started using it. I set up my solution to use WPF 4.0, ActiveRecord 2.1 and SQLite, and everything went kind well. But I still have some doubts:
I created a MainWindowViewModel, and am using the RelayCommand class from here to... relay the command. Am I breaking any guidelines by having a MenuItem from the MainWindow to have its command bound to a property of this viewmodel?
This action I'm binding the MenuItem command to is going to instantiate a new ViewModel and a new View, and show it. Again, is that ok in the MVVM context?
My MainWindow will be a kind of "dashboard", and I will have more than one model attached to this dashboard. Should I just wrap all those models in a single view model?
Something like this:
public class MainWindowViewModel {
private ObservableCollection<Order> openOrders;
private Address deliveryAddress;
private Order newOrder;
/* Wrappers for the OpenOrders Collection */
/* Wrappers for Delivery Address */
/* Wrappers for New Order */
/* Command Bindings */
}
TIA!
I created a MainWindowViewModel, and am using the RelayCommand class from here to... relay the command. Am I breaking any guidelines by having a MenuItem from the MainWindow to have its command bound to a property of this viewmodel?
No, you're not breaking any guideline. It's perfectly appropriate to bind the MenuItem to a command of the MainWindowViewModel (where else would you put this command anyway ?)
This action I'm binding the MenuItem command to is going to instantiate a new ViewModel and a new View, and show it. Again, is that ok in the MVVM context?
It's perfectly fine to create a new ViewModel, of course. As for creating a new view, it depends on how you create it... you should of course never instantiate a view explicitly from the ViewModel, because it would introduce a dependency of the VM to the view.
My MainWindow will be a kind of "dashboard", and I will have more than one model attached to this dashboard. Should I just wrap all those models in a single view model?
It depends on what you mean by "wrap"... Your MainWindowViewModel could expose other ViewModels through properties, and theses VMs would be displayed in different parts of the view. If that's what you mean, yes, you should wrap them.
Adding to the Thomas answer:
I would create different usercontrols for each part of the dashboard and assign a viewModel to each usercontrol.
I created a MainWindowViewModel, and am using the RelayCommand class from here to... relay the command. Am I breaking any guidelines by having a MenuItem from the MainWindow to have its command bound to a property of this viewmodel?
No, that's exactly where you put commands.
This action I'm binding the MenuItem command to is going to instantiate a new ViewModel and a new View, and show it. Again, is that ok in the MVVM context?
It shouldn't need to know how to instantiate a new view; that's the view's job. The specifics of how to do this depend on how you're showing this new view - it could be as simple as having a ContentPresenter in the view that's bound to a property in the view model, so when you set the property (and raise PropertyChanged) the ContentPresenter renders the new object with its related DataTemplate.
Things get a little hinky if by "instantiate a new view" you mean "open a new window." There's not an especially elegant way to do this, especially if you want the new window to be a modal dialog. One way is to add an event handler to the view's code-behind that listens to PropertyChanged on the view model; when the subordinate view model property gets set, the code in the view creates and shows the new window.
My MainWindow will be a kind of "dashboard", and I will have more than one model attached to this dashboard. Should I just wrap all those models in a single view model?
Sure. That's a really common pattern. It's not at all uncommon, for instance, to expose an observable collection property and bind an ItemsControl of some kind to it; the view will automagically create views for every view model you put in that collection. Again, the specific implementation really depends on your application.
I want to use UserControl as the base for my views, but I cannot add functionality to my views because they are based on UserControl.
How do I create my own view class by using a subclassed version of UserControl.
You put them in the subclassed version of UserControl, and implement an interface which denotes the abilities the class has, so the ViewModel can be used with any type of View by simply using the interface.