Note: I am not having problem with controls inside User Control like other similar articles on StackOverflow, I am having with a Property of the User Control itself. I am making a Custom Control based on Canvas, with a Dependency Property (using propdb template):
public sealed partial class PresentationViewer : Canvas
{
#region Properties
public ISlide PresentationSlide
{
get
{
Debug.WriteLine("Get PresentationSlide");
return (ISlide)GetValue(PresentationSlideProperty);
}
set
{
Debug.WriteLine("Set PresentationSlide");
SetValue(PresentationSlideProperty, value);
this.ShowSlideContent();
}
}
// Using a DependencyProperty as the backing store for PresentationSlide. This enables animation, styling, binding, etc...
public static readonly DependencyProperty PresentationSlideProperty =
DependencyProperty.Register(nameof(PresentationSlide), typeof(ISlide), typeof(PresentationViewer), new PropertyMetadata(null));
#endregion
// Other codes...
}
In my Page, I use the control and bind that property:
<views:PresentationViewer x:Name="PresentationViewer" PresentationSlide="{Binding CurrentSlide, Mode=TwoWay}" />
This is how I set the Page's DataContext
:
public MainPage()
{
this.InitializeComponent();
this.ViewModel = new MainPageViewModel();
this.DataContext = this.ViewModel;
}
And this is the code of my MainPageViewModel
:
public class MainPageViewModel : INotifyPropertyChanged
{
// Other codes...
public ISlide CurrentSlide
{
get
{
return this.CurrentPresentation?.Slides[this.CurrentSlideIndex];
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OpenSlide(int index)
{
if (index < 0)
{
index = 0;
}
if (index > this.TotalSlides - 1)
{
index = this.TotalSlides - 1;
}
this.currentSlideIndexField = index;
this.PropertyChanged(this, new PropertyChangedEventArgs(nameof(this.CurrentSlideIndex)));
System.Diagnostics.Debug.WriteLine("Current Slide notified");
this.PropertyChanged(this, new PropertyChangedEventArgs(nameof(this.CurrentSlide)));
this.PropertyChanged(this, new PropertyChangedEventArgs(nameof(this.PageCounter)));
}
}
Notice the line where I print the notification of CurrentSlide
property change. However, no setter or getter of the User Control's property is called. Here is the output when OpenSlide
is called (the output is since the beginning of the program):
The Binding is already in two-way mode. And other control in my page (Label, etc...) are also notified and changed their content, such as the Page counter, so I guess it is not the ViewModel problem too. Am I missing something in my Custom Control class? How can I make the Binding work?
As explained in XAML Loading and Dependency Properties, the CLR wrapper of a dependency property may not be called, so your breakpoints aren't hit and the
ShowSlideContent
method isn't executed. Instead, the framework directly calls the dependency property'sGetValue
andSetValue
methods.In order to react on changed property values, you'll have to register a
PropertyChangedCallback
with property metadata:Or, with a lambda expression: