WPF: How to reuse controls when ObservableCollection is concrete? - wpf

I have a object that inherits from TabItem. I have a bunch of Database objects that will reuse the same code so I wanted only one TabItem class and then use DataTemplates to control how each object gets presented.
Problem is that the TabItem shows a collection of Objects and ObservableCollection is concrete.
I've pondered a few solutions but none of them work. Seems like I will have to create one class for each object type even when they will all be the same (except for ObservableCollection having different types). That's not very DRY.
I can't make a UserControl generic, I can't let the UserControl constructor take in a generic class ( unless I define the Type wihc I don't wan't to do). I guess creating a base UserControl class and then inheriting that will have to do. Does it inherit the XAML code as well or will I have to rely on styles and templates?
Am I missing something?

Look into using DataTemplateSelector to provide flexibily in how you present your data in WPF.
Here are three sites that helped me:
Data Templating Overview
How to use DataTemplateSelector to alter views of objects in a ListBox
WPF Tutorial - How To Use A DataTemplateSelector

Related

How can I use two way bindings with dependency properties?

I read that I need to implement InotifyPropertyChanged but I can't have my control inherit from two different classes.
I'm a little confused as to how I do this.
Basically I wish to have a parent control have a property bound to a control in the UI (already done).
and then I wish to bind that value to a property in a child FrameworkElement.
however, the usercontrol is already inheriting from usercontrol, and multiple inheritance is not supported. How do i go about alerting other dependencyproperties that my dependency property has changed?
INotifyPropertyChanged is not a class. It is an interface, and C# allows you to inherit from as many interfaces as you'd like.
If that doesn't clear up your issue, please add more details. An example would be great.

DataTemplate for View made up of different Views

In a Windows 8 style app I have a View (or page) which is made up of several other Sub-Views.
Each of these has an associated ViewModel and they are defined and bounded via the MVVM Light ViewModelLocator
I then have a View2 which is made up of other Sub-Views which, again, are defined and bounded via the MVVM Light ViewModelLocator
What I want to do is to place instances of the View and View2 controls into a List on a MasterViewModel and then bind this list to a GridView on a MasterView file.
Each of the instances of View and View2 should render as they do if you were to create a single instance without placing it into a list.
What I have tried to do is create a List of Pages (as all views are instances of this type) and bind the GridView to this, but when I run the app the GridView appears empty.
I have seen an examples that use a DataTemplateSelector (http://www.wiredprairie.us/blog/index.php/archives/1705) and apply a DataTemplate to each of the items in the MasterView list.
I understand what this does, but what I don’t understand is how to create a DataTemplate for a View that is made up of other Views.
I’m sure I am overlooking something and / or just making this harder than it needs to be!
Thank you for any help :)
Normally in this case, you would be binding a list to a set of ViewModels, not views, and the data template selector (or ValueConverter depending on your flavour) would select and instantiate a view suited to the view model.
So if ViewA uses ViewModelA : ISubViewViewModel, and ViewB uses ViewModelB : ISubViewModel then your main ViewModel would contain a List<ISubViewModel> which has a set of ViewModelA & ViewModelB within it. The main view's ListBox is bound to the List<ISubViewModel> and the data template selector / ValueConverter resolves ViewA for ViewModelA's and ViewB for ViewModelB's.
Hope that makes sense, it's about as hard to describe the solution as it probably was to describe the problem. :)

Custom control, View Model and dependency properties

I'm creating custom control and because I need to do lot's of binding inside a style/template it makes perfect sense to go with MVVM. Where do I declare dependency properties then?
Do they stay in control class? How do I link them to VM?
See my answer to your other question about custom controls and view models. Here's the short version:
Custom controls shouldn't have view models.Don't set the data context of your own control. That's reserved for the consumer.All of your dependency properties should be declared in your MyCustomControl.cs file.Use TemplateBinding in your genric.xaml because it's more efficient that Binding.
To put it another way, what's the view model for a Border or a Button? Answer: they don't have one because they're just controls. UserControls have view models, but controls just present and interact with the data which you give them (where? In your UserControl). Custom control development is probably the hardest thing for a seasoned MVVM developer: your reflex is to make a view model, but that reflex is unfortunately wrong. I know because I've made this mistake myself.
Dependency Properties could be delared in the Control they are belongs to.
When following MVVM in WPF/Silverlight the common approach is to set ViewModel as DataContext of the appropriate View. So you would be able to link custom Dependency Properties to the ViewModel properties using Bindings in XAML.
Let's assume you already set ViewMosel to DataContext of the View:
var view = new UserView
{
DataContext = new UserViewModel { Name = "Custom Name" }
};
public class UserViewModel
{
string Name { get; set; }
}
UserView.xaml:
<TextBlock Text="{Binding Name}" />
When creating a custom control, the control itself is a view model. Declare dependency properties on it to expose bindings that users of the custom control can leverage. For example if you have a timeline control, you might have properties like StartDate and EndDate on the control exposed as dependency properties. Your Controls Default Template would make template bindings to the dependency properties. A consumer of your control might then have a project timeline viewmodel that he binds to the properties on the control.
The primary purpose of a custom control is to provide behavior and a default look and feel for that behavior which is easy to override (by providing a new template). Hope this helps.

MVVM and Custom Controls?

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.

Can MVVM Usercontrols have property defined in codebehind?

I have a WPF user control ...which is in MVVM. The user control(which contains a listview) need data from the page (where it is included). I have to set a property to get this data input. Will this comply with MVVM...if not, what is the way for the same?
I'm afraid this won't be correct in MVVM design pattern. try to stick to your view model to define properties. Why don't you consider moving that property to control's vm?
Use an ObservableCollection rather.
ObservableCollection<myModel> myOC = new ObservableCollection<myModel>();
where myModel is a class that has to be constructed transforming your columns in the DataTable to Properties.
In your MainViewModel, loop through the DataReader and create myOC out of it.
Now bind myOC to a ListView in your page.
The DataTemplate of ListView should be a view(UserControl) drawing data from a ViewModel constructed out of myModel
But your UserControl has the entire ListView inside. If that is on purpose, then let me know the entire design to give a better idea.

Resources