I am currently facing a little problem with specifing or not specifing the datacontext of a window, and why there is a difference between various methods. Hope you can help me out.
Lets start with some code to show my problem. This is the code behind for my TestWindow.xaml.cs, nothing really special about it just a simple string property
public partial class TestWindow : Window
{
private string _helloWorld = "Hello World!";
public string HelloWorld
{
get { return _helloWorld; }
set { _helloWorld = value; }
}
public TestWindow()
{
InitializeComponent();
}
}
This code will be the same for all 3 following XAML layouts, so no changes behind the code only in XAML.
1.) Databinding with given ElementName
<Window x:Class="Ktsw.Conx.ConxClient.TestWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="TestWindow" Height="300" Width="300"
Name="TestWin">
<Grid>
<TextBlock Text="{Binding HelloWorld, ElementName=TestWin}"></TextBlock>
</Grid>
</Window>
2.) Databinding with specifing DataContext on Window
<Window x:Class="Ktsw.Conx.ConxClient.TestWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="TestWindow" Height="300" Width="300"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid>
<TextBlock Text="{Binding HelloWorld}"></TextBlock>
</Grid>
</Window>
3.) Neither ElementName nor specifing DataContext
<Window x:Class="Ktsw.Conx.ConxClient.TestWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="TestWindow" Height="300" Width="300">
<Grid>
<TextBlock Text="{Binding HelloWorld}"></TextBlock>
</Grid>
</Window>
The first two methods work just fine, but why fails the 3rd?
In the first method I am not specifing the DataContext and it works automatically, in the second method I am not specifing the ElementName and it works, but without declaring one of those it fails. Why would it fail getting both automatically, but work fine with getting each individually?
Read the Remarks for the Binding.Source property. The binding source is the object on which to look up the property specified by Path (HelloWorld). ElementName, RelativeSource, and Source set the binding source. If they are null, the source is the DataContext of the element that you are binding (TextBlock). If an element's DataContext is not explicitly set, it's inherited from a containing element.
In the first case, any DataContext is irrelevant to the TextBlock binding, because the source is being set explicitly through ElementName.
In the second case, a DataContext is necessary to specify a source because it is not being set explicitly through ElementName, RelativeSource, or Source. TextBlock's DataContext is not set, so Window's is inherited.
In the third case, there is no explicit source and no DataContext to inherit, so the source is null and binding fails. There is no default source.
{Binding} by default always refers to the DataContext.
In your first example you simply deactivate the default behavior by using elementName, this uses the element as source then.
In your second example you explicitly change the DataContextto point at your Window.
So in the last example the {Binding HelloWorld} tries to convert null into and Object with a HelloWorld property which fails.
It is working in 1st and 2nd case because TextBlock is able to find HelloWorld property
In 1st case you are specifying ElemtnName so TextBlock will refer to Window and search for property HelloWorld in Window class.
In 2nd case you are specifying DataContext of Window so Textblock will inherit that and will look for HelloWorld property in DataContext i.e. again Window class
In 3rd case you aren't specifying anything so TextBlock is unable to find HelloWorld property
In 1st case I am not specifing a DataContext so why should it know
what to get?
When you are setting ElementName, TextBlock will try to find HelloWorld from that element
In 2nd case I am not specifing what it should get?
You are setting the DataContext of it's parent that is Window so it automatically inherits that and you are telling it to extract HelloWorld property from DataContext
The third fails because the DataContext is not inferred. If you wanted the third to work, you'd do something like this:
public TestWindow()
{
InitializeComponent();
this.DataContext = this;
}
It doesn't know anything about the path HelloWorld because it doesn't have a DataContext.
Related
I'm trying to refactor the property MyText to a new name HerText in the following solution:
MainWindow.xaml.cs
using System.Windows;
namespace resharper_refactoring_xaml
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
MyText = "Blabla";
DataContext = this;
}
public string MyText { get; set; }
}
}
MainWindow.Xaml
<Window x:Class="resharper_refactoring_xaml.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:resharper_refactoring_xaml"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<TextBlock Text="{Binding Path=MyText}"></TextBlock>
</Grid>
</Window>
I right click on the property and select Refactor this > Rename. Then I type in a new name for the property, hit Next.
Unfortunately, only the references of MyText in the code-behind are renamed. References to MyText in the XAML file rename intact.
According to this question Resharper should be able to propagate refactorings to XAML files.
Why is the rename not propagating to the XAML file? Is there some sort of Resharper setting I might have overlooked?
The reason behind this seems to be that ReSharper cannot determine that the property name specified in the XAML markup refers to the property defined in the MainWindow class, if the DataContext property is set in code-behind.
Bindings refer to the DataContext of controls as source by default. If it is not detected, the link between the loose markup and the defining type is lost. I cannot tell if this is a bug in ReSharper or a general limitation.
However, there are two simple solutions to this issue that work for me:
Set a design time data context to the type that defines the property here MainWindow.
<Window ...
d:DataContext="{d:DesignInstance Type={x:Type local:MainWindow}}">
Set the data context via binding in XAML instead of code-behind.
<Window ...
DataContext="{Binding RelativeSource={RelativeSource Self}}">
I am very sorry that this question is very basic. I just learned WPF and I failed to make simple two way binding to textbox.text to string property.
XAML Code:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication1"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid x:Name="StuInfo">
<TextBox x:Name="textBox" HorizontalAlignment="Left" Height="23" Margin="10,26,0,0" TextWrapping="Wrap" Text="{Binding Path=str,Mode=TwoWay}" VerticalAlignment="Top" Width="120"/>
<Button x:Name="button" Content="Check" HorizontalAlignment="Left" Margin="10,67,0,0" VerticalAlignment="Top" Width="75" Click="button_Click"/>
</Grid>
C# Code
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
str = "OK";
}
public string str { get; set; }
private void button_Click(object sender, RoutedEventArgs e)
{
Console.WriteLine(str);
}
}
First, the textbox does not show "OK", but it is blank. Then, I typed a different text into the textbox, for ex:"blablabla" without the quotes. Then I click the button to check if my str property has been updated. Apparently, str still contains "OK".
What did I do wrong here? What did I miss to make the binding work?
As a newcomer to WPF, all this Binding and DataContext jazz can be quite confusing. Let's start with your binding expression first...
<TextBox Text="{Binding Path=str, Mode=TwoWay}"/>
What this is saying is that you want to bind your Text property to whatever the DataContext of the TextBox is. DataContext is essentially the "thing" your TextBox is getting it's data from. Now here's the rub. DataContext is inherited from the element "above" it in the visual tree if not explicitly set. In your code, TextBox inherits it's DataContext from the Grid element, which in turn inherits it's DataContext from the Window element. Seeing that DataContext is not set in your Window the default value of the DataContext property will be applied, which is null. The DataContext is also not set in any of the child elements of your window, which, via inheritance, will set the DataContext of all children of that window to null.
It is important to note that you've left out the Source property in your binding expression.
<TextBox Text="{Binding Source=left_out, Path=str, Mode=TwoWay}"/>
When this property is left out, the binding's source is implied to be the elements DataContext, which in this case is null, for the reasons mentioned above. Basically, what your expression is saying here is that you want to bind your text property to DataContext.str which resolved by WPF is null.str.
OK, cool. Now, how do we set the DataContext of your TextBox.Text binding to the Code Behind for the window so we can get at that str property? There are several ways to do this, but for our purposes we'll focus on setting it explicitly in the binding of the TextBox.Text property. Now, there are three different "source" type properties of bindings. "Source" being where we want our control/element's binding to get it's data from. We have Source, RelativeSource, and ElementName. We're only going to focus on ElementName here, but the others are essential to research and understand.
So, let's name our Window element so we can access it through the ElementName property.
<Window x:Class="WpfApplication1.MainWindow"
x:Name="_window"
...
Now we can set the ElementName property on the TextBox.Text binding to refer to the window.
<TextBox Text="{Binding ElementName=_window, Path=str, Mode=TwoWay}"/>
This means the binding will look for the _window.str property when trying to resolve it's binding. At this point, you still probably won't see your str value reflected in the TextBox. This is because it's value is set after the InitializeComponent method in the window's constructor. This function is where bindings are resolved for the first time. If you were to set the value of str before calling InitializeComponent, you would see the value reflected in the TextBox.
This brings us to Dependency Properties. For now, just know that Dependency Properties have built in change notification, which your binding needs so it "knows" when the binding has changed and when to resolve the binding value again. Yes, you could use INotifyPropertyChanged in your code behind, but there are good arguments for using DependencyProperties in this case, which will only confuse the issue at this point. But, it is another one of those things that is essential to understand.
Here is the code for a DependencyProperty for your str property.
public static readonly DependencyProperty StrProperty
= DependencyProperty.Register("Str", typeof(string), typeof(MainWindow),
new FrameworkPropertyMetadata(FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public string Str
{
get{return (string)GetValue(StrProperty);}
set{SetValue(StrProperty,value);}
}
Now you'll be able to set the value like such and have it reflect through the binding to your TextBox.
public MainWindow()
{
InitializeComponent();
Str = "OK";
}
At this point, all should be well. I hope this helps out. It took me a while get the hang of WPF. My suggestion would be to read as much as you can on DataContext, Binding, and DependencyProperty as these are the core of WPF. Good luck!
The problem is that, you dont bind to codebehind of Window, but to DataContext.
Try this:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new DC();
}
public class DC
{
public string str { get; set; }
public DC()
{
str = "OK";
}
}
}
Normally, you would have two different files, but for test, you can do it in one file.
After that, your DC (DataContext) should implement INotifyPropertyChanged interface.
Try to find some article about MVVM like this http://www.codeproject.com/Articles/165368/WPF-MVVM-Quick-Start-Tutorial
I have 2 Windows. From the first window I'm calling second :
var window = new WindowButtonClick("Graphic") {DataContext = new GraphicViewModel()};
window.ShowDialog();
Here is XAML of second window:
<Window x:Class="WindowButtonClick"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:graphic="clr-namespace:Windows.Graphic"
WindowStartupLocation="CenterScreen" >
<Window.Resources>
<DataTemplate DataType="{x:Type graphic:GraphicViewModel}">
<graphic:Graphic />
</DataTemplate>
</Window.Resources>
<Grid>
<ContentControl Content="{Binding}"/>
</Grid>
and constructor:
public WindowButtonClicks(string title)
{
InitializeComponent();
Title = Application.Current.Resources[title].ToString();
}
So how can I set DataContext, that it will show title that I pass in constructor as window Title and ContentControl will show one of the viewModels(GraphicViewModel in this case) ?
This is a common problem in WPF. Luckily, it has a simple solution. You'll need to use a RelativeSource Binding. So you'll need to set the DataContext to one object, whose properties you can data bind simply to like this:
<TextBox Text="{Binding PropertyOfDataContext}" />
And for any properties that are declared in the Window or UserControl, you can use the RelativeSource Binding like this:
<TextBox Text="{Binding PropertyOfWindow, RelativeSource={RelativeSource AncestorType={
x:Type YourXamlPrefix:YourWindow}}}" />
UPDATE >>>
You said:
I will have 20 ViewModels, that I want to load to ContentControl
If you had only provided all of the relevant information when asking your question, then you would have had a better answer by now. This is a different problem, but can be fixed just as easily. In this case, you can just set your view models to their views using DataTemplates... just define one for each view model/view pair like this:
<DataTemplate DataType="{x:Type ViewModels:ViewModel1}">
<Views:View1 />
</DataTemplate>
...
<DataTemplate DataType="{x:Type ViewModels:ViewModelN}">
<Views:ViewN />
</DataTemplate>
Note that I did not set the x:Key values... this means that the specified views will be implicitly rendered by the Framework whenever it comes across objects of the relevant type. Then to display the View1 from this example, you'd just need to do this:
<ContentControl Content="{PropertyOfTypeViewModel1}" />
UPDATE 2 >>>
Wow... I really hope that you've explained your problem properly this time because this is my last update. So I can't really see a problem with what you are asking for... you want to set a property in the constructor to be displayed as the Window.Title. This would definitely work:
public WindowButtonClicks(string title)
{
InitializeComponent();
Title = "Some Title";
}
So if your code doesn't work, then you must have a problem with your call to Application.Current.Resources[title]... have you actually checked whether that returns a value or not? If it does, then you have a real problem, because it is perfectly acceptable to set the Window.Title like this.
If Application.Current is returning null, then just make sure that you set it to an instance of MainWindow.xaml.cs in the code behind:
// In MainWindow.xaml.cs constructor
Application.Current = this;
Other than that, your problem is impossible to determine from the information that you have provided.
I have created a UserControl with some DependencyProperties (in the example here only one string property). When I instantiate the Usercontrol, I can set the property of the UserControl and it is shown as expected. When I am trying to replace the static text by Binding, nothing is displayed.
My UserControl looks as follows:
<User Control x:Class="TestUserControBinding.MyUserControl"
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"
d:DesignHeight="30" d:DesignWidth="100">
<Grid>
<Label Content="{Binding MyText}"/>
</Grid>
</UserControl>
The Code Behind is:
namespace TestUserControBinding {
public partial class MyUserControl : UserControl {
public MyUserControl() {
InitializeComponent();
this.DataContext = this;
}
public static readonly DependencyProperty MyTextProperty =
DependencyProperty.Register(
"MyText",
typeof(string),
typeof(MyUserControl));
public string MyText {
get {
return (string)GetValue(MyTextProperty);
}
set {
SetValue(MyTextProperty, value);
}
}// MyText
}
}
When I try this in my MainWindow, everything is as expected:
<Window x:Class="TestUserControBinding.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TestUserControBinding"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<local:MyUserControl MyText="Hello World!"/>
</StackPanel>
</Window>
But this doesn't work:
<Window x:Class="TestUserControBinding.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TestUserControBinding"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<local:MyUserControl MyText="{Binding Path=Text}"/>
<Label Content="{Binding Path=Text}"/>
</StackPanel>
</Window>
The behaviour of the label is correct, so there is no Problem with the Property "Text"
What is my mistake?
With the following binding in your UserControl:
<Label Content="{Binding MyText}"/>
I'm not sure how setting the text directly to the MyText property works. You must be setting the DataContext on the UserControl somewhere for this to work.
Regardless, this binding is the issue - as I understand your scenario, you don't want to bind to the DataContext of the UserControl because that will not necessarily have a MyText property. You want to bind to the UserControl itself, and specifically the DependencyProperty you created. To do that, you need to use a RelativeSource binding, like the following:
<Label Content="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:MyUserControl}}, Path=MyText}"/>
This will navigate up the visual tree to MyUserControl and then find the MyText property there. It will not be dependent on the DataContext, which will change based on where you place the UserControl.
In this case, local refers to a namespace you'll need to define in the UserControl:
<UserControl x:Class="TestUserControBinding.MyUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TestUserControBinding"
...>
And your second example should work at that point.
There is a misunderstanding of how DataContexts are set. This is working against you...
Ultimately the binding to MyText on the user control, is not bound to the control's MyText dependency property but to the page's DataContext and there is no MyText property.
Let me explain
Explanation When the user control is put on your main page, it inherits its controls parent's DataContext (the StackPanel). If the parent's DataContext is not set, it will move up the chain to the StackPanel's parent's DataContext (ad Infinium) until it gets to the page's DataContext (which in your example is set and valid).
When you bind on the main page such as <local:MyUserControl MyText="{Binding Path=Text}"/> it looks for Text property on the main pages DataContext and sets the dependency property MyText to that value. Which is what you expect and it works!
Current State
So the state of the user control in your code is this, its DataContext is bound to the page's DataContext and MyText dependency property is set. But the internal control's binding to MyText fails. Why?
The user control has the parent's data context, and you are asking the control to bind to a MyText property on that data context. There is no such property and it fails.
Resolution
To bind to the control's instance and get the value from MyText property, just put a name (an element name) on the control such as
<User Control x:Class="TestUserControBinding.MyUserControl"
...
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
x:Name="ucMyUserControl"
and then properly path the binding away from the default DataContext and to the elementnamed named instance called ucMyUserControl. Such as:
<Label Content="{Binding MyText, ElementName=ucMyUserControl }"/>
Note that VS2017/2019 will actually intellisense the ElementName after you have named the control.
Side Effect of Just Using The Parents Data Context
A side effect of the original situation without the resolution mentioned, is that you could just bind the user control's binding to Text and it will work because the binding is defaulting to the page's datacontext. Subtle...
<User Control x:Class="TestUserControBinding.MyUserControl"
mc:Ignorable="d"
d:DesignHeight="30" d:DesignWidth="100">
<Grid>
<Label Content="{Binding Text}"/>
That works and technically you could remove the dependency property. If the control is not used outside the project, it could be designed to bind to other named properties with no ill effect as well.
Then all usercontrols could become defacto sub controls of the main page, as if you just pasted the internal XAML onto the page.
I keep trying to make this hurdle in WPF, and I think I've found a solution, albeit an ugly one.
The scenario is as follows:
I have a custom user control with a custom dependency property.
The user controls can be nested inside of my other user controls.
Each of my user controls has a data context that is specified by a locator (I am following the MVVM pattern)
I want to bind the custom dependency property to a value in the parent view model.
Code...
Parent View
<UserControl DataContext="{Binding Source={StaticResource Locator}, Path=ParentControlLocator}">
<my:Child Demo="{Binding Path=DataContext.DemoTextAlpha, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl, AncestorLevel=1}}" />
</UserControl>
Parent Class View Model
public class ParentClassViewModel : BaseViewModel
{
private string _demoTextAlpha = "Some Alpha text";
public string DemoTextAlpha
{
get
{
return this._demoTextAlpha;
}
set
{
this._demoTextAlpha = value;
this.NotifyPropertyChange("DemoTextAlpha");
}
}
}
Child View
<UserControl DataContext="{Binding Source={StaticResource Locator}, Path=ChildControlLocator}">
<TextBlock Text="{Binding Path=SomeProperty}" />
</UserControl>
Child View Code Behind
public partial class Child : UserControl
{
public Child()
{
InitializeComponent();
}
public static readonly DependencyProperty DemoProperty =
DependencyProperty.Register("Demo",
typeof(string),
typeof(Child),
new FrameworkPropertyMetadata()
{
PropertyChangedCallback = OnDemoChanged,
BindsTwoWayByDefault = true
});
public string Demo
{
get { return this.GetValue(DemoProperty).ToString(); }
set { this.SetValue(DemoProperty, value); }
}
private static void OnDemoChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = (Child)d;
var viewModel = (ChildViewModel)control.DataContext;
viewModel.SomeProperty = (string)e.NewValue;
}
}
Child View Model
public class ChildViewModel : BaseViewModel
{
private string _someProperty;
public string SomeProperty
{
get
{
return _someProperty;
}
set
{
_someProperty = value;
this.NotifyPropertyChange("SomeProperty");
}
}
}
Ok, so this WORKS. What I'm trying to achieve is better/ more elegant code, particularly as it regards to this statement.
<my:Child Demo="{Binding Path=DataContext.DemoTextAlpha, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl, AncestorLevel=1}}" />
Even that I could live with, as far as elegance goes, but one thing that is bothering me right now is that when I type
Path=DataContext.DemoTextAlpha
The intellisense drops when I try to drill down inside the DataContext. So I have to be extra careful to type everything right.
So - is there any different way to make the properties of the DataContext appear in intellisense, or is there an alternative way to achieve the same thing that I'm doing now?
Thanks.
EDIT to Clarify
When I put something like this instead of specifying the relative source as in the above examples...
<my:Child Demo="{Binding DemoTextAlpha}"/>
I receive an error...
System.Windows.Data Error: 40 : BindingExpression path error: 'DemoTextAlpha' property not found on 'object' ''ChildViewModel' (HashCode=34126977)'. BindingExpression:Path=DemoTextAlpha; DataItem='ChildViewModel' (HashCode=34126977); target element is 'Child' (Name=''); target property is 'Demo' (type 'String')
The DataContext (along with a lot of other properties such as FontSize) is "Inherited" along the visual tree. Therefore this:
<UserControl DataContext="{Binding Source={StaticResource Locator}, Path=ParentControlLocator}">
<my:Child Demo="{Binding Path=DataContext.DemoTextAlpha, RelativeSource={RelativeSource FindAncestor, AncestorType=UserControl, AncestorLevel=1}}" />
</UserControl>
Is exactly the same as this:
<UserControl DataContext="{Binding Source={StaticResource Locator}, Path=ParentControlLocator}">
<my:Child Demo="{Binding DemoTextAlpha}"/>
</UserControl>
With regards to the Intellisense support, I don't know what VS version you're using, but I'm using VS 2010 Pro with ReSharper 6.1 and it adds Intellisense support if you specify the d:DataContext value:
<UserControl x:Class="...etc."
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TheViewModelNamespace"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d" d:DataContext="{d:DesignInstance local:ViewModel}">
Edit:
Ok.. let's analize what you're doing here:
1 - Binding the UserControl to the ParentVM:
ParentVM -> UserControl
2 - Using RelativeSource To Grab some property from ParentVM and place it into a Custom DP you created in the Child control
ParentVM -> UserControl -> Child Control
3 - In the OnPropertyChanged of the custom DP, setting that same value to the ChildVM
ParentVM -> UserControl -> Child Control -> ChildVM
Do you realize you're using the View (User Control, Child Control) as an intermediate to share some properties between 2 View Models? Why don't you just
ParentVM -> ChildVM
Which would be easier, cleaner and really MVVM?
Either put a reference from the ParentVM directly to the ChildVM, or use something like a Messenger pattern to have indirect communication between them.
DataContext is inherited:
<UserControl DataContext="{Binding Source={StaticResource Locator}, Path=ParentControlLocator}">
<my:Child Demo="{Binding DemoTextAlpha}" />
</UserControl>
If, ina different scenario, your child control has a different DataContext specified and you still need to bind to a property of your parent control's DataContext, using ElementName is probably nicer:
<UserControl x:Name="Parent" DataContext="{Binding Source={StaticResource Locator}, Path=ParentControlLocator}">
<my:Child Demo="{Binding Path=DataContext.DemoTextAlpha, ElementName=Parent}" />
</UserControl>