Reputation: 6397
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"); }
}
Upvotes: 3
Views: 27954
Reputation: 158
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.
Upvotes: 3
Reputation: 4898
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.
Upvotes: 6
Reputation: 1223
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
}
Upvotes: 5
Reputation: 15247
Maybe I've misunderstood your question but,
treeView1.SelectedItem
Should work.
Upvotes: 2