I have several treeviews that are populated at the code level.
I want to apply checkboxes to them all with minimal code.
i can see the checkboxes and the items names i used to populate the treeviews with no problem however the treeview isnt expanding.
This is the resource Dictionary. i can see that all the settings are being implemented
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:col="clr-namespace:System.Collections;assembly=mscorlib"
xmlns:Primitives="clr-namespace:System.Windows.Controls.Primitives;assembly=System.Windows.Controls.Layout.Toolkit"
xmlns:ToolKit="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Layout.Toolkit"
x:Name="MainDefaultStyle"
>
<Style TargetType="TreeView">
<Setter Property="Background" Value="White"/>
<Setter Property="Height" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Grid}}, Path=ActualHeight}" />
<Setter Property="Width" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Grid}}, Path=ActualWidth}" />
</Style>
<Style TargetType="TreeViewItem" x:Name="TreeViewItem">
<Style.Resources>
<SolidColorBrush Color="AliceBlue" x:Key="{x:Static SystemColors.HighlightBrushKey}"/>
<SolidColorBrush Color="Black" x:Key="{x:Static SystemColors.HighlightTextBrush}"/>
</Style.Resources>
<Setter Property="Background" Value="White" />
<Setter Property="VerticalAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="Height" Value="{Binding BindsDirectlyToSource=True}"/>
<Setter Property="Width" Value="{Binding BindsDirectlyToSource=True}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TreeViewItem" >
<StackPanel>
<CheckBox
x:Name="CheckBox1"
Focusable="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TreeViewItem}}, Path=IsSelected}"
Grid.Column="0"
>
<TextBlock
Margin="1"
Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type TreeViewItem}}, Path=Header}"
Focusable="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TreeViewItem}}, Path=IsSelected}"
Foreground="Black"
Grid.Column="1"
Background="AliceBlue">
</TextBlock>
</CheckBox>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
this is the code in the MainWindow
<TreeView Name="TreeComputers" BorderBrush="Transparent" >
<TreeViewItem Header="This is a test" >
<TreeViewItem Header="Another test"></TreeViewItem>
</TreeViewItem>
</TreeView>
my treeview triggers are created in the code.
TreeComputers.SelectedItemChanged += new RoutedPropertyChangedEventHandler<object>(TreeView_SelectionChanged);
TreeUsers.SelectedItemChanged += new RoutedPropertyChangedEventHandler<object>(TreeView_SelectionChanged);
Somehow i need to be able to click the items in the treeview that now have the checkbox on them and trigger the routed command..
any ideas ?
Is your problem that you can no longer expand items in the tree to see the child items?
I think your problems is that you want to set TreeView.ItemTemplate to be a HierarchicalDataTemplate.
Something like:
<Setter Property="ItemTemplate">
<Setter.Value>
<HierarchicalDataTemplate ItemsSource="{Binding Children}">
<StackPanel>
<CheckBox
x:Name="CheckBox1"
Focusable="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TreeViewItem}}, Path=IsSelected}"
Grid.Column="0">
<TextBlock
Margin="1"
Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type TreeViewItem}}, Path=Header}"
Focusable="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TreeViewItem}}, Path=IsSelected}"
Foreground="Black"
Grid.Column="1"
Background="AliceBlue">
</TextBlock>
</CheckBox>
</StackPanel>
</HierarchicalDataTemplate >
</Setter.Value>
</Setter>
Related
I'm trying to create a button template where the button image content changes. However, I get no image showing at all with the following code. What am I doing wrong? Setting the style directly in the Page xaml works fine.
<Style x:Key="NetworkConnectivity" TargetType="Button">
<Setter Property="Width" Value="120"/>
<Setter Property="Height" Value="120"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Opacity" Value="0.7"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Image Width="50">
<Image.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding NetConfig}" Value="false">
<Setter Property="Image.Source" Value="/images/Unconfigured.png"/>
</DataTrigger>
<DataTrigger Binding="{Binding NetConfig}" Value="true">
<Setter Property="Image.Source" Value="/images/Disconnected.png"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
Not the exact solution but an alternative. Below is a excerpt from my work that shows how to switch images for buttons based on triggers. Instead of style, I use a usercontrol which is reused. The data that are bound are dependency properties. You can use data trigger. In your case assign two images, make one collapsed and on trigger toggle collapse.
<UserControl x:Class="ParameterModule.Base.Controls.ButtonWImage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:ParameterModule.Base.Controls"
mc:Ignorable="d"
x:Name="UctrlButtonWImage"
d:DesignHeight="100" d:DesignWidth="100">
<Button Click="Button_Click" CommandParameter="{Binding CommandParameter, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:ButtonWImage}}}" Command="{Binding Command, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:ButtonWImage}}}" Cursor="Hand" >
<Button.Template>
<ControlTemplate TargetType="{x:Type Button}">
<StackPanel>
<Image x:Name="PrimaryImage" Source="{Binding PrimaryImage, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:ButtonWImage}}}" Visibility="Visible" Stretch="UniformToFill" StretchDirection="Both"/>
<Image x:Name="SecondaryImage" Source="{Binding HoverImage, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:ButtonWImage}}}" Visibility="Collapsed" Stretch="UniformToFill" StretchDirection="Both"/>
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="PrimaryImage" Property="Visibility" Value="Collapsed"/>
<Setter TargetName="SecondaryImage" Property="Visibility" Value="Visible"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
</UserControl>
I need to add "Select All" to my wpf application ,
I've tried to do a simple binding but it doesn't work .
Can Someone Please advise , performing a simple binding
or other strait forward solution ?
Here's my treeview xaml :
<TreeView Name="CurrentTreeView" Margin="5" BorderBrush="Transparent" BorderThickness="0"
ScrollViewer.VerticalScrollBarVisibility="Auto">
<TreeView.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<Setter Property="IsSelected" Value="{Binding IsSelected}" />
<Setter Property="IsExpanded" Value="{Binding IsExpanded}" />
<Setter Property="HeaderTemplate" >
<Setter.Value>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox
Focusable="False"
Checked="CheckedItemCurreuntSession"
Unchecked="UnCheckedItemCurreuntSession"
Name="treeChk"
Tag="{Binding Path=ChName}"
Style="{StaticResource CheckBoxStyle1}"
IsChecked="{Binding Path=IsChecked}"
VerticalAlignment="Center"/>
<TextBlock VerticalAlignment="Center" Text="{Binding}"
Margin="5"
TextOptions.TextFormattingMode="Display"
TextOptions.TextHintingMode="Auto"
/>
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
<Style x:Key="CheckBoxListStyle" TargetType="{x:Type ListBox}">
<Setter Property="SelectionMode" Value="Multiple"/>
<Setter Property="ItemContainerStyle">
<Setter.Value>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Margin" Value="2"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<CheckBox Focusable="False" IsChecked="{Binding Path=IsSelected, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent} }">
<ContentPresenter/>
</CheckBox>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Setter.Value>
</Setter>
</Style>
I have a canvas which is bound to a List of items. Each item has his own X and Y field and is painted as rectangles on the canvas.
Each item has its contextmenu which in this case is bound to a List and is filled dynamically (e.g.: "On", "Off").
I'm now trying to pass the sender (item where the Contextmenu is assigned to) and the string of the binding as CommandParameter the viewmodel.
e.g.: itemA, "On"
How should I do this?
Here is my code:
<ItemsControl
x:Name="Overlay"
Grid.Column="1"
GCextAp:Dragging.IsDragging="{Binding IsDragging, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
ItemsSource="{Binding Path=MapElements, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas
localAp:MapProperties.GenerateMapElementFunc="{Binding CreateMapElementFunc}"
localAp:MapProperties.IsEditingMode="{Binding IsEditMode}"
localAp:MapProperties.ManipulationFinished="{Binding ManipulationFinishedDelegate}"
localAp:MapProperties.ScaleFactor="{Binding ElementName=Overlay, Path=DataContext.ScaleFactor}"
AllowDrop="True"
RenderOptions.BitmapScalingMode="LowQuality">
<Canvas.Style>
<Style TargetType="Canvas">
<Setter Property="Effect">
<Setter.Value>
<DropShadowEffect
BlurRadius="8"
Direction="270"
ShadowDepth="2.5"
Color="#DDDDDD" />
</Setter.Value>
</Setter>
<Setter Property="Opacity" Value="1" />
<Setter Property="Background" Value="{x:Null}" />
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding ElementName=Overlay, Path=(GCextAp:Dragging.IsDragging)}" Value="true" />
<Condition Binding="{Binding IsEditMode}" Value="true" />
</MultiDataTrigger.Conditions>
<Setter Property="Background" Value="WhiteSmoke" />
<Setter Property="Opacity" Value="0.1" />
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Canvas.Style>
<i:Interaction.Behaviors>
<localBehave:MapCanvasDropBehavior />
</i:Interaction.Behaviors>
</Canvas>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding DynamicX}" />
<Setter Property="Canvas.Top" Value="{Binding DynamicY}" />
</Style>
</ItemsControl.ItemContainerStyle>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Rectangle
Width="{Binding DynamicWidth}"
Height="{Binding DynamicHeight}"
Stroke="Black"
Tag="{Binding DataContext, RelativeSource={RelativeSource AncestorType=Canvas}}"
Visibility="{Binding IsVisible, Converter={StaticResource converter}}">
<Rectangle.Fill>
<ImageBrush ImageSource="{Binding Image}" />
</Rectangle.Fill>
<i:Interaction.Behaviors>
<localBehave:MapElementMoveBehavior />
</i:Interaction.Behaviors>
<Rectangle.ContextMenu>
<ContextMenu>
<MenuItem Header="Commands" ItemsSource="{Binding Path=PlacementTarget.Tag.AvailableElementCommands, RelativeSource={RelativeSource AncestorType=ContextMenu}, UpdateSourceTrigger=PropertyChanged}">
<MenuItem.ItemContainerStyle>
<Style TargetType="{x:Type MenuItem}">
<Setter Property="Header" Value="{Binding}" />
<Setter Property="Command" Value="{Binding Path=PlacementTarget.Tag.CMD_MapElement, RelativeSource={RelativeSource AncestorType=ContextMenu}}" />
<Setter Property="CommandParameter" Value=" I have no idea" />
</Style>
</MenuItem.ItemContainerStyle>
</MenuItem>
</ContextMenu>
</Rectangle.ContextMenu>
</Rectangle>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Sorry about asking questions which are unclear or not usefull :-). Anyway I found the solution myself.
The command paramater should look like this:
<Setter Property="CommandParameter">
<Setter.Value>
<MultiBinding Converter="{StaticResource menuItemCommandConverter}">
<MultiBinding.Bindings>
<Binding Path="DataContext" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType=ContextMenu}" />
<Binding Path="Header" RelativeSource="{RelativeSource Mode=Self}" />
</MultiBinding.Bindings>
</MultiBinding>
</Setter.Value>
</Setter>
I have one datagrid.The columns header name is binding from one xml file.
Now I need to add filter text box for header template from datagrid.
without textbox filter option the datagrid shown as per the below.
After adding filter text box the datagrid as shown as below
I don't want to show textbox in first column i.e checkbox column,how to do this?
The xaml code is attached below
<UserControl .....>
<UserControl.Resources>
<ResourceDictionary>
<DataGridTemplateColumn x:Key="CustomCheckBoxTemplate">
<DataGridTemplateColumn.HeaderTemplate>
<DataTemplate >
<CheckBox Name="ColumnHearderCheckBox" IsThreeState="True" PreviewMouseLeftButtonDown="OnHeaderCheckBoxMouseButtonDown" />
</DataTemplate>
</DataGridTemplateColumn.HeaderTemplate >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox PreviewMouseLeftButtonDown="OnCellCheckBoxPreviewMouseLeftButtonDown" IsChecked="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType=DataGridRow}, Path=IsSelected,Mode=TwoWay}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn >
<ContextMenu x:Key="ColumnHeaderContextMenu"
FontSize="{Binding PlacementTarget.FontSize, RelativeSource={RelativeSource Self}}">
<ContextMenu.ItemContainerStyle>
<Style TargetType="{x:Type MenuItem}" >
<EventSetter Event= "Click" Handler="OnContextMenuItemClicked" />
<Setter Property="IsCheckable" Value="True" />
<Setter Property="Header" Value="{Binding Header}" />
<Style.Triggers>
<DataTrigger Binding="{Binding Visibility}" Value="Visible">
<Setter Property="IsChecked" Value="True"/>
</DataTrigger>
<DataTrigger Binding="{Binding Visibility}" Value="Collapsed">
<Setter Property="IsChecked" Value="False"/>
</DataTrigger>
<DataTrigger Binding="{Binding Visibility}" Value="Hidden">
<Setter Property="IsChecked" Value="False"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ContextMenu.ItemContainerStyle>
</ContextMenu>
</ResourceDictionary>
</UserControl.Resources>
<Grid Margin="5,0,0,0">
<Grid.Resources>
<Style TargetType="{x:Type DataGridColumnHeader}" BasedOn="{StaticResource {x:Type DataGridColumnHeader}}">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="Height" Value="30"/>
<Setter Property="Foreground" Value="WhiteSmoke"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridColumnHeader}" >
<Border x:Name="Border"
Padding="2"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid x:Name="LayoutGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="{Binding RelativeSource={RelativeSource TemplatedParent},
Path=ActualHeight}" />
</Grid.ColumnDefinitions>
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Content, RelativeSource=
{RelativeSource Mode=TemplatedParent}}"/>
<TextBox x:Name="txtId" Width="100" />
</StackPanel>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<DataTemplate x:Key="CustomTemplate">
<StackPanel Orientation="Horizontal" >
<Image Source="{Binding Converter={StaticResource StringToImageConverter}}" Height="30" Width="30" Margin="30,0,0,0" HorizontalAlignment="Right"/>
</StackPanel>
</DataTemplate>
<ContextMenu x:Key="RowMenu" DataContext="{Binding DataContext, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid}}">
<MenuItem Header="Delete" Command="{Binding DeleteCommand}" CommandParameter="{Binding SelectedItems, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid}}" >
</MenuItem>
<MenuItem Header="Edit" Command="{Binding EditCommand}"/>
</ContextMenu>
<Style x:Key="DefaultRowStyle" TargetType="{x:Type DataGridRow}" BasedOn="{StaticResource {x:Type DataGridRow}}">
<Setter Property="ContextMenu" Value="{StaticResource RowMenu}" />
</Style>
</Grid.Resources>
<DataGrid x:Name="dataGrid" IsReadOnly="True" ItemsSource="{Binding PatientStudyList}" SelectionMode="{Binding SelectionMode, Converter={StaticResource SelectionModeToStringConverter}}"
AlternationCount="2" GridLinesVisibility="Horizontal" AutoGenerateColumns="False" BorderThickness="1"
RowStyle="{StaticResource DefaultRowStyle}" HorizontalAlignment="Stretch">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Unloaded">
<i:InvokeCommandAction Command="{Binding DataGridUnloadedCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
<DataGrid.ColumnHeaderStyle>
<Style TargetType="{x:Type DataGridColumnHeader}" BasedOn="{StaticResource {x:Type DataGridColumnHeader}}">
<Setter Property="ContextMenu" Value="{StaticResource ColumnHeaderContextMenu}" />
<Setter Property="Height" Value="50" />
</Style>
</DataGrid.ColumnHeaderStyle>
</DataGrid>
</Grid>
</UserControl>
You are changing the DataGridColumnHeader.Template with a new ControlTemplate
The CustomCheckBoxTemplate is providing a DataGridTemplateColumn.HeaderTemplate as DataTemplate which targets the DataGridColumnHeader.ContentTemplate. However, your ControlTemplate doesn't use the DataGridColumnHeader.ContentTemplate internally, so the HeaderTemplate part of your CustomCheckBoxTemplate will be ignored.
If it works for you, just define the DataGridColumnHeader.ContentTemplate instead of the DataGridColumnHeader.Template in your style (will behave a little differently).
<Style TargetType="{x:Type DataGridColumnHeader}" BasedOn="{StaticResource {x:Type DataGridColumnHeader}}">
...
<!-- Do not define Property="Template" here -->
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<!-- Similar to your ControlTemplate, but the TemplateBinding parts need to be reworked -->
Otherwise use the DataGridColumnHeader.ContentTemplate inside your ControlTemplate.
<!-- Old -->
<TextBlock Text="{Binding Content, RelativeSource=
{RelativeSource Mode=TemplatedParent}}"/>
<!-- Replace by -->
<ContentPresenter
Content="{Binding Content, RelativeSource={RelativeSource Mode=TemplatedParent}}"
ContentTemplate="{TemplateBinding ContentTemplate}"/>
Didn't test all part, so there might still be errors in my suggestion.
Edit Actually, the last part about the ContentPresenter doesn't prevent the txtId textbox. Here is an idea where the ControlTemplate is using Triggers to change the visible parts based on the ContentTemplate property being set. Note I changed some minor details like the ColumnDefinition Width for my testing.
<ControlTemplate TargetType="{x:Type DataGridColumnHeader}" >
<Border x:Name="Border"
Padding="2"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<Grid x:Name="LayoutGrid"
Visibility="Collapsed">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Content, RelativeSource={RelativeSource Mode=TemplatedParent}}"/>
<TextBox x:Name="txtId" Width="100" />
</StackPanel>
</Grid>
<ContentPresenter
x:Name="TemplatedContent"
Visibility="Visible"
Content="{Binding Content, RelativeSource={RelativeSource Mode=TemplatedParent}}"
ContentTemplate="{TemplateBinding ContentTemplate}"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="ContentTemplate" Value="{x:Null}">
<Setter Property="Visibility" TargetName="TemplatedContent" Value="Collapsed"/>
<Setter Property="Visibility" TargetName="LayoutGrid" Value="Visible"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
I got the following code :
<HierarchicalDataTemplate x:Key="AssignedRate" ItemsSource="{Binding Children}" DataType="{x:Type local:UnitRateCatElement}">
<ContentControl>
<ContentControl.Template>
<ControlTemplate>
<StackPanel Tag="{Binding DataContext, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}">
<TextBlock Text="{Binding Category.Description}" />
<StackPanel.ContextMenu>
<ContextMenu>
<MenuItem Header="Add Unit Rate"
Command="{Binding Path=PlacementTarget.Tag.AddUnitRateCommand, RelativeSource={RelativeSource AncestorType=ContextMenu}}"/>
</ContextMenu>
</StackPanel.ContextMenu>
</StackPanel>
</ControlTemplate>
</ContentControl.Template>
<ContentControl.Style>
<Style TargetType="{x:Type ContentControl}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsDefined, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type TreeViewItem}}}" Value="True">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<TextBlock Text="Hello, it works!" />
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
</HierarchicalDataTemplate>
The binding in the line : <DataTrigger Binding="{Binding Path=IsDefined, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type TreeViewItem}}}" Value="True">
is incorrect (VS says so). How can I get this to work? The class local:UnitRateCatElement does have a IsDefined property. But I cannot get the binding right to point to that object. How can I get this binding right?
Try
Binding="{Binding Path=DataContext.IsDefined, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type TreeViewItem}}}"
I think you should be doing this -
<DataTrigger Binding="{Binding Path=DataContext.IsDefined,
RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType={x:Type TreeViewItem}}}" Value="True">
as your RelativeSource binding points to the TreeViewItem, which doesn't have IsDefined property, it is present in the DataContext of the TreeViewItem.
Update:
For your second problem (trigger not working), this is happening because you are setting the Template explicitly i.e. Local Value which is having higher precedence then Triggers; this should work -
<ControlTemplate x:Key="DefaultTemplate">
<StackPanel Tag="{Binding DataContext, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}">
<TextBlock Text="{Binding Category.Description}" />
<StackPanel.ContextMenu>
<ContextMenu>
<MenuItem Header="Add Unit Rate"
Command="{Binding Path=PlacementTarget.Tag.AddUnitRateCommand, RelativeSource={RelativeSource AncestorType=ContextMenu}}"/>
</ContextMenu>
</StackPanel.ContextMenu>
</StackPanel>
</ControlTemplate>
<ControlTemplate x:Key="DefinedTemplate">
<TextBlock Text="Hello, it works!" />
</ControlTemplate>
<HierarchicalDataTemplate x:Key="AssignedRate" ItemsSource="{Binding Children}"
DataType="{x:Type local:UnitRateCatElement}">
<ContentControl>
<ContentControl.Style>
<Style TargetType="{x:Type ContentControl}">
<Setter Property="Template" Value={StaticResource DefaultTemplate}>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=DataContext.IsDefined, RelativeSource=
{RelativeSource Mode=FindAncestor, AncestorType={x:Type TreeViewItem}}}"
Value="True">
<Setter Property="Template" Value={StaticResource DefinedTemplate}>
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
</HierarchicalDataTemplate>