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.
Related
I am trying to make a wizard in wpf using the wpf toolkit extended wizard control.
I need to prevent the user from proceeding to the next page unless certain conditions are met.
This answer to another question suggested binding the CanSelectNextPage property to a boolean property in the code behind the current page.
I am having trouble implementing INotifyPropertyChanged. In the answer linked above, his MainWindow class extends INotifyPropertyChanged. How is that possible? Wouldn't the MainWindow class have to extend the Window class?
Also, what assembly is INotifyPropertyChanged located in? MSDN says it is in System.ObjectModel.dll which I don't seem to have...
His MainWindow class implements INotifyPropertyChanged, which is found in System.ComponentModel.
This MSDN article should explain how to use it: https://msdn.microsoft.com/en-us/library/vstudio/system.componentmodel.inotifypropertychanged(v=vs.100).aspx
INotifyPropertyChanged will notify clients, such as your UI, when a given property changes. You could bind the visibility of your 'next' button to a boolean property of your class, and set the boolean property to true once all of your other properties are set.
EDIT: I should add that in order to bind a boolean value to the visibility of a button, you'll need to use an IValueConverter.
First off, INotifyPropertyChanged is an interface, not a class. So while a class can inherit from a single class only (here the Window class), it can implement multiple interfaces.
The interface itself is located in the System.dll assembly in the System.ComponentModel namespace.
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.
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!
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.
I was wondering what the best approach is for sharing a menu across all wpf windows/views.
My Application doesnt really fit the navigation model, so will probably use a Ribbon control.
I am leaning towards creating a user control for the menu and dropping it on each view, but have also seen Josh Smith's msdn article, where he loads user controls.
Are there any other options or established best practices?
Thanks in Advance.
I ended up implementing in a way similar to Josh Smiths; I have however simplified things a bit.
All views are usercontrols, except the MainWindow.
The MainWindow contains a ContentTemplate which is bound to a property holding reference to a single UserControl in the view model.
I then have an ApplicationController responsible for controlling the view and view model lifecycle.
The ViewModel base class used by each view contains a reference to the IApplicationController.
The MainWindowViewModel then makes calls to the ApplicationController to load a new view etc.
Still not 100% on this approach so would welcome any further suggestions.
Here's what I would probably try:
Define an ISharedMenu interface
Create a UserControl which uses the ISharedMenu as its DataContext.
For each ViewModel that you want to use the shared menu, implement the ISharedMenu interface.