wpfdependency-propertiescaliburn

DependencyProperty and caliburn, view model not updated by dependency property


I have a view which wraps a TreeView, called MbiTreeView. I want to get the selected item from the (wrapped) tree view in the view model.

The 'parent' user control which uses this custom user control:

<UserControl [...]>

    <views:MbiTreeView
        Grid.Row="0"
        cal:Bind.Model="{Binding TreeViewModel}"
        SelectedItem="{Binding SelectedItem}">
    </views:MbiTreeView>
</UserControl>

The parent user control is bound to this view model:

internal sealed class SomeViewModel : PropertyChangedBase
{
    public object SelectedItem
    {
        get => _selectedItem;
        set
        {
            _selectedItem = value;
            NotifyOfPropertyChange(() => SelectedItem);
        }
    }

    public IMbiTreeViewModel TreeViewModel { get; }

    public SomeViewModel(
        IMbiTreeViewModel treeViewModel)
    {
        TreeViewModel = treeViewModel;
    }
}

The MbiTreeView user control is rather straight forward. It subscribes to the selection changed event, and defines a few templates (not relevant for this question, so left them out in the question)

<TreeView ItemsSource="{Binding Items}" SelectedItemChanged="TreeView_OnSelectedItemChanged">

iew.ItemContainerStyle>

The code behind declares the dependency property:

public partial class MbiTreeView
{
    public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register(
        nameof(SelectedItem),
        typeof(object),
        typeof(MbiTreeView),
        null);

    public object SelectedItem
    {
        get => GetValue(SelectedItemProperty);
        set => SetValue(SelectedItemProperty, value);
    }

    public MbiTreeView()
    {
        InitializeComponent();
    }

    private void TreeView_OnSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
    {
        SelectedItem = e.NewValue;
    }
}

when I start the application, I can navigate through the tree view items. When I click on a treeview node, then the OnSelectedItemChanged event fires (I get into my breakpoint there). So everything goes fine up and until setting the value in the dependency property SelectedItem.

Then I would expect that the xaml binding gets notified, and updates the view model. But that never happens.

I am getting nowhere with this, help is greatly appreciated.


Solution

  • The SelectedItem Binding should be TwoWay:

    <views:MbiTreeView ...
        SelectedItem="{Binding SelectedItem, Mode=TwoWay}"/>
    

    You could declare the property like shown below to make to bind TwoWay by default.

    public static readonly DependencyProperty SelectedItemProperty =
        DependencyProperty.Register(
            nameof(SelectedItem),
            typeof(object),
            typeof(MbiTreeView),
            new FrameworkPropertyMetadata(
                null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));