How can I bind to the design instance of the data context - wpf

How can I do a binding like this?
<local:MySubView d:DataContext="{Binding MyParentView.(d:DesignProperties.DataContext)}"/>
I see MySubView doesn't get the DataContext of MyParentView automatically. The syntax above gives the DataContext is unknown.
The MySubView is used as DataTemplate inside MyParentUserControl.Resources. Both user controls should have the same view model. When I create a new instance like I do in MyParentView it is working:
<local:MySubView d:DataContext="{d:DesignInstance local:MyParentView, IsDesignTimeCreatable=True}"/>
But how can I bind to the same instance?

This Post was the answer. I had the same scenario. The binding was missing on an other place:
<ContentControl Content="{Binding}" Style="{StaticResource MyContentControlStyle}" >

Related

How can I set ComboBox DataContext in XAML?

I am trying to understand Binding so I have come up with a very simple program to try and test it.
I have the following element in my MainWindow:
<ComboBox Name="comboBox1" ItemsSource="{Binding}" />
In my Code I have the following observable collection:
public ObservableCollection<string> ComboItems = new ObservableCollection<string>();
I can successfully add items this way at any point during runtime:
comboBox1.DataContext = ComboItems;
ComboItems.Clea();
ComboItems.Add("Item");
My question is, how could I set the DataContext in XAML so that I don't have to do it in code? Is it possible?
Thank you!
Something common is:
<Window DataContext="{Binding RelativeSource={RelativeSource Self}}">
<ComboBox ItemsSource="{Binding ComboItems}" .../>
However usually you want to inject another object instance as DataContext, have a look at the MVVM pattern for example. Properties in WPF are inherited, so the ComboBox has the DataContext of the Window, it can be overwritten at any level though.
Note: For the Binding to work ComboItems needs to be a public property, not a field.
Resources of interest:
Data Binding Overview
Data Templating Overview
Depedency Properties Overview

Adding resource in code and using it as StaticResource

For some reason I am unable to bind to ViewModel properties within DataTemplates on some controls. The result of the binding itself is unpredictable, sometimes it work, sometimes it doesn't. For this reason I am thinking of exposing the ViewModel in some other way besides setting it as DataContext.
First thought was to add ViewModel to Resources collection. I am using TabControls for UI, so whenever a view needs to be displayed, it is done through Data templates.
<DataTemplate DataType="{x:Type vm:SomeViewModel}">
<vw:SomeView />
</DataTemplate>
In this situation the view is instantiated automatically, and its DataContext is set to ViewModel set in template. Is there a way I can make this ViewModel available to View's Resources (ex with key=viewModel), so that I can use it like this:
<TextBlock Text="{Binding SomeProperty, Source={StaticResource viewModel}}" />
I have tried adding it in code, in the Loaded event for the View:
this.Loaded += (s, e) =>
{
this.Resources.Add("viewModel", this.DataContext);
};
Above code is executed before the error pops up that says static resource is not found at run-time, so the resource was added to collection.
Any ideas what can I do?
You can define ViewModel as a resource in XAML like that:
<vm:SomeViewModel x:Key="ViewModel"/>
If you want to Bind to DataContext in a DataTemplate you can use the following:
{Binding Path=DataContext, ElementName=uc}
assuming that your window/usercontrol name is x:Name="uc" , or as #stukselbax wrote:
{Binding Path=DataContext, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=[UserControl|Window]}}

What is DataContext for?

As a continuation of the question Linking DataContext with another property in WPF.
At the very end of the research I was very surprised to find out that when one writes something like that:
<Label Content="{Binding Path=Name}" />
The DataContext against which the Content property is binded is of the Label control itself! The fact that it still works is due to the default inheritance of the DataContext value from the nearest parent.
But if you have this label wrapped in a custom control, and you don't want to bind your data to the DataContext property of that control, you would more likely love to have:
<Controls:SearchSettings Settings="{Binding Path=Settings}" />
And here you are. Now you need to set Settings as the DataContext for the SearchSettings control, for Label inside to bind against, but you can't, because that will trigger re-binding of Settings property.
I can't see the point in mixing binding properties using different sources: DataContext, by ElementName, etc.
So why would I ever use DataContext?
When you write
<Label name="myLabel" Content="{Binding Path=Name}" />
you are binding to myLabel.DataContext.Name, and not myLabel.Name.
The XAML in WPF is just a pretty user interface to display and interact with the actual data, otherwise known as the DataContext. The purpose of other binding sources (RelativeSource, ElementName, etc) is to point to another property that doesn't exist in the current control's DataContext
So suppose you have a Window. Without setting the DataContext, the window still displays but there is no data behind it.
Now suppose to set myWindow.DataContext = new ClassA();. Now the data that the window is displaying is ClassA. If ClassA has a property called Name, I could write a label and bind it to Name (such as your example), and whatever value is stored in ClassA.Name would get displayed.
Now, suppose ClassA has a property of ClassB and both classes have a property called Name. Here is a block of XAML which illustrates the purpose of the DataContext, and an example of how a control would refer to a property not in it's own DataContext
<Window x:Name="myWindow"> <!-- DataContext is set to ClassA -->
<StackPanel> <!-- DataContext is set to ClassA -->
<!-- DataContext is set to ClassA, so will display ClassA.Name -->
<Label Content="{Binding Name}" />
<!-- DataContext is still ClassA, however we are setting it to ClassA.ClassB -->
<StackPanel DataContext="{Binding ClassB}">
<!-- DataContext is set to ClassB, so will display ClassB.Name -->
<Label Content="{Binding Name}" />
<!-- DataContext is still ClassB, but we are binding to the Window's DataContext.Name which is ClassA.Name -->
<Label Content="{Binding ElementName=myWindow, Path=DataContext.Name}" />
</StackPanel>
</StackPanel>
</Window>
As you can see, the DataContext is based on whatever data is behind the UI object.
Update: I see this question so often from new WPF users that I expanded this answer into a post on my blog: What is this “DataContext” you speak of?
From CodeProject by kishore Gaddam:
DataContext is one of the most fundamental concepts in Data Binding. The Binding object needs to get its data from somewhere, and there are a few ways to specify the source of the data like using Source property directly in the Binding, inheriting a DataContext from the nearest element when traversing up in the tree, setting the ElementName and RelativeSource properties in the Binding object.
Detailed example on CodeProject: http://www.codeproject.com/Articles/321899/DataContext-in-WPF
In that particular case, you could do:
<Controls:SearchSettings DataContext="{Binding Path=Settings}" Settings="{Binding}" />
Assuming you want everything that may be content of the SearchSettings to use Settings as it's data context. Basically, the DataContext affects the element itself an any descendants that don't explicitly override it.
In most cases you do want to bind to the DataContext, in some templates on ItemsControls it is the only way to bind to the currently templated item for example. Further bindings to the DataContext are nice to write and read as they are concise.
In your example you can still set the DataContext, you only need to modify the binding on the Settings respectively:
<Controls:SearchSettings DataContext="{Binding Settings}" Settings="{Binding}"/>

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

Resources