2
votes

Does anyone know how I can get the SelectedItem (not the Header) from a TreeView?
Here is my code:

<TreeView Name="treeView1" DataContext="{Binding Path=PresentationsViewModel}" Grid.Column="1" >
    <TreeViewItem IsExpanded="True" Header="Objects-A-List" DisplayMemberPath="Name" ItemsSource="{Binding Path=MyItem.ListA}"></TreeViewItem>
    <TreeViewItem IsExpanded="True" Header="Objects-B-List" DisplayMemberPath="Name" ItemsSource="{Binding Path=MyItem.ListB}"></TreeViewItem>
    <TreeViewItem IsExpanded="True" Header="Objects-C-List" DisplayMemberPath="Name" ItemsSource="{Binding Path=MyItem.ListC}"></TreeViewItem>
</TreeView>

Note that there are 3 different Lists, containing 3 different Object-Types. It'd help me a lot to have something like:

public Object SelectedObject
{
    set { _selectedObject = value; RunMyMethod(); RaisePropertyChanged("SelectedObject"); }
}  
4
What are you trying to do? Why doesn't TreeView.SelectedItem not work for you?Andy

4 Answers

6
votes

Ok I know this is an old question and probably dead but as Charlie has it right. This is something that can also be used in code. You could do for example:

<ContentPresenter Content="{Binding ElementName=treeView1, Path=SelectedItem}" />

Which will show the selected item. You can add a style or DataTemplate to that or use a default DataTemplate to the object you are trying to show.

5
votes

Step 1 Install the NuGet: Install-Package System.Windows.Interactivity.WPF

Step 2 In your Window tag add: xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"

Step 3 In the TreeView add:

    <TreeView Name="treeView1" ... >
         <i:Interaction.Triggers>
              <i:EventTrigger EventName="SelectedItemChanged">
                   <i:InvokeCommandAction Command="{Binding SelectedItemChangedCommand}" CommandParameter="{Binding ElementName=treeView1, Path=SelectedItem}"/>
              </i:EventTrigger>
          </i:Interaction.Triggers>
   ...
   </TreeView>

Step 4 In your ViewModel add:

        private ICommand _selectedItemChangedCommand;
        public ICommand SelectedItemChangedCommand
        {
            get
            {
                if (_selectedItemChangedCommand == null)
                    _selectedItemChangedCommand = new RelayCommand(args => SelectedItemChanged(args));
                return _selectedItemChangedCommand;
            }
        }

        private void SelectedItemChanged(object args)
        {
            //Cast your object
        }
3
votes

Diego Torres's answer is clean and simple! But for those who don't want to install a NuGet Package just for this purpose, you can create your own dependency property that Execute Command when a even is fired.

namespace View.Helper
{
    public class EventToCommandAdaptor
    {
        public static readonly DependencyProperty TreeViewSelectedItemChangedCommand_DpProp =
            DependencyProperty.RegisterAttached(
              "TreeViewSelectedItemChangedCommand",
              typeof(ICommand),
              typeof(EventToCommandAdaptor), // owner type
              new PropertyMetadata(new PropertyChangedCallback(AttachOrRemoveTreeViewSelectedItemChangedEvent))
              );

        public static ICommand GetTreeViewSelectedItemChangedCommand(DependencyObject obj)
        {
            return (ICommand)obj.GetValue(TreeViewSelectedItemChangedCommand_DpProp);
        }

        public static void SetTreeViewSelectedItemChangedCommand(DependencyObject obj, ICommand value)
        {
            obj.SetValue(TreeViewSelectedItemChangedCommand_DpProp, value);
        }

        public static void AttachOrRemoveTreeViewSelectedItemChangedEvent(DependencyObject obj, DependencyPropertyChangedEventArgs args)
        {
            TreeView treeview = obj as TreeView;
            if (treeview != null)
            {
                ICommand cmd = (ICommand)args.NewValue;

                if (args.OldValue == null && args.NewValue != null)
                {
                    treeview.SelectedItemChanged += ExecuteTreeViewSelectedItemChanged;
                }
                else if (args.OldValue != null && args.NewValue == null)
                {
                    treeview.SelectedItemChanged -= ExecuteTreeViewSelectedItemChanged;
                }
            }
        }

        private static void ExecuteTreeViewSelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> args)
        {
            DependencyObject obj = sender as DependencyObject;
            ICommand cmd = (ICommand)obj.GetValue(TreeViewSelectedItemChangedCommand_DpProp);

            if (cmd != null)
            {
                if (cmd.CanExecute(args.NewValue))
                {
                    cmd.Execute(args.NewValue);
                }
            }
        }
    }
}

Include xmlns:vh="clr-namespace:View.Helper" in <Windows></Windows>

And the TreeView looks like:

<TreeView ItemsSource="{Binding MyItemSource}"
    vh:EventToCommandAdaptor.TreeViewSelectedItemChangedCommand="{Binding MyCommand}">
</TreeView>

I learnt this trick when I encountered a similar situation: I want to execute a command when DataGrid.MouseDoubleClick Event is fired. But sorry that I forgot to mark down the source.

0
votes

Maybe I've misunderstood your question but,

treeView1.SelectedItem

Should work.