0

I have a WPF app where the view models are in a .Net Standard library so they can be reused in mobile apps. This means the view models do not have access to the actual controls. I have a tree view that uses a DataTemplate to define the tree view item. I then have a ContentControl which displays a vectored image. The Fill of the vectored image is data bound to the view model. The problem is that I need to change colors when the tree view item is no longer focused but still selected. How can my view model data bind to the tree view item focused property? After more research it seems I need to bind from the control to my viewmodel one way to IsSelectionActive however the TreeViewItem style does not permit binding to the IsSelectionActive stating there is no setter.

<DataTemplate x:Key="NormalTemplate"> <StackPanel Orientation="Horizontal" ToolTip="{Binding Tooltip}" Opacity="{Binding Opacity}"> <ContentControl Template="{StaticResource TreeViewItemImage}" Focusable="False"/> <fa:ImageAwesome Style="{StaticResource TreeNodeIsWaitingForResult}" Visibility="{Binding IsRunning, Converter={StaticResource BooleanToVisibilityConverter}, FallbackValue=Hidden}"/> <TextBlock Text="{Binding Text}" Style="{StaticResource TreeViewItemTextBlockStyle}" /> <StackPanel.ContextMenu> <ContextMenu ItemContainerStyle="{StaticResource ContextMenuItemStyle}" ItemsSource="{Binding MenuItemVMs}" Visibility="{Binding MenuItemVisibility, Converter={StaticResource BooleanToVisibilityConverter}, FallbackValue=Hidden}"/> </StackPanel.ContextMenu> </StackPanel> </DataTemplate> 

I have made the following changes per comments but receive the following error when attempting to load the vector image resource style:

System.Windows.Markup.XamlParseException: 'A 'Binding' cannot be set on the 'Property' property of type 'Trigger'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject.'

Here is my updated style:

 <Style x:Key="HostsTreeNodeStyle" TargetType="{x:Type ContentControl}" BasedOn="{StaticResource TreeNodeStyle}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="ContentControl"> <Viewbox Style="{StaticResource TreeNodeViewboxStyle}"> <Canvas Width="24" Height="24"> <Path Data="M4,1H20A1,1 0 0,1 21,2V6A1,1 0 0,1 20,7H4A1,1 0 0,1 3,6V2A1,1 0 0,1 4,1M4,9H20A1,1 0 0,1 21,10V14A1,1 0 0,1 20,15H4A1,1 0 0,1 3,14V10A1,1 0 0,1 4,9M4,17H20A1,1 0 0,1 21,18V22A1,1 0 0,1 20,23H4A1,1 0 0,1 3,22V18A1,1 0 0,1 4,17M9,5H10V3H9V5M9,13H10V11H9V13M9,21H10V19H9V21M5,3V5H7V3H5M5,11V13H7V11H5M5,19V21H7V19H5Z" /> </Canvas> </Viewbox> <ControlTemplate.Triggers> <MultiDataTrigger> <MultiDataTrigger.Conditions> <Condition Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=TreeViewItem}}" Value="True"/> <Condition Binding="{Binding IsKeyboardFocusWithin, RelativeSource={RelativeSource AncestorType=TreeViewItem}}" Value="False"/> </MultiDataTrigger.Conditions> <Setter Property="Foreground" Value="{Binding Color1}"/> </MultiDataTrigger> <MultiDataTrigger> <MultiDataTrigger.Conditions> <Condition Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=TreeViewItem}}" Value="True"/> <Condition Binding="{Binding IsKeyboardFocusWithin, RelativeSource={RelativeSource AncestorType=TreeViewItem}}" Value="True"/> </MultiDataTrigger.Conditions> <Setter Property="Foreground" Value="{Binding Color2}"/> </MultiDataTrigger> <Trigger Property="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=TreeViewItem}}" Value="false"> <Setter Property="Foreground" Value="{Binding Color3}"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> 

1 Answer 1

1

You can use TreeViewItem.IsSelected and UIElement.IsKeyboardFocusWithin to create a MultiDataTrigger for these conditions.

Here's an example which uses this approach to change the Text of a TextBlock if it is inside a TreeViewItem which is selected, but not in focus:

public partial class MainWindow : Window { public List<FooItem> Items { get; } = new List<FooItem> { new FooItem() { Name = "A" }, new FooItem() { Name = "B" }, new FooItem() { Name = "C" }, new FooItem() { Name = "D" }}; } public class FooItem { public string Name { get; set; } public string SelectedButNotFocusedName => Name + "*"; } 
<Window x:Class="CSharpTest.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" DataContext="{Binding RelativeSource={RelativeSource Self}}"> <DockPanel> <TreeView ItemsSource="{Binding Items}" DockPanel.Dock="Left"> <TreeView.ItemTemplate> <DataTemplate> <TextBlock> <TextBlock.Style> <Style TargetType="TextBlock"> <Setter Property="Text" Value="{Binding Name}"/> <Style.Triggers> <MultiDataTrigger> <MultiDataTrigger.Conditions> <Condition Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=TreeViewItem}}" Value="True"/> <Condition Binding="{Binding IsKeyboardFocusWithin, RelativeSource={RelativeSource AncestorType=TreeViewItem}}" Value="False"/> </MultiDataTrigger.Conditions> <Setter Property="Text" Value="{Binding SelectedButNotFocusedName}"/> </MultiDataTrigger> </Style.Triggers> </Style> </TextBlock.Style> </TextBlock> </DataTemplate> </TreeView.ItemTemplate> </TreeView> <TextBox/> </DockPanel> </Window> 

The TextBox at the end is only there as another element that you can give focus to see that the code works.

You can expose your alternate colors as a property of your view model and then use a setup like the above to switch between them in the UI.

Sign up to request clarification or add additional context in comments.

2 Comments

I have made changes to the question per your comments. I am now receiving the following error: System.Windows.Markup.XamlParseException: 'A 'Binding' cannot be set on the 'Property' property of type 'Trigger'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject.'
My goal here is to actually bind to IsKeyboardFocusWithin so I can handle the colors in my view model rather than the layout styles.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.