WPF View - UserControl path instead of UserControl content - wpf

What can be the reasons that I see the UserControl path instead of UserControl content?
I have quite complex code, so I just would like to ask for some hints, where I should look for the problem..
This shows when I debug my app:

Presumably, you have ConteControl which binds to OrderEntryViewModel but it is not associated with any view. You need
<Window.Resources>
<DataTemplate DataType="{x:Type viewmodel:OrderEntryViewModel}">
<userControls:YourView/>
</DataTemplate>
</Window.Resources>

Related

connect View to ViewModel with DataTemplate

I'm trying to understand. When I'm connecting View to ViewModel like this:
<DataTemplate DataType="{x:Type local:MyViewModel}">
<local:MyView />
</DataTemplate>
What does it mean?
It looks like the View is set to be the DataTemplate of the ViewModel. BUT the ViewModel doesn't have a Property of DataTemplate. So what exactly is going on in there?
A demonstration of the question - How do I do that by code (Connecting the View and ViewModel this specific way. I can't write ViewModel.DataTemplate = View)?
Thank you.
It means "To whatever control whose Content data is MyViewModel place MyView there". You are not setting DataTemplate of viewmodel (That does not mean anything) you are setting the DataTemplate for the control whose Data is MyViewModel.
Take for example an ItemsControl with an Items Source of
ObservableCollection<Employee> Employees
where each Employee is represented by a DataTemplate for Example :
<DataTemplate TargetType="{x:Type local:Employee}">
<StackPanel>
<TextBlock Text="{Binding FirstName}" />
<TextBlock Text="{Binding LastName}" />
</StackPanel>
</DataTemplate>
So in the same manner a MyViewModel.cs such as Employee.cs as a visual representation based on a DataTemplate .
and represented for example as such :
<ContentControl Content="{Binding MyViewModelProperty}" />
The way how it works is very simple. Your definition of DataTemplate is something like a definition of how a data will look like. In your example the data that you want to represent visually are of type:
DataType="{x:Type local:MyViewModel}"
By defining DataTemplate in control, window or other resources, e.g.
<UserControl.Resources> ...your template... <UserControl.Resources>,
you say "Hey, I want that all my data of type local:MyViewModel will look like this...". Inside the template you define a root control, that will be put in all places where your local:MyViewModel have been used. Normally when you place local:MyViewModel in Grid, ContentControl or other containers, you will see its string representation like "xxxx.xxxxx.MyViewModel" instead of visual.
To to see a graphical representation you must define a DataTemplate. It will replace the string "xxxx.xxxxx.MyViewModel" - representing your data and put there a visual control you defined in the template. Then when it is done, this representation - control from your DataTemplate will get DataContext property set to your View Model, here it will be local:MyViewModel instance.
That will give you a possibility to use binding in your DataTemplate, to bind in you DataTemplate directly to properties from you ViewModel.
Is that more clear now?

Should I be using UserControls for my Views instead of DataTemplates?

I was reading this post and the author makes the suggestion that using DataTemplates to define a ViewModel is a lunatic's way to do it (#7). I do that all the time, is it really that bad?
<DataTemplate DataType="{x:Type local:MyViewModel}">
<Grid>
...
</Grid>
</DataTemplate>
Most of my Views are simply a ResourceDictionary that defines a DataTemplate or two. To me, it makes much better sense to do this than creating a UserControl for every ViewModel. Why would I want the extra layer in WPF's visual tree when it's not needed? And why would I want to take care of mapping ViewModels to Views when a DataTemplate does that for me? Is this syntax really a "lunatics approach"?
Nothing bad about it, except for incredibly large xaml files and the lack of edit support that DataTemplates have on the design surface.
If those issues are hurting you, you can always...
<DataTemplate DataType="{x:Type local:MyViewModel}">
<local:MyViewModelUserControl />
</DataTemplate>
The good thing with DataTemplate is that they are strongly typed to Viewmodel classes. All you need to do is create a ContentPresenter in View and Bind DataContext to VM. If your DataTemplate is defined in a ResourceDictionary and has a DataType attribute instead of Key, WPF will internally figure out the right DataTemplate for the VM class and display it.
But as you mentioned, we cannot create the DataTemplate in a seperate file. So the file where the DataTemplates exist in ResourceDictionary (e.g. App.xaml), the file gets really messy and it becomes difficult to manage the code soon.
So my take is, if the VM is simple create a DataTemplate. Or else it is always better to create a seperate UserControl and bind its content to the VM.
I run into the issue with performance. There is difference between next two case:
1.
<DataTemplate DataType="{x:Type local:MyViewModel}">
<!-- xaml is moved to separate user control -->
<local:MyViewModelUserControl />
</DataTemplate>
2.
<DataTemplate DataType="{x:Type local:MyViewModel}">
<!-- xaml is typed here directly -->
<Border>
...
</Border>
</DataTemplate>
In 1st case it takes longer to render results than in the 2nd. And this difference is in about 2 times.
I posted it as a separate question

How do I bind a generic window to an arbitrary view model at runtime, using DataTemplates?

I have a large number of ViewModel classes. For each of these classes, there is a corresponding .xaml file which is a 'UserControl'. In my App.xaml, I have them registered as DataTemplates, like so:
<DataTemplate DataType="{x:Type viewModel:MainMenuViewModel}">
<view:MainMenuView/>
</DataTemplate>
With the idea being that WPF will be able automatically swap in the necessary user controls at runtime. For example, this works:
<Grid>
<StackPanel>
<TextBlock Text="SuperApp" />
<ItemsControl>
<ViewModels:MainMenuViewModel/>
</ItemsControl>
</StackPanel>
</Grid>
In that the entry "MainMenuViewModel" is automatically replaced by the MainMenuView, bound to the MainMenuViewModel. Great. My current goal is now this: I want to have a button, on, say, a view embedded in the MainMenuView, which opens a popup window, which will have a new ViewModel inside. The idea is to set it up so that I have a single 'generic' popup form, in which I embed an arbitrary ViewModel, and let WPF handle actually rendering it with DataTemplates, similar to the above. So I have a command bound to a button, like so:
<Button Command="{Binding Path=LaunchInStandaloneForm}" Content="Rip Out"/>
Which successfully creates a new window, sets the dataContext equal to the appropriate ViewModel, and shows the window.
The question is: How do I set up the XAML of this popup window so that it will render the appropriate DataTemplate for the ViewModel which is the DataContext? I've tried:
<Grid>
<ItemsControl ItemsSource="{Binding Path=.}">
</ItemsControl>
</Grid>
, but it comes up blank. Any pointers?
To set the ItemsSource to the DataContext, use ItemsSource={Binding}. That assumes that the DataContext is an enumerable collection of your View Model objects.
Updating with correct answer:
Use a ContentControl :)
Hope that helps.
The accepted answer here shows how to change templates at runtime. You should be able to dig out the answer from that. Any questions just shout.
How to modify silverlight combobox data display
Hope that helps

DataTemplate DataType usage WPF

I had been setting the DataContext for UserControls like so:
<uc:DepartmentListingView DataContext="{Binding ., Mode=TwoWay}" />
Based on a sample project by Josh Smith I am trying to accomplish the same thing with a DataTemplate and DataType:
<!-- Template applies a DepartmentListingView to an instance of the DepartmentSelectionViewModel class. -->
<DataTemplate DataType="{x:Type model:DepartmentSelectionViewModel}">
<uc:DepartmentListingView />
</DataTemplate>
This works well, but of course there is a problem; I think it might arise from trying to set more than one view (UserControl) to the same view model(?). In the code below I am now associating the same viewModel from above with a different view in the same window.
<DataTemplate DataType="{x:Type model:DepartmentSelectionViewModel}">
<uc:ListSubjectHeaderView />
</DataTemplate>
The first view is wired the same as it was when I set the DataContext explicitly but the last view gets no binding, although no obvious DataBinding error in the console either.
So, would resusing the DataType / DataTemplate trick this way be the problem?
Thanks,
Berryl
Ideally you will have a one to one relationship between a view and viewmodel.
To get what you want perhaps subclass your viewmodel with nothing extra and have that subclassed viewmodel as the datatype in the datatemplate.
That way just creating the correct viewmodel will drive the correct datatemplate and therefore usercontrol

Is it Possible to apply a DataTemplate to a Page?

I'm trying to follow the MVVM pattern laid out here: http://msdn.microsoft.com/en-us/magazine/dd419663.aspx#id0090097 I have this in my MainWindowResources.xaml file:
<DataTemplate DataType="{x:Type vm:VendorsViewModel}">
<vw:Vendors/> <--- I get a "Can't put a page in a style" error in blend with this
</DataTemplate>
and I've got this in my MainWindow.xaml file
<Window.Resources>
<ResourceDictionary Source="MainWindowResources.xaml"/>
</Window.Resources>
The mainWindow.xaml file contains a menu on the left and page holder on the right. Can I apply a dataTemplate to a <Page>? Or does it have to be a <UserControl>? As it stands, nothing is being data bound, here's what I have on the page that I want to have the viewmodel applied to:
<Custom:DataGrid Margin="0,30,0,0" d:LayoutOverrides="Width" ItemsSource="{Binding Path=AllVendors, Mode=Default}" >
<Custom:DataGrid.Columns>
<Custom:DataGridTextColumn Header="Company Name" Binding="{Binding Path=Name}" />
</Custom:DataGrid.Columns>
</Custom:DataGrid>
DataTemplates are applied to Content, which in most cases is either the Content property of a ContentControl or the Items/ItemsSource property of an ItemsControl. Page is not derived from ContentControl (UserControl is) so a DataTemplate can't be applied to its Content.
From what you're doing here it doesn't sound like that's what you're trying to do though. It looks like you're trying to use a Page in a DataTemplate which is what the error is telling you. Page is treated like Window in that it is a root container that is intended to have visual Content defined in a xaml file. UserControl has a similar purpose but can be inserted anywhere into a layout. If you change vw:Vendors to be a UserControl that should get rid of this specific error but you should also consider whether you're gaining anything from having the UserControl instead of just putting its content directly into the DataTemplate - this can help discourage code-behind and force you to use your ViewModel correctly.

Resources