I have a question regarding the Data Context of a Window and how it is inherited by the children controls.
If I have a Window, whose DataContext
property is set in XAML like such:
<Window.DataContext>
<local:SomeViewModel />
</Window.DataContext>
By adding a user control to the window, I understand that the user control will have its data context inherited from the window (unless I specify otherwise).
<local:MyUserControl />
What about within the user control? Since it is a different XAML file, how can I strongly type the Data Context within the user control? So if I specify a data context within the control:
<UserControl.DataContext>
<local:SomeViewModel />
</UserControl.DataContext>
Does that override the Window's instance of the view model, creating a new instance in memory? I assume it does and if so, how can I pass around a view model to children views via xaml? I know I can do it in code-behind with direct assignments but I want this to be handled in xaml.
We've segregated the majority of our UI and currently have to manually assign the context in code behind.
I tried using RelativeSource
but it did not seem to work. Perhaps I was using it wrong, but the context was never passed around.
Any thoughts?
Update 1
To clarify, I present a simple Window with a DataContext set to a custom view model.
<Window x:Class="MyProject.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:viewModels="clr-namespace:MyProject.ViewModels"
xmlns:views="clr-namespace:MyProject.MyCustomView">
<Window.DataContext>
<viewModels:ProjectViewModel />
</Window.DataContext>
<StackPanel>
<views:MyCustomView />
</StackPanel>
<Window>
Now within my MyCustomView
user control, the other developer working on it will not know what the Type of the Data Context is with out manually walking through all of the possible parent Window's to see where it is being used. What I would like, is within my UserControl, to do the following:
<UserControl x:Class="MyProject.Views.DiaryDetailsDescription"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d" >
<UserControl.DataContext Type="viewModels:ProjectViewModel />
</UserControl>
So that the designer/developer working on that user control knows that the data context for that user control will be the ProjectViewModel
type, inherited by the owning Window.
Update 2
So to further clarify, what I want to do in my User Control XAML is the equivalent to the following C# code.
return (SingleViewModel)this.DataContext;
So the Designer in Blend knows exactly what type the DataContext will be. To him, the DataContext is just an object in the user control, even though it inherits the SingleViewModel
context from the Window.
Maybe you should try to use a bunch DataTemplate + UserControl
? In Resources e.g. in Window create DataTemplate
with your UserControl:
<Window.Resources>
<DataTemplate DataType="{x:Type vm:SingleViewModel}">
<vw:SingleView /> <!-- Your UserControl -->
</DataTemplate>
</Window.Resources>
And in root Panel add the ContentControl
like this:
<ContentControl Name="MyContent"
Content="{Binding Path=CurrentViewModel}" />
Where CurrentViewModel may be SingleViewModel type.
In this case, we see immediately that for SingleView
DataContext using vm:SingleViewModel
type. For more info, see this
and this
.
Edit: more suitable option
You can also try use d:DesignInstance
:
Use
d:DesignInstance
for create data bindings at design time for a DataContext that is assigned at run time. To create the data binding, you use the data binding builder to create a special design-time data context and set the DesignInstance to a business object type.DesignInstance
is a design-time property.
It is used successfully in the Blend for assigning DataContext. d:DesignInstance
provides a technique for creating a non-faux type, setting the property IsDesignTimeCreatable
to True on the d:DesignInstance enables this.
For more information, please see this: