Reputation: 1559
I have the following controls embedding (not inheritance, just placing):
Native TextBlock is placed in MyMiddleControl, which is placed in MyGlobalControl. MyMiddleControl has a DependencyPropery "GroupName", which is binded to TextBox.Text. MyGlobalControl has a public property "MyText, which is binded to MyMiddleControl.GroupName.
XAML:
<UserControl x:Class="MyMiddleControl"
...
DataContext="{Binding RelativeSource={RelativeSource Mode=Self}}">
<TextBlock Text="{Binding Path=GroupName}"/>
</UserControl>
with
public static readonly DependencyProperty GroupNameProperty =
DependencyProperty.Register("GroupName", typeof(string),
typeof(MyMiddleControl),
new PropertyMetadata("default"));
public string GroupName
{
get { return (string)GetValue(GroupNameProperty); }
set { SetValue(GroupNameProperty, value); }
}
and
<UserControl x:Class="MyGlobalControl"
...
DataContext="{Binding RelativeSource={RelativeSource Mode=Self}}">
<MyMiddleControl GroupName="{Binding MyText}"... />
</UserControl>
with
public string _myText = "myDef";
public string MyText
{
get { return _myText ; }
set { _myText = value; }
}
Problem #1. When I run the program I see "default" in the textblock instead of "myDef".
Problem #2. I have the button which do:
private void TestButton_Click(object sender, RoutedEventArgs e)
{
MyText = "TestClick";
}
The result is the same: "default".
Why? :(
Update:
I forget to say. If I do
<UserControl x:Class="MyGlobalControl"
...
DataContext="{Binding RelativeSource={RelativeSource Mode=Self}}">
<MyMiddleControl GroupName="FixedTest"... />
</UserControl>
It works fine.
PS. The sample project with changes from the first answer: TestBind.zip.
Upvotes: 1
Views: 699
Reputation: 14601
you must implement INotifyPropertyChanged to notify changes for a binded property
public class SampleData : INotifyPropertyChanged
{
public SampleData ()
{
this.MyText = "myDef";
}
public string _myText;
public string MyText
{
get { return _myText ; }
set {
_myText = value;
this.RaisePropChanged("MyText");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropChanged(string name) {
var eh = this.PropertyChanged;
if (eh != null) {
eh(this, new PropertyChangedEventArgs(name));
}
}
}
hope that helps
EDIT try following solution with setting x:Name and DataContext in code behind
public partial class MyMiddleControl : UserControl
{
public MyMiddleControl() {
this.DataContext = this;
this.InitializeComponent();
}
public static readonly DependencyProperty GroupNameProperty =
DependencyProperty.Register("GroupName", typeof(string),
typeof(MyMiddleControl),
new PropertyMetadata("default"));
public string GroupName {
get { return (string)this.GetValue(GroupNameProperty); }
set { this.SetValue(GroupNameProperty, value); }
}
}
<UserControl x:Class="TestBind.MyMiddleControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Name="middleControl">
<Grid>
<TextBlock Height="40" HorizontalAlignment="Left" Margin="45,23,0,0"
Name="textBlock1" Text="{Binding ElementName=middleControl, Path=GroupName}"
VerticalAlignment="Top" Width="203" />
</Grid>
</UserControl>
public partial class MyGlobalControl : UserControl, INotifyPropertyChanged
{
public MyGlobalControl() {
this.DataContext = this;
this.InitializeComponent();
this.MyText = "myDef";
}
public string _myText;
public string MyText {
get { return this._myText; }
set {
this._myText = value;
this.OnPropertyChanged("MyText");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName) {
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null) {
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
private void button1_Click(object sender, RoutedEventArgs e) {
this.MyText = "btnClick";
}
}
<UserControl x:Class="TestBind.MyGlobalControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:my="clr-namespace:TestBind"
x:Name="globalControl">
<Grid>
<my:MyMiddleControl HorizontalAlignment="Left"
Margin="24,82,0,0"
x:Name="myFloatTest"
GroupName="{Binding ElementName=globalControl, Path=MyText}"
VerticalAlignment="Top" />
<Button Content="Button"
Height="23"
HorizontalAlignment="Left"
Margin="296,65,0,0"
Name="button1"
VerticalAlignment="Top"
Width="75"
Click="button1_Click" />
</Grid>
</UserControl>
Upvotes: 2