0

I have an Attached Property called TreeViewSelectedItem. Without going into too many details of why I need this attached property, I will say it has to do with having to update different properties on my VM based on what type of item is selected in the TreeView.

My problem is, I cannot seem to get my code to update the property on the VM.

The xaml setup:

    <TreeView ItemsSource="{Binding Lists}" l:BindableSelectedItemBehavior.TreeViewSelectedItem="{Binding SelectedListGroup}">

        <ItemsControl.ItemTemplate>
            <HierarchicalDataTemplate ItemsSource="{Binding }" >
                <TextBlock Text="{Binding Key}"/>
                <HierarchicalDataTemplate.ItemTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Key}"/>
                    </DataTemplate>
                </HierarchicalDataTemplate.ItemTemplate>                    
            </HierarchicalDataTemplate>
        </ItemsControl.ItemTemplate>
    </TreeView>

My Attached Property:

    public static object GetTreeViewSelectedItem(DependencyObject obj)
    {
        return (object)obj.GetValue(TreeViewSelectedItemProperty);
    }

    public static void SetTreeViewSelectedItem(DependencyObject obj, object value)
    {
        obj.SetValue(TreeViewSelectedItemProperty, value);
    }

    // Using a DependencyProperty as the backing store for TreeViewSelectedItem.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty TreeViewSelectedItemProperty =
        DependencyProperty.RegisterAttached("TreeViewSelectedItem", typeof(object), typeof(BindableSelectedItemBehavior), new UIPropertyMetadata(null,
            (s,a) =>
            {
                TreeView tree = s as TreeView;

                if (tree == null)
                    return;

                if (a.NewValue != null)
                {
                    tree.SelectedItemChanged += tree_SelectedItemChanged;
                    tree.SourceUpdated += tree_SourceUpdated;
                }
                else
                {

                }

            }));

    static void tree_SourceUpdated(object sender, System.Windows.Data.DataTransferEventArgs e)
    {
        throw new NotImplementedException();
    }

    static void tree_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
    {
        TreeView tree = sender as TreeView;
        object binding;
        BindingExpression bindingExp;

        if (tree == null)
            return;

        bindingExp = BindingOperations.GetBindingExpression(tree, BindableSelectedItemBehavior.TreeViewSelectedItemProperty);
        binding = GetTreeViewSelectedItem(tree);

        if (binding == null)
            return;

        if (binding.GetType() == e.NewValue.GetType())
        {
            System.Diagnostics.Debug.WriteLine("Type match");
            binding = tree.SelectedItem;
            //tree.SetValue(BindableSelectedItemBehavior.TreeViewSelectedItemProperty, tree.SelectedItem);
            //SetTreeViewSelectedItem(tree, tree.SelectedItem);
            tree.SetCurrentValue(BindableSelectedItemBehavior.TreeViewSelectedItemProperty, tree.SelectedItem);
        }

    }

At the bottom, I have tried a number of different ways to try an update whatever this Attached Property is bound to but it doesn't seem to hit the VM property's Set method (doesn't hit the breakpoint).

How do I update that property?

Hexum064
  • 349
  • 2
  • 14
  • Just a friendly comment: If you subscribe to an event dont forget to unsubscibe. To you question. It's probably easier, to create a class derived from Treeview and Override the `SelectedItem`- Property – lokusking Jul 05 '16 at 18:14
  • @lokusking, good catch on the unsubscribe. This is just test code so I wasn't worried about it, but for anyone looking to this, that's really important to NOT leave out! And you're right, it might just be easier at this point to subclass TreeView. – Hexum064 Jul 05 '16 at 18:25
  • The funny thing is, Treeview as this Property, yet readonly. [This](http://stackoverflow.com/questions/1000040/data-binding-to-selecteditem-in-a-wpf-treeview) might help you on further desicions – lokusking Jul 05 '16 at 18:33
  • Have you tried to RaisePropertyChanged when you initialize the public SetTreeViewSelectedItem? – tCoe Jul 05 '16 at 20:38
  • Please provide a good [mcve] that reliably reproduces the problem. There's not even a view model at all in the above code, never mind anything that looks like it ought to set any property of a view model. What code is there is mostly obfuscating the question, due to the extraneous bits that don't seem to relate to the specific issue. Note that the `SetCurrentValue()` method is specifically there to change the target value of a binding _without_ changing the source value. Please improve the question so that it's more clear what you are doing and asking. – Peter Duniho Jul 05 '16 at 21:20

1 Answers1

0

As it turns out, the solution was 1: to use SetTreeViewSelectedItem(tree, tree.SelectedItem); (which I had commented out) and 2: use Mode=TwoWay in the binding.

I will note that the other approach to addressing what I am trying to accomplish here is to use the IsSelected property of the TreeView and bind it to some boolean property on the underlying VMs. This was pointed out by a number of people (like Julien and Maverik). While I couldn't use it in my very special situation, this is the way to go in 99.9% of the situations.

Hexum064
  • 349
  • 2
  • 14