Search code examples
c#wpfdata-binding

WPF Binding from ParentViewModel to child user control not working


Left out irrelevant stuff in code snippets (like private member declaration e.g.)

ViewModel:

public class LinearGaugeViewModel<T> : INotifyPropertyChanged where T : GaugeElementViewModel
{
    public double Value
    {
        get => _value;
        set
        {
            _value = value;
            OnPropertyChanged();
        }
    }
}

XAML of "Parent" user control:

<ItemsControl ItemsSource="{Binding Elements}">
    <ItemsControl.Resources>
        <DataTemplate DataType="{x:Type local:HorizontalGaugeElementViewModel}">
            <local:HorizontalGaugeElement Value="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=DataContext.Value, Mode=OneWay}"/>
        </DataTemplate>
    </ItemsControl.Resources>
</ItemsControl>

Code behind HorizontalGaugeElement

public static DependencyProperty ValueProperty = DependencyProperty.Register(
    nameof(Value),
    typeof(double),
    typeof(HorizontalGaugeElement));

public double Value
{
    get => (double) GetValue(ValueProperty);
    set => SetValue(ValueProperty, value);
}

I want the Value in LinearGaugeViewModel to the dependency property of HorizontalGaugeElement.

When I change the value, I can see the setter LinearGaugeViewModel.Value getting set and notifying it's listeners.

public event PropertyChangedEventHandler PropertyChanged;

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

Yes still, the setting in the dependency property never gets set.

What am I doing wrong?


Solution

  • implement property changed callback for DP registration

    if callback fires, then your assumption about "the setting in the dependency property never gets set." is incorrect.

    WPF uses DependencyObject.SetValue(ValueProperty) to change DP values from XAML. Setter of common property wrapper (public double Value) is not used