2

My page xaml:

<header:DefaultText x:Name="header" HeaderText="{Binding Resources.HeaderTitle}"/>

My DefaultText.cs DependencyProperty:

    public string HeaderText
    {
        get { return (string)GetValue(HeaderTextProperty); }
        set
        {   //This part is never called when binding, but it is with static text
            SetValue(HeaderTextProperty, value);
            SetText(value);
        }
    }

    public readonly DependencyProperty HeaderTextProperty = DependencyProperty.Register("HeaderText", typeof(string), typeof(DefaultText), new PropertyMetadata(string.Empty));

My problem is that when I set the HeaderText property with a binding the setter isn't called, but when I use a normal string without binding it is called.

I already tried the answers of similar questions like: WPF Binding to variable / DependencyProperty

Community
  • 1
  • 1
Roy
  • 656
  • 12
  • 28
  • possible duplicate of [WPF: XAML property declarations not being set via Setters?](http://stackoverflow.com/questions/3836076/wpf-xaml-property-declarations-not-being-set-via-setters) – Tim Pohlmann Sep 14 '15 at 13:29

1 Answers1

7

XAML binding internally doesn't call your Setter method but sets the dependency property's value directly, as is pointed out at MSDN:

The WPF XAML processor uses property system methods for dependency properties when loading binary XAML and processing attributes that are dependency properties. This effectively bypasses the property wrappers. When you implement custom dependency properties, you must account for this behavior and should avoid placing any other code in your property wrapper other than the property system methods GetValue and SetValue.

What you need to do is register a callback method that fires whenever the dependency property changes:

public static DependencyProperty HeaderTextProperty = DependencyProperty.Register(
    "HeaderText", 
    typeof(string), 
    typeof(DefaultText), 
    new PropertyMetadata(string.Empty, PropertyChangedCallback)
);

private static void PropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args)
{
    // this is the method that is called whenever the dependency property's value has changed
}
andreask
  • 4,248
  • 1
  • 20
  • 25
  • Thanks for the quick reply and explanation, it still doesn't appear to work, could I be missing something else? The PropertyChangedCallback does get called when I'm not using a binding but not when using the binding. – Roy Aug 26 '14 at 08:39
  • Maybe your dependency property isn't updated at all, try adding `{Binding ..., Mode=TwoWay}` to the binding to force updating in both directions? – andreask Aug 26 '14 at 08:42
  • I changed it to `HeaderText="{Binding Resources.HeaderTitle, Mode=TwoWay}"` and it still doesn't appear to work. The binding does work when I'm using it on a normal control like TextBlock.Text instead of a user control. – Roy Aug 26 '14 at 08:46
  • Another idea: Can you check if `Resources.HeaderTitle` (or whatever you're binding to) really contains some data at the moment the binding is evaluated? If the binding value is equal to the dependency property's default value (in your case, `string.Empty`), the callback will not fire. – andreask Aug 26 '14 at 08:51
  • That was the problem, the translator appeared to have missed that one. Thanks a lot! – Roy Aug 26 '14 at 08:54
  • I used so many DependencyProperties in the last few years but never met this problem. I honestly thought it'd call the setter. So thank you for the PropertyChangedCallback! – ecth Mar 27 '17 at 14:17