Pseudonymous
Pseudonymous

Reputation: 884

WPF DependencyProperty PropertyChangedCallback Not Being Called

My issue is my OnMatrixPropertyChanged method never gets called. The label, which is bound to the same property, does update so I know binding is happening on the Matrix property.

I have a UserControl that I want to add a DependencyProperty to in order that it can be bound to. My MainWindow looks like this:

<Window.DataContext>
    <local:MainWindowViewModel />
</Window.DataContext>

<StackPanel>
    <Button
        Command="{Binding LoadMatrixCommand}"
        Content="Load"
        Width="150">
    </Button>

    <Label
        Content="{Binding Matrix.Title}">
    </Label>

    <controls:MatrixView
        Matrix="{Binding Path=Matrix, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
    </controls:MatrixView>
</StackPanel>

In my MatrixView UserControl code-behind I have the DependencyProperty set as such:

public partial class MatrixView : UserControl
{
    public static readonly DependencyProperty MatrixProperty =
        DependencyProperty.Register(nameof(Matrix), typeof(Matrix), typeof(MatrixView), new PropertyMetadata(default(Matrix), OnMatrixPropertyChanged));

    private static void OnMatrixPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        // Do Something
    }

    public Matrix Matrix
    {
        get => (Matrix)GetValue(MatrixProperty);
        set => SetValue(MatrixProperty, value);
    }

    public MatrixView()
    {
        InitializeComponent();
    }
}

I must be missing something very obvious...

EDIT #1: View Models

public class MatrixViewModel : ViewModelBase
{
    public MatrixViewModel()
    {
    }
}

public class MainWindowViewModel : ViewModelBase
{
    private IMatrixService _matrixService;
    private Matrix _matrix;

    public Matrix Matrix
    {
        get => _matrix;
        set
        {
            _matrix = value;
            base.RaisePropertyChanged();
        }
    }

    public ICommand LoadMatrixCommand { get; private set; }

    public MainWindowViewModel()
    {
        LoadMatrixCommand = new RelayCommand(LoadMatrix);
        _matrixService = new MatrixService();
    }

    private void LoadMatrix()
    {
        var matrixResult = _matrixService.Get(1);

        if (matrixResult.Ok)
        {
            Matrix = matrixResult.Value;
        }
    }
}

Upvotes: 0

Views: 1393

Answers (1)

Clemens
Clemens

Reputation: 128061

There certainly is something like

<UserControl.DataContext>
    <local:MatrixViewModel/>
</UserControl.DataContext>

in the XAML of your UserControl. Remove that, because it prevents that a Binding like

<controls:MatrixView Matrix="{Binding Matrix}" />

looks up the Matrix property in the correct view model instance, i.e. the one inherited from the MainWindow.

UserControls with bindable (i.e. dependency) properties should never set their own DataContext, because doing so breaks any DataContext based bindings of these properties.

Upvotes: 1

Related Questions