WPF bind point to UserControl - c#

I have a user control that contains 2 DoubleUpDown, I have bound point to that controls
<DoubleUpDown x:Name="X" Grid.Column="1" Grid.Row="0" Value="{Binding Path=Value.X, Mode=TwoWay" />
<DoubleUpDown x:Name="Y" Grid.Column="1" Grid.Row="1" Value="{Binding Path=Value.Y, Mode=TwoWay}" />
controls get updated pretty well when I change Value from outside, but Value stays unchanged when I change controls data.
I bound Value to user control from code inside
Point2DEditorView editor = new Point2DEditorView();
Binding binding = new Binding("Value");
binding.Mode = BindingMode.TwoWay;
editor.SetBinding(Point2DEditorView.ValueProperty, binding);
and Point2DEditorView.Value also changed when I insert new coordinates into controls. But that does not affect bound Value.

Point is a value type data. Because of this when you bind it to control boxing and unboxing occurs. For more information see this. So, you may easy solve this problem by creating your own class (not struct!):
class MyPoint
{
public int X { set; get; }
public int Y { set; get; }
}
And then bind this objects to your control and you will see that all works as you expect.
Update
First of all your DoubleUpDown is'n in standart FCL and I think your problem in it. There is a simple example where all works as expect. I created a simple UpDown control for it:
Point class
public class Point2D : INotifyPropertyChanged
{
private double x;
private double y;
public double X
{
set
{
if (value.Equals(x)) return;
x = value;
OnPropertyChanged();
}
get { return x; }
}
public double Y
{
set
{
if (value.Equals(y)) return;
y = value;
OnPropertyChanged();
}
get { return y; }
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
UpDown xaml
<UserControl x:Name="doubleUpDown" x:Class="PointBind.DoubleUpDown"
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:DesignWidth="105" Height="33">
<StackPanel Orientation="Horizontal" DataContext="{Binding ElementName=doubleUpDown}">
<TextBox Margin="5,5,0,5" Width="50" Text="{Binding Value}" />
<Button x:Name="Up" x:FieldModifier="private" Margin="5,5,0,5" Content="˄" Width="20" Click="Up_Click" />
<Button x:Name="Down" x:FieldModifier="private" Margin="0,5,0,5" Content="˅" Width="20" Click="Down_Click" />
</StackPanel>
</UserControl>
UpDown .cs
public partial class DoubleUpDown : UserControl
{
public double Value
{
get { return (double)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
// Using a DependencyProperty as the backing store for Value. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("Value", typeof(double), typeof(DoubleUpDown), new PropertyMetadata(0.0));
public DoubleUpDown()
{
InitializeComponent();
DataContext = this;
}
private void Up_Click(object sender, RoutedEventArgs e)
{
Value++;
}
private void Down_Click(object sender, RoutedEventArgs e)
{
Value--;
}
}
Point2DEditorView xaml
<UserControl x:Name="point2DEditorView" x:Class="PointBind.Point2DEditorView"
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"
xmlns:local="clr-namespace:PointBind"
d:DesignHeight="300" d:DesignWidth="300">
<StackPanel>
<local:DoubleUpDown Value="{Binding Point.X, ElementName=point2DEditorView, Mode=TwoWay}"/>
<local:DoubleUpDown Value="{Binding Point.Y, ElementName=point2DEditorView, Mode=TwoWay}"/>
</StackPanel>
</UserControl>
UpDown .cs
public partial class Point2DEditorView : UserControl
{
public Point2D Point
{
get { return (Point2D)GetValue(PointProperty); }
set { SetValue(PointProperty, value); }
}
// Using a DependencyProperty as the backing store for Point. This enables animation, styling, binding, etc...
public static readonly DependencyProperty PointProperty =
DependencyProperty.Register("Point", typeof (Point2D), typeof (Point2DEditorView),
new PropertyMetadata(new Point2D {X = 10, Y = 20}));
public Point2DEditorView()
{
InitializeComponent();
}
}
Test form xaml
<Window x:Class="PointBind.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:PointBind"
Title="MainWindow" Height="350" Width="525">
<Grid>
<local:Point2DEditorView x:Name="pointEditor"/>
<Button Content="Button" HorizontalAlignment="Left" Margin="39,121,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
</Grid>
</Window>
And test form .cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
pointEditor.Point = new Point2D{X = 300, Y = 400};
}
}
Hope this helps.

Related

WPF Binding and Observable Model fail

In a simple trying-to-learn-WPF experiment I'm trying to bind a property ("InternalName") of an instance of MyModel to the contents of TextBlock "MainWindowTextBlock". Clicking the ``ChangeNameButton" changes the InternalName property of mymodel, but that property change never makes it through to the TextBlock. Nothing happens. What am I doing wrong?
XMAL
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:UserControlExperiments"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<StackPanel Grid.Row ="0">
<Button Width="100" Height="20" Name="ChangeName" Content="Change the Name" Click="ChangeNameButtonClick"/>
<TextBlock Text=""/>
<TextBlock Name="MainWindowTextBox" Width="100" Height="20" Text="{Binding Path = mymodel.InternalName, Mode=TwoWay}"/>
</StackPanel>
</Grid>
</Window>
CODE BEHIND
public partial class MainWindow : Window
{
public MyModel mymodel;
public MainWindow()
{
InitializeComponent();
DataContext = this.DataContext;
mymodel = new MyModel("The old name");
}
private void ChangeNameButtonClick(object sender, RoutedEventArgs e)
{
mymodel.InternalName = "A new name!";
}
}
public class MyModel : INotifyPropertyChanged
{
private string internalname;
public event PropertyChangedEventHandler PropertyChanged;
public MyModel(string nm)
{
InternalName = nm;
}
protected void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public string InternalName
{
get { return internalname; }
set
{
if (internalname != value)
{
internalname = value;
OnPropertyChanged("InternalName");
}
}
}
}
}
The following markup tries to bind to a property named "mymodel" of the current DataContext of the TextBlock, which is inherited from the parent window:
<TextBlock Name="MainWindowTextBox"
Text="{Binding Path = mymodel.InternalName}"/>
So you need to set the DataContext of the window to itself:
DataContext = this;
And you also need to make mymodel a public property since you cannot bind to fields:
public MyModel mymodel { get; }
Then it should work but you probably also want to change the name of the property to comply with the C# naming standards.
You can also remove Mode=TwoWay from the binding. It makes no sense for a TextBlock.

Usercontrol binding lost on value updated, that doesn't happen with standard textbox control

I have a problem with binding in usercontrol.
This is my usercontrol:
UserControl1.xaml
<UserControl x:Class="WpfApp1.UserControl1"
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-ompatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
x:Name="usercontrol"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<TextBox Text="{Binding HmiField, ElementName=usercontrol}"/>
</Grid>
</UserControl>
UserControl1.xaml.cs
namespace WpfApp1
{
public partial class UserControl1 : UserControl
{
public double HmiField
{
get { return (double)GetValue(HmiFieldProperty); }
set { SetValue(HmiFieldProperty, value); }
}
public static readonly DependencyProperty HmiFieldProperty =
DependencyProperty.Register("HmiField", typeof(double), typeof(UserControl1));
public UserControl1()
{
InitializeComponent();
}
}
}
And this is the main window:
MainWindow.xaml
<Window x:Class="WpfApp1.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:WpfApp1"
mc:Ignorable="d"
DataContext="{Binding Md, RelativeSource={RelativeSource Self}}"
Title="MainWindow" Height="450" Width="800">
<UniformGrid>
<Button Content="{Binding Prop1}" Click="Button_Click"/>
<Label Content="{Binding Prop1}"/>
<TextBox Text="{Binding Prop1}"/>
<local:UserControl1 HmiField="{Binding Prop1}"/>
</UniformGrid>
</Window>
MainWindow.xaml.cs
namespace WpfApp1
{
public class tMd: INotifyPropertyChanged
{
#region Interfaccia INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
}
#endregion
private double prop1;
public double Prop1 { get
{
return prop1;
}
set
{
if (prop1 != value)
{
prop1 = value;
NotifyPropertyChanged("Prop1");
}
}
}
}
public partial class MainWindow : Window
{
public tMd Md
{
get { return (tMd)GetValue(MdProperty); }
set { SetValue(MdProperty, value); }
}
public static readonly DependencyProperty MdProperty =
DependencyProperty.Register("Md", typeof(tMd), typeof(MainWindow), new PropertyMetadata(new tMd()));
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Md.Prop1 = 1234.5678;
}
}
}
I found some similar question:
How do I change TextBox.Text without losing the binding in WPF?
WPF: Binding is lost when bindings are updated
WPF Textbox TwoWay binding in datatemplate not updating the source even on LostFocus
But I can't completely understand what's happening: why a standard textbox work as expected and my usercontrol no?
Or better: is there a way to have my usercontrol works with the textbox's behaviour?
The Binding must be TwoWay, either set explicitly
<local:UserControl1 HmiField="{Binding Prop1, Mode=TwoWay}"/>
or implicitly by default:
public static readonly DependencyProperty HmiFieldProperty =
DependencyProperty.Register(
nameof(HmiField), typeof(double), typeof(UserControl1),
new FrameworkPropertyMetadata(
0d, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
A TextBox's Text property is registered like shown above, i.e. with the BindsTwoWayByDefault flag.
At the TextBox Binding in the UserControl's XAML you may also want to update the source property while the user is typing (instead of only on lost focus):
<TextBox Text="{Binding HmiField,
ElementName=usercontrol,
UpdateSourceTrigger=PropertyChanged}"/>
or without the otherwise useless generated usercontrol field:
<TextBox Text="{Binding HmiField,
RelativeSource={RelativeSource AncestorType=UserControl}
UpdateSourceTrigger=PropertyChanged}"/>
Your Prop1 notifies when it changes, but you haven't told you binding to trigger on that notification.
Try including UpdateSourceTrigger=PropertyChanged in you binding

WPF usercontrol Twoway binding Dependency Property

I created a Dependency Property in the usercontrol, but however changes in the usercontrol was NOT notified to the Viewmodel
Usercontrol
<UserControl x:Class="DPsample.UserControl1"
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="300" d:DesignWidth="300">
<Grid>
<TextBox x:Name="txtName"></TextBox>
</Grid>
UserControl.cs
/// <summary>
/// Interaction logic for UserControl1.xaml
/// </summary>
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
#region SampleProperty
public static readonly DependencyProperty SamplePropertyProperty
= DependencyProperty.Register("SampleProperty",
typeof(string),
typeof(UserControl1),
new PropertyMetadata(OnSamplePropertyChanged));
public string SampleProperty
{
get { return (string)GetValue(SamplePropertyProperty); }
set { SetValue(SamplePropertyProperty, value); }
}
static void OnSamplePropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
(obj as UserControl1).OnSamplePropertyChanged(e);
}
private void OnSamplePropertyChanged(DependencyPropertyChangedEventArgs e)
{
string SamplePropertyNewValue = (string)e.NewValue;
txtName.Text = SamplePropertyNewValue;
}
#endregion
}
MainWindow
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:DPsample" x:Class="DPsample.MainWindow"
Title="MainWindow" Height="350" Width="525">
<Grid>
<local:UserControl1 SampleProperty="{Binding SampleText,Mode=TwoWay}" HorizontalAlignment="Left" Margin="76,89,0,0" VerticalAlignment="Top" Width="99"/>
<Button Content="Show" HorizontalAlignment="Left" Margin="76,125,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
</Grid>
MainWindow.cs
public MainWindow()
{
InitializeComponent();
this.DataContext = new MainViewModel();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
var item = this.DataContext as MainViewModel;
MessageBox.Show(item.SampleText.ToString());
}
MainViewModel.cs
public class MainViewModel : NotifyViewModelBase
{
public MainViewModel()
{
this.SampleText = "test";
}
private string _sampleText;
public string SampleText
{
get { return _sampleText; }
set { _sampleText = value; OnPropertyChanged("SampleText"); }
}
}
Bind the TextBox.Text property in the UserControl to its SampleProperty like this:
<TextBox Text="{Binding SampleProperty,
RelativeSource={RelativeSource AncestorType=UserControl}}"/>
Now you could simply remove your OnSamplePropertyChanged callback.
You might also register SampleProperty to bind two-way by default like this:
public static readonly DependencyProperty
SamplePropertyProperty = DependencyProperty.Register(
"SampleProperty", typeof(string), typeof(UserControl1),
new FrameworkPropertyMetadata(
null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
An alternative way to do this is an ElementName Binding. First assign the x:Name attribute to the UserControl (for example x:Name="MyUC"), then change the binding to:
<TextBox Text="{Binding ElementName=MyUC, Path=SampleProperty}"/>

Relations between UserControl and MainWindow

How could I make possible to access data/properties from a UserControl and the parent, MainWindow (and viceversa)? For example, say I have a TextBox in my MainWindow called mainTextBox. Then I create a UserControl with another TextBox called ucTextBox. I also have a button called ucButton in the UserControl that should popup a MessageBox with the product of the values mainTextBox.Text * ucTextBox.Text (converted to double, to make it work).
What I really want to know is how to achieve to do this dynamically, with a button that allows to create more UserControls that are capable to interact with the parent. In this case it makes no sense to name every UserControl.
I've tried several things, mainly with get,set properties but with no desired outcome.
I'm not sure if I need to use UserControl, but it seems to, I've read that CustomControl is for a deep customization but I don't need that.
Here is just a quick sample to get you started (and what probably was meant by mr. #Adriano):
RootViewModel.cs:
public class RootViewModel :INotifyPropertyChanged
{
#region Implementation of INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged = delegate {};
private void OnPropertyChanged(string propertyName)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
private double _x;
private double _y;
public double X
{
get { return _x; }
set
{
_x = value;
OnPropertyChanged("X");
}
}
public double Y
{
get { return _y; }
set
{
_y = value;
OnPropertyChanged("Y");
}
}
public double XY
{
get { return _x * _y; }
}
}
UserControl1.xaml:
<UserControl x:Class="WpfApplication2.UserControl1"
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:DesignWidth="200">
<Grid>
<GroupBox Header="User Control">
<StackPanel>
<Label Content="Y:" />
<TextBox Text="{Binding Path=Y, UpdateSourceTrigger=PropertyChanged, FallbackValue=1}" Margin="5" />
<Button Content="Press me" Click="OnButtonClick" />
</StackPanel>
</GroupBox>
</Grid>
UserControl1.xaml.cs:
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
private void OnButtonClick(object sender, RoutedEventArgs e)
{
var viewModel = (RootViewModel)DataContext;
var resultMessage = string.Format("{0} * {1} = {2}", viewModel.X, viewModel.Y, viewModel.XY);
MessageBox.Show(resultMessage, "X * Y");
}
}
MainWindow.xaml:
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:WpfApplication21="clr-namespace:WpfApplication2"
Title="Main Window" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<StackPanel>
<Label Content="X:" />
<TextBox Text="{Binding Path=X, UpdateSourceTrigger=PropertyChanged, FallbackValue=1}" Margin="5" Height="24" />
</StackPanel>
<WpfApplication21:UserControl1 Grid.Row="1" Margin="5" />
</Grid>
MainWindow.xaml.cs:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new RootViewModel
{
X = 5,
Y = 7
};
}
}

Binding on DependencyProperty of custom User Control not updating on change

I'm having difficulties with databinding on my custom user control (s). I created an example project to highlight my problem. I'm completely new to WPF and essentially MVVM as well, so bear with me...
I created a simple view that uses databinding two ways. The databinding on the built-in control works just fine. My custom control doesn't... I put a breakpoint in the PropertyChangedCallback of my control. It gets hit once on startup, but then never again. Meanwhile, the label I have bound to the same value is happily counting down.
What am I missing? My example project follows:
The main window:
<Window x:Class="WpfMVVMApp.MainWindow"
xmlns:local="clr-namespace:WpfMVVMApp"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.DataContext>
<local:CountdownViewModel />
</Grid.DataContext>
<Label Name="custName" Content="{Binding Path=Countdown.ChargeTimeRemaining_Mins}" Height="45" VerticalAlignment="Top"></Label>
<local:UserControl1 MinutesRemaining="{Binding Path=Countdown.ChargeTimeRemaining_Mins}" Height="45"></local:UserControl1>
</Grid>
</Window>
Here's my model:
namespace WpfMVVMApp
{
public class CountdownModel : INotifyPropertyChanged
{
private int chargeTimeRemaining_Mins;
public int ChargeTimeRemaining_Mins
{
get
{
return chargeTimeRemaining_Mins;
}
set
{
chargeTimeRemaining_Mins = value;
OnPropertyChanged("ChargeTimeRemaining_Mins");
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
}
The ViewModel:
namespace WpfMVVMApp
{
public class CountdownViewModel
{
public CountdownModel Countdown { get; set; }
DispatcherTimer timer;
private const int maxMins = 360;
public CountdownViewModel()
{
Countdown = new CountdownModel { ChargeTimeRemaining_Mins = 60 };
// Setup timers
timer = new DispatcherTimer();
timer.Tick += new EventHandler(this.SystemChargeTimerService);
timer.Interval = new TimeSpan(0, 0, 1);
timer.Start();
}
private void SystemChargeTimerService(object sender, EventArgs e)
{
//convert to minutes remaining
// DEMO CODE - TODO: Remove
this.Countdown.ChargeTimeRemaining_Mins -= 1;
}
}
}
Here's the XAML for my user control:
<UserControl x:Class="WpfMVVMApp.UserControl1"
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="300" d:DesignWidth="300">
<Grid>
<Label Name="Readout"></Label>
</Grid>
</UserControl>
And here's the code behind the user control:
namespace WpfMVVMApp
{
public partial class UserControl1 : UserControl
{
#region Dependency Properties
public static readonly DependencyProperty MinutesRemainingProperty =
DependencyProperty.Register
(
"MinutesRemaining", typeof(int), typeof(UserControl1),
new UIPropertyMetadata(10, new PropertyChangedCallback(minutesRemainChangedCallBack))
);
#endregion
public int MinutesRemaining
{
get
{
return (int)GetValue(MinutesRemainingProperty);
}
set
{
SetValue(MinutesRemainingProperty, value);
}
}
static void minutesRemainChangedCallBack(DependencyObject property, DependencyPropertyChangedEventArgs args)
{
UserControl1 _readout = (UserControl1)property;
_readout.MinutesRemaining = (int)args.NewValue;
_readout.Readout.Content = _readout.MinutesRemaining;
}
public UserControl1()
{
InitializeComponent();
}
}
}
Your change callback is breaking the binding.
As a skeleton: in your window you have UC.X="{Binding A}" and then in that property change (in UC) you have X=B;. This breaks the binding since in both cases you set X.
To rectify, remove change callback and add this to the label:
Content="{Binding MinutesRemaining, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"
I tried your code works fine the only change i made was to remove the code behind propertychangedcallback you have and databind the Label (Readout) to the dependency property.
USERCONTROL(XAML)
<UserControl x:Class="WpfApplication1.UserControl"
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="300" d:DesignWidth="300">
<Grid>
<Label Name="Readout" Content="{Binding RelativeSource={RelativeSource
AncestorType=UserControl}, Path=MinutesRemaining}"/>
</Grid>
</UserControl>
USERCONTROL (CODE BEHIND)
public partial class UserControl1 : UserControl
{
#region Dependency Properties
public static readonly DependencyProperty MinutesRemainingProperty =
DependencyProperty.Register
(
"MinutesRemaining", typeof(int), typeof(UserControl1),
new UIPropertyMetadata(10)
);
#endregion
public int MinutesRemaining
{
get
{
return (int)GetValue(MinutesRemainingProperty);
}
set
{
SetValue(MinutesRemainingProperty, value);
}
}
public UserControl1()
{
InitializeComponent();
}
}

Categories