I am making my first WPF application, so this question may seem rather odd. I have been reading about MVVM and so far it has made sense to me. What I don't understand, though, is separating all the XAML.
What I mean is this: I assume you don't place everything in the MainWindow.xaml and just collapse controls based upon what is going to be used. I would think you would want a container that would contain xaml of other files. Is this correct?
How do you go about separating the XAML out so that it isn't just a mash of everything in one file?
How do you go about separating the XAML out so that it isn't just a mash of everything in one file?
There are many ways, including creating a seperate UserControl, CustomControl, Page or Window
For example, if you wanted to pull some XAML out of your MainWindow.xaml, you could create a UserControl (right-click project, Add, New Item..., User Control (WPF)) called MyUserControl.xaml like this:
<UserControl x:Class="WpfApplication1.MyUserControl"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<Grid>
<TextBlock>This is from a different XAML file.</TextBlock>
</Grid>
</UserControl>
and then use this control in your MainWindow.xaml like this:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:myControls="clr-namespace:WpfApplication1">
<Grid>
<myControls:MyUserControl/>
</Grid>
</Window>
Note that you need to add a reference to the namespace of your UserControl
xmlns:myControls="clr-namespace:WpfApplication1"
I agree with Kevin's answer about UserControl and Window, so I'll just address the follow up question:
So I should switch between various controls that are collapsed/visible in the content of my MainWindow when the user is interacting with my application?
That is a valid option. It might get messy if you are working with a large application.
The other options that I've used are
switching Views in the code behind; i.e. on the click events you can add and remove elements from the page as you would have done in WinForms. This is not pure MVVM and some people will jump down your throat, but I believe MVVM is a tool, not a religion.
provide Views as properties in your ViewModel, and bind to them from your parent View. I don't know if this is pure MVVM, it's nice when you need to dynamically create Views depending on complex conditions but it can get complicated
use DataTemplates, which are essentially rules to determine the View to use based on the type of data that is provided. So if the data is an Address (or AddressViewModel), use the AddressView. If the data is a CustomerViewModel, use the CustomerView. And so on.
DataTemplates are the preferred pattern in my opinion - clean, easy to maintain, and a nice standard. It's trivial to go to the DataTemplate to see how the binding works, whereas the other two options I've given may lead to spaghetti code in the wrong hands.
MSDN has a nice page on DataTemplates in WPF.
When using Caliburn framework you could compose your application using smaller Views and ViewModels and have a shell which binds all those smaller views together. The shell would display one or many views at the same time, depending on how you want your application to behave. The good thing about this - unlike the pattern mentioned above where you hardcode the name of the View/UserControl in other places - is that you just create a ContentControl and bind it to the correct ViewModel property and Caliburn will find the correct View for you by convention.
Let's say you have a ShellViewModel and a ShellView which is just an empty window, and another View/ViewModel where you want to display in your shell at one point. You no longer need to instantiate your views anywhere and just work your way using POCO ViewModels objects:
public class ShellViewModel : Screen
{
public ChildViewModel Child { get; set; }
public void SomeAction()
{
Child = new ChildViewModel(); //Or inject using factory, IoC, etc.
}
}
public class ShellView : Window
{
}
<Window x:Class="WpfApplication1.ShellView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:cal="http://www.caliburnproject.org">
<Grid>
<ContentControl cal:View.Model="{Binding Child}" />
</Grid>
</Window>
Related
I've been recently trying to re-write a WinForm application to WPF. I've been trying to implement an MVVM structure into my application because it's starting to look a lot like Winforms where I need to name my controls x:Name and referencing them all the time. Essentially, I'm not using the power of what MVVM provides.
One thing I'm having trouble wrapping my head around, is the Window. Every time I create a Window, it generates a partial class. My question is, how does that tie in to MVVM? The confusion starts as to what content this class should contain. Does it have a single DataContext binding? What about button events?
From my understanding (at the moment), is that this "partial" class should have very minimal code, perhaps only to bind your ViewModel in your constructor:
this.DataContext = new ViewModel();
and the rest of the functionality should come from your ViewModel with the help of binding things on XAML. However, each ViewModel should be tied to a single Model. But what happens when this particular Window calls for many Models, such as a Client, Products, etc? Do you make a single ViewModel class that somehow does everything?
The essence of my question lies within the contents of this particual "partial" class and its relation to the ViewModel.
Looks like you've got two questions:
How the heck does this partial class thing fit in with MVVM?
How do I structure all the view models and models and stuff?
1) What you are referring to as a "partial class" is often called "code-behind" when discussing WPF. This is because in that in non MVVM patterns it usually has all the actual C# code that sits behind the xaml layout - i.e. "code-behind".
You're correct that a good indication of a good MVVM implementation is minimal/no code-behind. As you mentioned, usually all it will have is binding the DataContext to the ViewModel - and in lots of frameworks this is all handled for you and you don't even need that. In my MVVM projects every partial class looks like this:
namespace MyApp.Views
{
public partial class GeneratorView : CreatableView
{
public GeneratorView()
{
InitializeComponent();
}
}
}
Part of the nice thing with MVVM is that all the spaghetti event updating/connection code that you had to have in WinForms is all bypassed by using bindings. But as you noted, you can still do this with WPF but it's generally considered bad practice, and definitely with MVVM.
With all content and commands being bound directly to the ViewModel through data binding, the partial class need not have any content at all. There's lots of interpretations, but on a basic level:
The View lays things out and shows things on the screen.
The View Model contains UI specific data and logic. It deals with commands from the view, and may utilize business services.
The Model represents your data. Think of the stuff that's going in a database or file system.
2) MVVM is not strict in how you structure it. Generally the convention is you have ViewModel for every View. However, I believe it's fine to have a ViewModel without a View. Especially simple ones.
But what happens when this particular Window calls for many Models, such as a Client, Products, etc? Do you make a single ViewModel class that somehow does everything?
Not at all, it seems like you've got this all-or-nothing monolithic ViewModel in your head. If these were really simple structures, I'd do it like this:
However, you might want a dedicated ClientView or ProductView, and instead embed them in the main view:
The key thing is your ViewModels may contains other ViewModels, arrays of ViewModels. Similarly, your View can embed other View's to display it's ViewModels - or not. If they're simple, or you're just, say, listing a few properties (Maybe when you click an 'info' button a dialog shows up and that has the full View for said ViewModel, but in the list you just want the Name and Cost.
It's flexible. On thing is, often the Window isn't even part of the MVVM pattern. It's so "dumb" that it doesn't even have a ViewModel (also, what if you want to embed your app into another app or something?).
It's more flexible to have a high-level "AppViewModel" and all your Window does is contain that (often not even bothering with a WindowViewModel, it's not really a concern).
You can use more than one model in a view model. The aim of the view model is to abstract from the business layer (models, services).
For creating and keeping the instances you may use IoC (Inversion of Control) containers. There are many IoC containers available to use in .NET applications such as Castle Windsor, Autofac and so on (see List of .NET Dependency Injection Containers (IOC)). You just need to instantiate a view model object by necessary model objects, for example like this:
public class ViewModel
{
private readonly IClientModel _clientModel;
private readonly IProductModel _productModel;
public ViewModel(IClientModel clientModel, IProductModel productModel)
{
_clientModel = clientModel;
_productModel = productModel;
}
// Logic of your view model
}
Also you need to configure object dependencies and scopes (your model will be a singleton or a new instance of the type). The container injects dependencies when it creates the objects.
Also I recommend to read the article MVVM - IOC Containers and MVVM.
Yes, the way I approach it anyway, is to keep my Window dumb. How dumb? I guess it depends on the application. If I am just trying to throw a proof of concept or something with low importance together then I will cut a few corners. If I am working an a large application that will need to be maintained then I am going to be more strict, I may even frown on setting the ViewModel from the constructor in that case.
However, each ViewModel should be tied to a single Model
I don't know that I agree with that. That is not how I have approached MVVM, anyway. I would say that every View should be tied to a ViewModel. Within the ViewModel it may be the case that you are only dealing with one model but I have also had great success using a single ViewModel to expose multiple models to a View in a coherent way as well.
Here is an example of a template I use as a jumping off point in some of my smaller projects. I like to use explicit ViewModel properties in my Window and Views but you don't have to; you could modify this to use the DataContext property instead.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
public object ViewModel
{
get { return (object)GetValue(ViewModelProperty); }
set { SetValue(ViewModelProperty, value); }
}
public static readonly DependencyProperty ViewModelProperty = DependencyProperty.Register(
"ViewModel",
typeof(object),
typeof(MainWindow));
}
In the code behind the ViewModel propoerty is just a dependency property of the Window. I will bind the Window content to this property. In this case it is an object but it could be some base ViewModel class or an interface if you want.
In my Window's markup I add a DataTemplate for each ViewModel to the Window's resources. If everything is wired together correctly WPF's implicit data templating will take over and make sure the correct view is rendered whenever the ViewModel property is changed.
<Window x:Class="Example.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:system="clr-namespace:System;assembly=mscorlib"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:viewModels="clr-namespace:Example.ViewModels;assembly=Example"
xmlns:views="clr-namespace:Example.Views;assembly=Example">
<Window.Resources>
<ResourceDictionary>
<DataTemplate DataType="{x:Type viewModels:FirstViewModel}">
<views:FirstView ViewModel="{Binding }" />
</DataTemplate>
<DataTemplate DataType="{x:Type viewModels:SecondViewModel}">
<views:SecondView ViewModel="{Binding }" />
</DataTemplate>
</ResourceDictionary>
</Window.Resources>
<Grid>
<ContentControl HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Content="{Binding ViewModel, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" />
</Grid>
</Window>
There are multiple places in my application whehe I have ContentControl placed in xaml and I do not know beforehand what its Content is going to be. What is the best practice to implement this scenario?
Right now I am considering two approaches:
Bind ContentControl.Content to view model and use a dictionary of DataTemplates to find an appropriate view. My issue with this approach is that even if I were to list all the possible combinations in a dicitonary, in some cases I simply do not know an exact type of view (or viewmodel if there is any) at compilation time. I think, I am also going to have troubles using this approach for hosting non-WPF content.
Create some sort of an interface:
interface IContentPlugin : IDisposable
{
object View { get; }
}
and bind ContentControl.Content to IContentPlugin.View directly. I could then have multiple implementations of this interface and swap them when I need to. But this solution does not strike me as something that goes well with MVVM application, as it forces me to have references to IContentPlugins in my view models.
What do you think is the best option and why? Perhaps there is a better approach?
this is a very interesting scenario and for these cases I usually introduce a ViewResolverService or a ViewModelResolverService (or both). So something that can either give you the ViewModel based on a view (class,type or name) match them to host them in the ContentControl. Or a Service which can give you a view based on the ViewModel (type, or string name). With this powerful concept you can use ContentControls and/or DataTemplates and you have full control.
I answered some questions explaining the concepts here:
Register all viewmodel and services in ViewModelLocator
and here:
Get the View & ViewModel from a plugin
more here: https://stackoverflow.com/search?q=ViewModelResolver
So if you look at it from the birds eye view you need to apply MVVM to your ContentControls with your views. (And the views have also MVVM applied within themselves).
HTH
You should use implicit View determination via DataTemplates.
This is achieved by having type-specific DataTemplates (i.e. DataTemplates without a key reference) for your ViewModel types in a ResourceDictionary local to the scope of the ContentControl.
Be aware though that you will need to scope the ResourceDictionary quite carefully in the case where a single ViewModel can have multiple Views associated with it.
Update:
The reasons to use implicit View determination are:
In general, the View resolution look-ups are faster than if you were to write a View resolving service.
You're not duplicating effort by writing your own View resolver which you then need to plug into the WPF runtime.
You should be telling the external source what you support and in this case, keep it always to WPF ResourceDictionary so that regardless of the content/resources, you are able to merge it into your runtime ResourceDictionaries - this means, your external sources will need to provide the WinForms control wrappers for you.
As someone who has created a plugin framework before using this pattern, working with a conceptually "pure MVVM" implementation simplifies things considerably - external sources supply a ViewModel class and a ResourceDictionary of the resources for the VM and you let WPF do the heavy-lifting of View determination for you.
Use DataTemplate for ContentControls:
<DataTemplate DataType="{x:Type vm:DataSourceViewModel}">
<view:DataSourceView></view:DataSourceView>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:SelectTemplateViewModel}">
<view:SelectTemplateView></view:SelectTemplateView>
</DataTemplate>
.........
........
<ContentControl Margin="5" HorizontalAlignment="Stretch" Content="{Binding CurrentPage}" Name="ImportControls"></ContentControl>
VM:is the object type that is content of your contentcontrol
View: is specific view you want to see if object of a specific type is set as content of ContentControl
Eventually, I went with second approach. I was able to solve my main problem, which was:
But this solution does not strike me as something that goes well with MVVM application, as it forces me to have references to IContentPlugins in my view models.
Passing those "plugins" into viewmodels was a mistake, you should not do it. What you can and should do is find a way to partition your view into smaller independent segments, and set their content in non-MVVM way. So basically I ended up with a view, which acted as container and looked like this:
<UserControl x:Name=this>
<Grid>
<Grid.RowDefinitions>
<RowDefiniton>
<RowDefiniton>
<RowDefiniton>
</Grid.RowDefinition>
<ContentControl Grid.Row="0" Content="{Binding PluginA.View, ElementName=this}"/>
<ContentControl Grid.Row="1" Content="{Binding PluginB.View, ElementName=this}"/>
<ContentControl Grid.Row="2" Content="{Binding PluginC.View, ElementName=this}"/>
</Grid>
</UserControl>
where PluginA, PluginB and PluginC are dependency properties in code-behind, that are set by DI container using property injection. I am happy with the end-result, and it gives me the flexibility I need.
You can also use PRISM, which roughly speaking does the same thing, but in more general and flexible manner. It was somewhat too complex for my application though, so I decided to keep it simple. But you should give it a try, if you are trying to solve similar issue.
I have a large project coded with VB6 which I've been trying to upgrade to new technologies for a few months. My project consist on 6 administrative modules reunited under a client-server application. Coming from VB, my logical choice was to upgrade to .NET. After a lot of research I decide to use C#, WPF and the MVVM pattern (with Caliburn Micro).
At the beggining I had some problems, but I managed to resolve them. But now I've come to a point where I need (like every complex application) to communicate with different views and their corresponding viewModel through modal popups (or some other technique). And in this matter the MVVM pattern seems to be very restrictive or complex. A simple "Are you sure you want to delete this record (yes/no)" is a very complex task. So I'm looking for advice as how communicate views without complex artifacts as EventAgregators.
So far the only possible alternative I've found is to use the ModalContentPresenter class from this blog. The problems with this solution are:
I need to write the father view XAML and modal XAML on the same view.
I cannot have multiple popus from same view.
Some examples of where I'd like to use modal popups is:
Put a button on a view to select a Client. It should open a popup with all posible clients and let the user chose one.
Add a product popup to a customer order.
Any ideas or suggestions? Some sample code would be appreciated? Thanks!
I am the author of the linked ModalContentPresenter control so I will attempt to address some of your questions and concerns.
I need to write the father view XAML and modal XAML on the same view.
You can actually write both views in separate files. The views can then be loaded dynamically using DataTemplates which will depend on the ViewModel that is bound to either the Content or ModalContent properties.
See this which describes the general way in which this view switching can be achieved.
You could have a MainViewModel which has two properties, PrimaryViewModel and SecondaryViewModel which return appropriate view models which provide the properties and commands for the main and modal content.
You could have the following setup in XAML:
<DataTemplate DataType="{x:Type FooViewModel}">
<Controls:FooView />
</DataTemplate>
<DataTemplate DataType="{x:Type BarViewModel}">
<Controls:BarView />
</DataTemplate>
<controls:ModalContentPresenter
Name="modalPresenter"
Content={Binding DataContext.PrimaryViewModel}
ModalContent={Binding DataContext.SecondaryViewModel} />
When the IsModalproperty is false, only your PrimaryView will be displayed. As soon as you set the IsModal property to true the ModalContentPresenter will display your SecondaryView.
I cannot have multiple popus from same view.
I take it you mean you want to be able to display different modal content at different times from the same main view.
Using the above technique this is as simple as switching the ViewModel that is bound to the ModalContent property (before displaying it by setting IsModal to true). As long as you have a DataTemplate for the ViewModel that is bound (and your MainViewModel implements INotifyPropertyChanged correctly), the correct content will be displayed.
Some example on where i'd like to use modal popups is:
Put a button on a view to select a Client. It should open a popup with
all possible clients and let the user chose one.
Add a product popup to a customer order.
Once you understand the technique described above you should be able to see that the as long as you have a View and ViewModel pair you can cover any scenario you can think of.
As an example, consider viewModels that have the following interfaces:
public interface SelectCustomerViewModel : INotifyPropertyChanged {
event EventHandler CustomerSelected;
public ObservableCollection<Customer> Customers { get; }
public Customer Customer { get; set; }
public Command CustomerSelectedCommand { get; }
}
public interface MainViewModel : INotifyPropertyChanged {
public SelectCustomerViewModel ModalContent { get; }
public Command SelectCustomerCommand { get; }
public bool IsSelectingCustomer { get; }
}
You could have XAML that looks something like this:
<Window x:Class="ModalContentTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Select a customer">
<DataContext>
<vm:MainViewModel />
</DataContext>
<DataTemplate DataType="{x:Type SelectCustomerViewModel}">
<Controls:SelectCustomerView />
</DataTemplate>
<c:ModalContentPresenter Name="modalPresenter"
ModalContent={Binding ModalContent}
IsModal={Binding IsSelectingCustomer}>
<!-- This is the primary content! -->
<Grid>
<Button Content="Select a customer"
Command={Binding SelectCustomerCommand} />
</Grid>
</c:ModalContentPresenter>
</Window>
Here's how it works:
The IsSelectingCustomer property of the MainViewModel would start off as false.
Clicking the button in the main view would invoke the SelectCustomerCommand object. The command would then tell the MainViewModel to change the IsSelectingCustomer property to true.
The ModalContentPresenter would display the view specified by the data template. The user can now only interact with the 'select customer view'.
Once a customer has been selected, a button can be clicked (which is bound to the CustomerSelectedCommand of the SelectCustomerViewModel) which in turn would raise the CustomerSelected event.
The MainViewModel would have an event handler that would respond to the CustomerSelected event. The handler would then read the SelectedCustomer property from the SelectCustomerViewModel and finally, it would set the IsSelectingCustomer property back to false, causing the modal content to be closed.
I'm new to WPF and the whole data binding thing. I read a couple of posts and I'm quite confused about how to bind my data to a UI element.
I saw a post doing it this way:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Name="myWindow">
<Grid>
<TextBox Text="{Binding Path=Speed, ElementName=myWindow}" />
</Grid>
</Window>
This assumes Speed is a property / member defined in the code-behind file. A few other people named binding using a static resource and reference this one and others named DataContext to be used for binding. Now, because I'm new to WPF's data binding, I'm quite unsure if there exists any best practice method about which data binding to use.
Basically I was wondering why there has to be a several class-property defined as kind of connector to the underlying viewmodel, I though this stuff was more "dynamically".
I'm aiming at only having the XAML file, without the need to add anything into the *.xaml.cs code behind file. For example: I have a class named MainWindowViewModel (which will represent my ViewModel) having a member of the type ObservableCollection<string> and I want to bind a ListBox (in my View) to this collection. The only way I got this working so far was using the the first case, ElementName, where I have to add a property to the view-class as a kind of connector. Just like this:
MainWindow.xaml:
<Window x:Class="Sample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Name="MW" Title="MainWindow" Height="419" Width="463">
<Grid>
<ListBox ItemsSource="{Binding ElementName=MW, Path=ListerResultConnector}" />
</Grid>
</Window>
MainWindow.xaml.cs:
private ObservableCollection<string> mListerResultData = MainWindowViewModel.Instance.RetrievalStringResults;
public ObservableCollection<string> ListerResultConnector
{
get { return mListerResultData; }
}
My question is, if there exists a smarter way to bind data to my UI as using as further "connector" property in the code-behind file.
Your ViewModel should be set as the DataContext to the view. Then you don't need any "further connector" in codebehind. Binding actually refers to DataContext and if you don't set it, it remains as 'this', which corresponds to your codebehind file (which is just a partial to your view).
Also, take a look at: WPF Apps With The Model-View-ViewModel Design Pattern
You should get the WPF and it's binding basics first, but once you understand those, I suggest looking at Caliburn Micro and its convention-based bindings, event handling and other features which make your code much cleaner.
Your {Binding ElementName=MW means you are binding to the Window itself, so your DataContext is the Window, and any properties you implement need to be defined in that Window (in your code behind - your "connectors").
You need to remove the ElementName=MW bit and assign your ViewModel as the DataContext so you can bind to its properties directly. How you do this depends on whether you use "ViewModel First", or "View First"
In View first, you manually assign the DataContext to the View in code when you create the view.
In ViewModel first, you create a DataTemplate in XAML that ties your View to a particular ViewModel. I think ViewModel first is more common. The link that Darjan posted should help you understand the difference.
You should use a separate ViewModel class (WindowViewModel) which represents your data context for your Window (Window.DataContext).
I found that using the MVVM Light toolkit and following some of the videos on the site helped me fill in the gaps. Take time to learn it before getting started and it will start to sink in. IoC containers are also mixed in with MVVM + WPF for directory management & lifetime management of view models and improved design-time experience (blendability).
Toolkits aren't required and sometimes get in your way of learning the pattern. Once you understand it though, you should leverage a toolkit to speedup the development process. Here is a comparison of various MVVM toolkits.
A binding generally has two parts: a source object and a property name
When you specify ElementName in a binding, you are setting the Source object. Other ways to specify the binding's source object include the RelativeSource and Source properties. You can also leave the binding's source object undefined, in which case it will use whatever the DataContext is of the current object. The Source Object can be a UI Element found in WPF's VisualTree, or it can be a class object that is in the control's DataContext
When you specify Path, you are telling the binding what Property to use. You can also leave this property blank to bind to the current object's DataContext
The DataContext is the data object stored behind the control. This is typically a Model or a ViewModel (if using MVVM), although it can also be almost any object, such as a UI Element.
In your example
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Name="myWindow">
<Grid>
<TextBox Text="{Binding Path=Speed, ElementName=myWindow}" />
</Grid>
</Window>
you are telling the binding that it's Source Object is the UI Element in the Visual Tree named myWindow, and the property is called Speed. Since your object named myWindow is of type Window, this binding will only work if your Window class actually has a property called Speed.
There are a lot of answers here suggesting you switch to using the MVVM design pattern, and I agree that you should try and use MVVM if you're working with WPF. It makes coding a lot simpler since you are separating your application logic from your UI. If you're interested, I have a simple MVVM example posted on my blog which explains the basics of that design pattern.
Yeah, Binding is nothing if not confusing.
This example from msdn may be helpful. Notice how a DataContext is declared at the Window "level" - it's a complex/compound object in this case and Window sub-elements' {Binding} declarations are therefore implicitly relative to the "Parent level" DataContext.
The main goodness we get is that when the DataContext is set to a given object all the "sub element" data bindings are automagically keep in synch. We can control this synchronization at any/many levels in the UI Control structure heirarchy by using this pattern.
Collection binding under the hood
The bottom line is your collection must implement IList as a minimum. Many .NET Collection classes are "binding ready."
Here's a quote from the msnd doc on ObservableCollection:
Before implementing your own collection, consider using ObservableCollection or one of the existing collection classes, such as List, Collection, and BindingList, among many others. If you have an advanced scenario and want to implement your own collection, consider using IList, which provides a non-generic collection of objects that can be individually accessed by index. Implementing IList provides the best performance with the data binding engine.
Finally, IBinding list vs IList is needed for 2-way binding.
The simplest way to do it would be:
<Window x:Class="WpfApplication4.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ctrl="clr-namespace:WpfApplication4"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<ctrl:MainWindowViewModel x:Key="mym" />
</Window.Resources>
<Grid DataContext="{Binding Source={StaticResource mym}}">
<ListBox ItemsSource="{Binding Path=MyListProp}" />
</Grid>
The example above does the following:
Creates a new object of the ViewModel as resource for you window
Assigns the view model as DataContext for the window (more precisley for the root grid)
Binds the List box to your ViewModel ObservableCollection property MyListProp.
Try to get familiar with the properties of the binding class to fully understand this example by using the msdn library.
Also WPF 4 Unleashed - Adam Nathan is a great resource for a wpf beginner. Chapter 13 - Data Binding should cover everything you might want to know about bindings.
I have a fairly basic WPF UI whereby user requests cause a new tab to open in my TabControl. The TabControl is bound to an ObservableCollection<ViewModelBase>
I add ViewModel instances to this collection, and the corresponding tab's content is displayed based on templates like this:
<DataTemplate DataType="{x:Type viewModels:UserUploadsViewModel}">
<userControls:UserUploads />
</DataTemplate>
Now let's say that inside of the UserUploads control I'd like to wire up a ViewModel in XAML to help with the designing, like this:
<UserControl x:Class=".....UserUploads"
.....
DataContext="{Binding Source={StaticResource ViewModelLocater},
Path=UserAdministrationViewModel}">
This property will return a ViewModel with live services at runtime, and a ViewModel with mock data at design time.
Question: Will this XAML interfere with what I'm doing in binding a TabItems content to a ViewModel instance, and relying on the dataTemplate above to render the right View? If so, is there a way to get both of these concepts to work together?
There is an easier way to do this. Have a DesignTimeUserAdministrationViewModel and populate it with static data in the constructor and refer that in UserControl as:
<UserControl d:DataContext="{d:DesignInstance designTimeVMs:DesignTimeUserAdministrationViewModel, IsDesignTimeCreatable=True}">
This way you have a design time test data bound to d:DataContext and runtime live data bound to the actual DataContext. More details here.
Yes I think it will interfere with your current setup
The ViewModelLocator is a static class that returns a dummy object at design time, and a static ViewModel at runtime. This means that
The ViewModelLocator, not your ParentViewModel, contains your TabViewModels
You cannot have multiple instances of the same Tab (ViewModel) open at once
You cannot manage Open/Closed tabs unless you reference the UserControl, which is a violation of the MVVM principle where the ViewModel doesn't know of the View
You can't instantiate new copies of the TabViewModel with parameterized constructors. For example, OpenTabs.Add(new CustomerViewModel(CustomerId));
Perhaps an alternative could be a Converter? One that returns a static object if in design time, or the bound object during runtime? I've never tested such a thing but in theory it should work :)
The built in MS stuff is not bad, but another more elegant and structurally sound alternative which I am busy incorporating in my project is:
http://msdn.microsoft.com/en-us/magazine/dn169081.aspx
Basically, you use the MVVM Light toolkit with the SimpleIoc container it comes with and end up with the ability to serve up data for the following three scenarios:
Design time, Run time, and Test time.
Better still, the whole point of MVVM Light is to have your stuff be directly editable in Blend and there is a whole series of videos and blogs and sample apps describing it all. I wish I had found these earlier in my WPF explorations.