0

I created a DependencyObject with properties in it, I also have it inherit INotifyPropertyChanged.

But when it is implemented as a DependencyProperty, it does not trigger PropertyChangedCallback when I change a single property from the DependencyObject both in design and code.

This is the dependency object that I will use for my CustomControl.

public class Basemap : DependencyObject, INotifyPropertyChanged
{
    private string identifier;
    private string name;
    private string alias;
    private string url;

    private Map.DetailRange detailrange;
    private Map.Attribution attribution;

    public string Identifier
    {
        get => identifier;
        set
        {
            identifier = value;
            OnPropertyChanged("Identifier");
        }
    }

    public string Name
    {
        get => name;
        set
        {
            name = value;
            OnPropertyChanged("Name");
        }
    }

    public string Alias
    {
        get => alias;
        set
        {
            alias = value;
            OnPropertyChanged("Alias");
        }
    }

    public string URL
    {
        get => url;
        set
        {
            url = value;
            OnPropertyChanged("URL");
        }
    }

    public Map.DetailRange DetailRange
    {
        get => detailrange;
        set
        {
            detailrange = value;
            OnPropertyChanged("DetailRange");
        }
    }

    public Map.Attribution Attribution
    {
        get => attribution;
        set
        {
            attribution = value;
            OnPropertyChanged("Attribution");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged([CallerMemberName] string name = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
    }
}

It has a PropertyChangedEventHandler and invoking it whenever the OnPropertyChanged is called, just like in this GUIDE

This it the DependecyProperty I implemented into the CustomControl that has a PropertyChangedCallback.

public static DependencyProperty BasemapProperty = DependencyProperty.Register("Basemap", typeof(Basemap), typeof(Browser), new PropertyMetadata(null, BasemapChanged));
private static void BasemapChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    Debug.WriteLine("Basemap Changed");
}

But the PropertyChangedCallback is not triggered when an individual property's value is changed, but it is triggered only when the whole DependecyObject is updated or inserted. Both in design and code

<Window.Resources>
    <mMAP:Basemap x:Key="OpenStreetMap" 
                      Identifier="OpenStreetMap.Standard"
                      Name="OpenStreetMap Standard" 
                      Alias="OpenStreetMap" 
                      URL="https://tile.openstreetmap.org/{z}/{x}/{y}.png" 
                      DetailRange="0,0,18"
                      Attribution="© OpenStreetMap contributors, CC-BY-SA" />
</Window.Resources>

Can anyone suggest any fixes to this?

Thank you.

Edit: I assigned the PropertyChanged event from the DependecyObject to the control:

Basemap.PropertyChanged += Basemap_PropertyChanged;

so it can be triggered every time any member of the DependecyObject class. It may be sacrilegious to do it to WPF, but works for me.

PS: I needed it to be grouped, for it is a configuration for the CustomControl.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459

1 Answers1

0

You are not binding to the Dependency Property you defined in the control, that is why the PropertyChangedCallback BasemapChanged is not triggered.

While it works on some cases, I try to avoid implementing the INotifyPropertyChanged Interface on Controls and use only Dependency Properties instead when binding is required.

public static DependencyProperty AliasProperty = DependencyProperty.Register(
    nameof(Alias),
    typeof(string),
    typeof(Basemap),
    new PropertyMetadata(null, AliasPropertyChangedCallback));

public string Alias
{
    get { return (string)GetValue(Alias); }
    set { SetValue(Alias, value); }
}

private static void AliasPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    Debug.WriteLine($"New Value of Alias: {e.NewValue}");
}

See: Dependency properties overview (WPF .NET)

quarkonaut
  • 51
  • 2
  • Should it be implemented to the DependencyObject Class or is it directly on the CustomControl? – Brian James Gresos Feb 15 '23 at 08:03
  • Directly on the Control. No need for an extra DependencyObject. – quarkonaut Feb 15 '23 at 09:09
  • Is there any other way to at least group properties? – Brian James Gresos Feb 15 '23 at 09:21
  • Not sure what you are up to, or what the end goal is. If you want to re-use certain values for properties in different controls, try to create Style Resources. Maybe create another question for your grouping issue. – quarkonaut Feb 15 '23 at 09:38
  • I needed it to be an Object because it is a configuration for the Control. Thank you @quarkonaut , you gave me an idea to implement on other Controls. – Brian James Gresos Feb 15 '23 at 10:46
  • In that case, you could maybe use complex types (i.e. your configuration objects) as type of your dependency properties and apply the configuration of the control in the `PropertyChangedCallback`. – quarkonaut Feb 15 '23 at 11:53