I'm using Caliburn Micro Message.Attach through XAML to try and bind Events to a View Model, but I cannot get the TreeViewItem.Expanded Event to fire. Other events like SetSelectedItem work fine.
I found another question on this on SO here but it was not helpful in my case as no context for the response was provided.
The only other information I can find is the following GitHub issue.
Internally Caliburn.Micro turns
<Button cm:Message.Attach="[Event Click] = [Action Test]" />
into
<Button>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<cm:ActionMessage MethodName="Test" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
As you noted, EventTrigger doesn't support attached events. A quick look around brought up How to attached an MVVM EventToCommand to an Attached event which shows how to create a RoutedEventTrigger that you could plug into the full syntax.
Again, I tried this approach, but don't fully understand how to implement this. It fires the event in the custom class, but never gets passed on to my handler in the View Model.
Here is my XAML (without the GitHub suggestion):
<TreeView x:Name="FolderView"
cal:Message.Attach="[Event TreeViewItem.Expanded] = [Action Expanded($this)];
[Event SelectedItemChanged] = [Action SetSelectedItem($this.SelectedItem)]">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type models:LogicalDriveItem}"
ItemsSource="{Binding Directories}" >
<StackPanel Orientation="Horizontal">
<TextBlock VerticalAlignment="Center" Text="{Binding Path=DriveLetter}"></TextBlock>
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type models:DirectoryItem}"
ItemsSource="{Binding Directories}">
<TextBlock VerticalAlignment="Center" Text="{Binding Path=Path}"></TextBlock>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
And my view model code:
public void Expanded(object sender, RoutedEventArgs e)
{
// This won't fire
}
public void Expanded(object sender)
{
// Or this
}
public void SetSelectedItem(object sender)
{
// But this will
}
The link provided by mm8 resolved my issue.
The OP in that question is using the same RoutedEventTrigger helper class that I found on GitHub, but the additional context provided by their answer was helpful. Using the RoutedEventTrigger helper class, I updated my XAML to the following:
<i:Interaction.Triggers>
<!--in the routed event property you need to put the full name space and event name-->
<helpers:RoutedEventTrigger RoutedEvent="TreeViewItem.Expanded">
<cal:ActionMessage MethodName="Expanded">
<cal:Parameter Value="$eventArgs" />
</cal:ActionMessage>
</helpers:RoutedEventTrigger>
</i:Interaction.Triggers>
which now successfully fires my event in the ViewModel code.
Note that $this did not work for me because the data item in my case is a string. In my case, it's a File Explorer style Tree View. For context, here is the full XAML:
<TreeView x:Name="FolderView">
<i:Interaction.Triggers>
<!--in the routed event property you need to put the full name space and event name-->
<helpers:RoutedEventTrigger RoutedEvent="TreeViewItem.Expanded">
<cal:ActionMessage MethodName="Expanded">
<cal:Parameter Value="$eventArgs" />
</cal:ActionMessage>
</helpers:RoutedEventTrigger>
</i:Interaction.Triggers>
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type models:LogicalDriveItem}"
ItemsSource="{Binding Directories}" >
<StackPanel Orientation="Horizontal">
<!--<Image MaxWidth="20" Source="Images/Image.png"/>-->
<TextBlock VerticalAlignment="Center" Text="{Binding Path=DriveLetter}"></TextBlock>
</StackPanel>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type models:DirectoryItem}"
ItemsSource="{Binding Directories}">
<TextBlock VerticalAlignment="Center" Text="{Binding Path=Name}"></TextBlock>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
Related
In my app using the Windows App SDK, I'm trying to get a button-tapped event to trigger a command in my viewmodel. I have gotten this to work when the data template is between the and on the page, but it won't work when the data template is in Page.Resources. I have to place some data templates in Page.Resources because I need to have multiple data templates in the TreeView and use a DataTemplateSelector to select the correct one based on the type of the item. I've gotten the template selection working, but I just can't get the button binding to work. It looks like the ElementName binding can't find the page name. Can anyone show me what I'm doing wrong?
<Page.Resources>
<DataTemplate x:Key="treeViewSFTemplate" x:DataType="models:SF">
<TreeViewItem ItemsSource="{Binding OwnedSFEs}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding SFName}"/>
<Button Content="+">
<i:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Tapped">
<core:InvokeCommandAction Command="{Binding ElementName=sfSettingsPage, Path=ViewModel.AddNewSubfactorCommand}"/>
</core:EventTriggerBehavior>
</i:Interaction.Behaviors>
</Button>
<Button Content="-"/>
</StackPanel>
</TreeViewItem>
</DataTemplate>
<DataTemplate x:Key="treeViewSFETemplate" x:DataType="models:SFE">
<TreeViewItem>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding SFEName}"/>
<Button Content="+">
<i:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Tapped">
<core:InvokeCommandAction Command="{Binding ElementName=thisPage, Path=ViewModel.DeleteSFECommand}"/>
</core:EventTriggerBehavior>
</i:Interaction.Behaviors>
</Button>
<Button Content="-"/>
</StackPanel>
</TreeViewItem>
</DataTemplate>
</Page.Resources>
And then in the in the page code below:
<TreeView x:Name="MyTreeView"
ItemsSource="{x:Bind ViewModel.SFList}"
ItemTemplateSelector="{StaticResource treeViewDataTemplateSelector}" />
The reason for this behavior is that you wrapped a TreeViewItem in
the DataTemplate. It will cause that TreeViewItem contains sub-TreeViewItem in the Visual Tree and you could not access correct DataContext with element name in your button. Please remove TreeViewItem from your code.
Like:
<DataTemplate x:Key="treeViewSFETemplate" x:DataType="models:SFE">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding SFEName}"/>
<Button Content="+">
<i:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Tapped">
<core:InvokeCommandAction Command="{Binding ElementName=thisPage, Path=ViewModel.DeleteSFECommand}"/>
</core:EventTriggerBehavior>
</i:Interaction.Behaviors>
</Button>
<Button Content="-"/>
</StackPanel>
</DataTemplate>
Assuming the view model MyViewModel for the page is bound to the DataContext property of the page and MyItemViewModel is the datatype of the item in a collection. The CommandParameter binding binds the view model of the item:
<Page
...
x:Name="MyPage"
...
<Page.Resources>
...
<DataTemplate x:Key="MyDataTemplate" x:DataType="vm:MyItemViewModel>
...
<Button
...
Command="{Binding ElementName=MyPage, Path=DataContext.MyCommand}"
CommandParameter="{Binding}"
...
Changes to the value of the property DataContext can be verified by adding an eventhandler after InitializeComponent() in the page constructor:
public MyPage()
{
InitializeComponent();
...
DataContextChanged += MyPage_DataContextChanged;
...
}
void MyPage_DataContextChanged(FrameworkElement sender, DataContextChangedEventArgs args)
{
if (DataContext is MyViewModel vm)
{
}
}
I've got following problem. Following situation in my xaml code:
<ListView ItemsSource="{Binding ListViewItems}">
<ListView.ItemTemplate>
<DataTemplate>
<WrapPanel>
<Label Content="Test">
<Label.ContextMenu>
<ContextMenu ItemsSource="{Binding MenuItems}">
</ContextMenu>
</Label.ContextMenu>
</Label>
</WrapPanel>
</DataTemplate>
</ListView.ItemTemplate>
<i:Interaction.Triggers>
<i:EventTrigger EventName="PreviewMouseUp">
<i:InvokeCommandAction Command="{Binding LabelMouseUpCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</ListView>
After clicking a label no context menu is shown and the trigger does not work as well, LabelMouseUpCommand method is not entered. I fear the listview handles the click itself and does not pass it to the embedded controls.
Is there any way to pass it to the controls. In future i want to add several controls to the itemtemplate and everyone has it own different context menu.
I found the answer for my problem with this stackoverflow article
There the author explains that the contextmenu does not lie in the same visual tree as the listview. Therefore my initial binding can't work because the source can't be found within the visual tree.
Furthermore Sinatr was totally right, the trigger was initially defined for listview, not for the label.
Here is my working code:
<ListView ItemsSource="{Binding ListViewItems}" x:Name="listViewMain">
<ListView.ItemTemplate>
<DataTemplate>
<WrapPanel>
<Label Content="Test">
<Label.ContextMenu>
<ContextMenu ItemsSource="{Binding DataContext.MenuItems, Source={x:Reference listViewMain}}">
</ContextMenu>
</Label.ContextMenu>
<i:Interaction.Triggers>
<i:EventTrigger EventName="PreviewMouseUp">
<i:InvokeCommandAction Command="{Binding DataContext.LabelMouseUpCommand, Source={x:Reference listViewMain}}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Label>
</WrapPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I need an ApplicationBar which can be bound to both commands and tap events (tap events are needed for UI related stuff and I can't handle them in my Model).
I'm trying with BindableApplicationBar from NuGet and the command binding works fine but there's no way to get the tap events.
Please note that I'm changing the DataContext to make the binding work but the Tap event has to be managed in the code-behind (and I don't know if this may be the main cause of my problem!)
Here's the bar's xaml:
<bindableApplicationBar:Bindable.ApplicationBar>
<bindableApplicationBar:BindableApplicationBar>
<bindableApplicationBar:BindableApplicationBarButton
Text="{Binding MainSearchText}"
IconUri="Assets/AppBar/feature.search.png"
Command="{Binding NavigateCommand}"
Name="SearchBarButton" />
<bindableApplicationBar:BindableApplicationBarButton
Text="{Binding Path=LocalizedResources.AppBarSettingsText, Source={StaticResource LocalizedStrings}}"
IconUri="Assets/AppBar/feature.settings.png"
Tap="SettingsButton_OnTap" />
<bindableApplicationBar:BindableApplicationBar.MenuItems>
<bindableApplicationBar:BindableApplicationBarMenuItem
Text="{Binding Path=LocalizedResources.AppBarAboutText, Source={StaticResource LocalizedStrings}}"
Tap="Info_OnTap" />
</bindableApplicationBar:BindableApplicationBar.MenuItems>
</bindableApplicationBar:BindableApplicationBar>
</bindableApplicationBar:Bindable.ApplicationBar>
and here's one of the handlers that I have in my .xaml.cs file:
private void Info_OnTap(object sender, GestureEventArgs e)
{
_about.Show();
Debug.WriteLine("INFO ON_TAP");
}
No "INFO ON_TAP" line is written when I click on the MenuItem.
What's wrong with it?
This is not how you would use BindableApplicationBar. BindableApplicationBarButton inherits from FrameworkElement (and thus has Tap event) to support DataContext and Bindings; the Tap event is not fired because no BindableApplicationBarButton is ever tapped, no BindableApplicationBarButton is ever onscreen - this is only a wrapper that creates an ApplicationBarIconButton, but doesn't pass the Tap event handler to it (ApplicationBarIconButton, by the way, has only one event - Click). The same goes for BindableApplicationBarMenuItem. BindableApplicationBar works best with Commands.
See more in comments in source: BindableApplicationBar # codeplex
Here are (some of) your options:
use Command property of BindableApplicationBarButton to react to buttons clicks
after defining BindableApplicationBar in xaml, hookup to Click events of ApplicationBarIconButtons it created in code behind
use BindableApplicationBar code (open source) and alter it for best experience in your scenerio
You can try Cimbalino Toolkit AppBar ... much more powerfull and easier to use!
For example:
<i:Interaction.Behaviors>
<cimbalinoBehaviors:MultiApplicationBarBehavior
SelectedIndex="{Binding SelectedIndex, ElementName=MainInfo, Converter={StaticResource HomeMenuConverter}}" >
<cimbalinoBehaviors:ApplicationBar Opacity="0.5"
IsMenuEnabled="{Binding IsLoading, Converter={StaticResource NegativeBooleanConverter}}">
<cimbalinoBehaviors:ApplicationBarIconButton
IsVisible="{Binding IsAuthenticated}"
IsEnabled="{Binding IsLoading, Converter={StaticResource NegativeBooleanConverter}}"
Command="{Binding GetFavorites, Mode=OneTime}"
IconUri="/Assets/appbar.sync.rest.png" Text="{Binding Labels.Translation.Refresh, Source={StaticResource LabelsManager}}" />
<cimbalinoBehaviors:ApplicationBarIconButton
IsVisible="{Binding SelectionMode, Converter={StaticResource NegativeBooleanConverter}}"
IsEnabled="{Binding IsLoading, Converter={StaticResource NegativeBooleanConverter}}"
Command="{Binding SetSelectionMode, Mode=OneTime}"
IconUri="/Assets/ApplicationBar.Select.png" Text="{Binding Labels.Translation.Select, Source={StaticResource LabelsManager}}" />
<cimbalinoBehaviors:ApplicationBarIconButton
IsVisible="{Binding SelectionMode}"
IsEnabled="{Binding IsLoading, Converter={StaticResource NegativeBooleanConverter}}"
Command="{Binding DeleteFavorites, Mode=OneTime}"
IconUri="/Assets/ApplicationBar.Delete.png" Text="{Binding Labels.Translation.Delete, Source={StaticResource LabelsManager}}" />
<cimbalinoBehaviors:ApplicationBarIconButton
IsVisible="{Binding SelectionMode}"
IsEnabled="{Binding IsLoading, Converter={StaticResource NegativeBooleanConverter}}"
Command="{Binding SetSelectionMode, Mode=OneTime}"
IconUri="/Assets/ApplicationBar.Cancel.png" Text="{Binding Labels.Translation.Cancel, Source={StaticResource LabelsManager}}" />
</cimbalinoBehaviors:ApplicationBar>
</cimbalinoBehaviors:MultiApplicationBarBehavior>
</i:Interaction.Behaviors>
https://github.com/Cimbalino/Cimbalino-Phone-Toolkit
This is a pretty easy question I think , but I can't find the answer. I have an itemtemplate defined into a datatemplate. When an item is selected, I wanna trigger a command to select the name of my element and apply it somewhere else. For the moment the MouseDown event doesn't accept my command.
<ListView Margin="4" Grid.Row="1" Grid.ColumnSpan="2" ItemsSource="{Binding Path=ExistingStateInfos, ElementName=Window}"
SelectedItem="{Binding Path=SelectedStateInfo, ElementName=Window}" x:Name="statinfoListview">
<ListView.ItemTemplate>
<DataTemplate DataType="{x:Type States:StateInfo}">
<TextBlock Text="{Binding Path=Name}" MouseDown="{x:Static MyWindow.ApplyStateInfoNameToStateCommand}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
You can't set a command directly to an event handler.
Use EventToCommand from the MVVM LightToolkit
<DataTemplate DataType="{x:Type States:StateInfo}">
<TextBlock Text="{Binding Path=Name}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDown">
<Command:EventToCommand Command="{Binding YourCommand, Mode=OneWay}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBlock>
</DataTemplate>
In fact ot was bulshit from me, I just add to do
<TextBlock Text="{Binding Path=Name}" MouseDown="{x:Static ApplyStateInfoNameToState_Click}" />
Sorry it's friday. Have a nice weekend :)
I am busy creating my first MVVM application in WPF.
Basically the problem I am having is that I have a TreeView (System.Windows.Controls.TreeView) which I have placed on my WPF Window, I have decide that I will bind to a ReadOnlyCollection of CommandViewModel items, and these items consist of a DisplayString, Tag and a RelayCommand.
Now in the XAML, I have my TreeView and I have successfully bound my ReadOnlyCollection to this. I can view this and everything looks fine in the UI.
The issue now is that I need to bind the RelayCommand to the Command of the TreeViewItem, however from what I can see the TreeViewItem doesn't have a Command. Does this force me to do it in the IsSelected property or even in the Code behind TreeView_SelectedItemChanged method or is there a way to do this magically in WPF?
This is the code I have:
<TreeView BorderBrush="{x:Null}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<TreeView.Items>
<TreeViewItem
Header="New Commands"
ItemsSource="{Binding Commands}"
DisplayMemberPath="DisplayName"
IsExpanded="True">
</TreeViewItem>
</TreeView.Items>
and ideally I would love to just go:
<TreeView BorderBrush="{x:Null}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<TreeView.Items>
<TreeViewItem
Header="New Trade"
ItemsSource="{Binding Commands}"
DisplayMemberPath="DisplayName"
IsExpanded="True"
Command="{Binding Path=Command}">
</TreeViewItem>
</TreeView.Items>
Does someone have a solution that allows me to use the RelayCommand infrastructure I have.
Thanks guys, much appreciated!
Richard
I know this was "answered" a while ago, but since the answers weren't ideal, I figured I'd put in my two cents. I use a method that allows me to not have to resort to any "styled button trickery" or even using code-behind and instead keeps all my separation in MVVM. In your TreeView add the following xaml:
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectedItemChanged">
<i:InvokeCommandAction Command="{Binding TreeviewSelectedItemChanged}" CommandParameter="{Binding ElementName=treeView, Path=SelectedItem}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
In your xaml header add:
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
and then you'll have to add a reference to the above assembly in your project.
After that, everything acts just the same as any other command would on say a button or something.
Thanks for the input into the issue, and yes, I did say I didn't want a Code behind solution, however at that time I was still very much under the impression that I was simply missing something... so I ended up using the TreeView_SelectedItemChanged event.
Even though Will's approach seems like a good work around, for my personal situation I decided that I would use the code behind. The reason for this is so that the View and XAML would remain as it would be if the TreeViewItem had a "Command" property to which my Command could be bound. Now I do not have to change the Templates or the Views, all I have to do is add the code and the Event for the TreeView_SelectedItemChanged.
My solution:
private void TreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
if (sender != null)
{
var treeView = sender as TreeView;
if (treeView != null)
{
var commandViewModel = treeView.SelectedItem as CommandViewModel;
if (commandViewModel != null)
{
var mi = commandViewModel.Command.GetType().GetMethod("Execute");
mi.Invoke(commandViewModel.Command, new Object[] {null});
}
}
}
}
As I already have the RelayCommand attached to the TreeViewItem, all I am now doing is to just manually invoke the "Execute" method on that specific RelayCommand.
If this is the completely wrong way of going about it then please let me know...
Thanks!
What I'd do is set the Header of the TreeViewItem to be a button, then skin the button so that it doesn't look or act like one, then perform my command binding against the button.
You might need to do this via a DataTemplate, or you might need to change the template of the TreeViewItem itself. Never done it, but this is how I've done similar things (such as tab page headers).
Here's an example of what I'm talking about (you can drop this in Kaxaml and play around with it):
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Page.Resources>
<Style x:Key="ClearButan" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Name="border"
Padding="4"
Background="transparent">
<Grid >
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center">
</ContentPresenter>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Page.Resources>
<Grid>
<TreeView>
<TreeViewItem>
<Button Style="{StaticResource ClearButan}">
easy peasy
</Button>
</TreeViewItem>
</TreeView>
</Grid>
</Page>
I've created a new clear style for a button. I then just drop a button in the TVI and set its style. You can do the same thing using data templates, of course.
This is a good example of how the MVVM is very much an after-thought in WPF. You expect there to be Command support of certain gui items, but there isn't, so you're forced to go through an elaborate process (as shown in Will's example) just to get a command attached to something.
Let's hope they address this in WPF 2.0 :-)
I improve good solution from Richard via common Tag property:
MyView.xaml:
<TreeView SelectedItemChanged="TreeView_SelectedItemChanged" Tag="{Binding SelectTreeViewCommand}" >
<TreeViewItem Header="Item1" IsExpanded="True" Tag="Item1" />
<TreeViewItem Header="Item2" IsExpanded="True">
<TreeViewItem Header="Item21" Tag="Item21"/>
</TreeViewItem>
</TreeView>
MyView.xaml.cs
private void TreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
var treeView = (TreeView)sender;
var command = (ICommand)treeView.Tag;
TreeViewItem selectedItem = (TreeViewItem)treeView.SelectedItem;
if (selectedItem.Tag != null)
{
command.Execute(selectedItem.Tag);
}
}
MyViewModel.cs
public RelayCommand selectTreeViewCommand;
[Bindable(true)]
public RelayCommand SelectTreeViewCommand => selectTreeViewCommand ?? (selectTreeViewCommand = new RelayCommand(CanSelectTreeViewCommand, ExecuteSelectTreeViewCommand));
private void ExecuteSelectTreeViewCommand(object obj)
{
Console.WriteLine(obj);
}
private bool CanSelectTreeViewCommand(object obj)
{
return true;
}
The answer provided by Shaggy13spe is very good. But still, it took me some additional time to understand it so I will extend the answer.
Whole TreeView xaml can look like this:
<TreeView x:Name="treeView" Grid.Row="1" Grid.Column="0" ItemsSource="{Binding Tree}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectedItemChanged">
<i:InvokeCommandAction Command="{Binding FilterMeetingsCommand}" CommandParameter="{Binding ElementName=treeView, Path=SelectedItem}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Path=Nodes}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}"></TextBlock>
<TextBlock Text="{Binding Id}"></TextBlock>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
In my View I have a Tree collection
public ObservableCollection<TreeNode> Tree { get; set; }
TreeNode is defined as a simple class:
public class TreeNode
{
public int Id { get; set; }
public string Name { get; set; }
public List<TreeNode> Nodes { get; set; }
public TreeNode(string name)
{
this.Name = name;
this.Nodes = new List<TreeNode>();
}
}
First important point: CommandParameter is not bind to the property on the ViewModel but it is passed to the method. So the method should look like:
private async void FilterMeeting(object parameter){}
Second important point: if you will pass the selected item (in my case object will be TreeNode type) and you will have the hierarchical structure you will face event bubbling. So selecting an item will fire the event for this particular item and for all parents. To resolve this you need to understand that you can pass only one object to the method in ViewModel (not two as in standard event handler) and this object needs to be an event.
In this case change the XAML to following (PassEventArgsToCommand="True" is important here)
<TreeView x:Name="treeView" Grid.Row="1" Grid.Column="0" ItemsSource="{Binding Tree}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectedItemChanged">
<i:InvokeCommandAction Command="{Binding FilterMeetingsCommand}" PassEventArgsToCommand="True"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Path=Nodes}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}"></TextBlock>
<TextBlock Text="{Binding Id}"></TextBlock>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
Then in your handling method, you won't receive the model object, but event args, which have a model object inside.