So I have this code:
<Style TargetType="{x:Type TreeViewItem}">
<Style.Resources>
<Converters:GetElementTypeConverter x:Key="GetElementTypeConverter" />
</Style.Resources>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=., Converter={StaticResource GetElementTypeConverter}}" Value="{x:Type Models:ServerItem}">
<Setter Property="CommandBehaviors:MouseDoubleClick.Command" Value="{Binding ConnectServer}" />
<Setter Property="CommandBehaviors:MouseDoubleClick.CommandParameter" Value="{Binding Path=SelectedItem, RelativeSource={RelativeSource Self}}" />
<Setter Property="Foreground" Value="Gray" />
</DataTrigger>
<DataTrigger Binding="{Binding Path=., Converter={StaticResource GetElementTypeConverter}}" Value="{x:Type Models:DatabaseItem}">
<Setter Property="CommandBehaviors:MouseDoubleClick.Command" Value="{Binding ConnectDb}" />
<Setter Property="CommandBehaviors:MouseDoubleClick.CommandParameter" Value="{Binding Path=SelectedItem, RelativeSource={RelativeSource Self}}" />
<Setter Property="Foreground" Value="Red" />
</DataTrigger>
</Style.Triggers>
</Style>
It defines some properties for tree view item, but it doesn't work entirely - I mean it sets foreground colors, but when I double click any item, it doesn't fire my command.
I take it this is related to your previous question.
RelayCommand<T>
needs to be on the concerned element not the parent VM. That's why you're probably seeing the Foreground
properties work fine but not the Command getting executed since the DataContext
where the command is being looked for(ServerItem
and DatabaseItem
) does not actually define the Commands ConnectServer
and ConnectDb
.ConnectDb
as default and use the trigger to set ConnectServer
for just ServerItem
's on the concerned elements.Now to fix your problem you can define ConnectServer
command in your ServerItem
and ConnectDb
command in your DatabaseItem
, or if you want to keep the commands in the DataContext of the TreeView
, use a RelativeSource
binding to find these commands from the TreeView
.
something like (Tested this and it works fine):
<TreeView ItemsSource="{Binding ServerItems}">
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Style.Resources>
<CommandBehaviors:GetElementTypeConverter x:Key="GetElementTypeConverter" />
</Style.Resources>
<Setter Property="CommandBehaviors:MouseDoubleClick.Command"
Value="{Binding Path=DataContext.ConnectDb,
RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type TreeView}}}" />
<Setter Property="CommandBehaviors:MouseDoubleClick.CommandParameter"
Value="{Binding Path=.}" />
<Setter Property="Foreground"
Value="Black" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=.,
Converter={StaticResource GetElementTypeConverter}}"
Value="{x:Type CommandBehaviors:ServerItem}">
<Setter Property="CommandBehaviors:MouseDoubleClick.Command"
Value="{Binding Path=DataContext.ConnectServer,
RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type TreeView}}}" />
<Setter Property="Foreground"
Value="Tomato" />
</DataTrigger>
</Style.Triggers>
</Style>
</TreeView.ItemContainerStyle>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Databases}">
<TextBlock Text="{Binding}" />
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
Update: (Fix for the recursive DoubleClick
event call of TreeViewItem
's)
In your class MouseDoubleClick
switch:
public class MouseDoubleClick {
...
private static void OnMouseDoubleClick(object sender, RoutedEventArgs e) {
Control control = sender as Control;
ICommand command = (ICommand)control.GetValue(CommandProperty);
object commandParameter = control.GetValue(CommandParameterProperty);
command.Execute(commandParameter);
}
}
to
public class MouseDoubleClick {
...
private static void OnMouseDoubleClick(object sender, RoutedEventArgs e) {
Control control = sender as Control;
var possibleTreeViewItem = sender as TreeViewItem;
if (control == null || (possibleTreeViewItem != null && !possibleTreeViewItem.IsSelected))
return;
ICommand command = (ICommand)control.GetValue(CommandProperty);
object commandParameter = control.GetValue(CommandParameterProperty);
command.Execute(commandParameter);
}
}