Styling custom control - c#

I made my own controls. One inherits from DataGrid and the another from ContentControl. One of them gets the other so I try to expose their properties but as I need many different controls I want to make a Style for my control (the one that inherit from DataGrid) and set the properties from this control to my ContentControl. I just wrote the code like this but it does not work. Any body knows what I am doing wrong?
<Style x:Key="CustomDataGridStyle"
TargetType="{x:Type controls:CustomDataGrid}">
<Setter Property="CurrentRow"
Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type controls:DataGridContainer}}, Path=SelectedItem, Mode=TwoWay}" />
<Setter Property="CaptionVisibility"
Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type controls:DataGridContainer}}, Path=CaptionVisibility, Mode=TwoWay}" />
<Setter Property="CaptionText"
Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type controls:DataGridContainer}}, Path=CaptionText, Mode=TwoWay}" />
<Setter Property="RowValidationErrorTemplate"
Value="{StaticResource BasicRowValidationErrorTemplate}" />
<Setter Property="CurrentView"
Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type controls:DataGridContainer}}, Path=CurrentView, Mode=OneWayToSource}" />
<Setter Property="CurrentColumnHeaderText"
Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type controls:DataGridContainer}}, Path=CurrentColumnHeader, Mode=OneWayToSource}" />
<Setter Property="SelectedCellText"
Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type controls:DataGridContainer}}, Path=SelectedText, Mode=OneWayToSource}" />
<Setter Property="IsDataGridFocused"
Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type controls:DataGridContainer}}, Path=HasFocus, Mode=OneWayToSource}" />
</Style>
And I have defined my control like this
<controls:CustomDataGrid x:Key="DataGridOne" AutoGenerateColumns="True" x:Shared="False" ItemsSource="{Binding UpdateSourceTrigger=PropertyChanged}" />
and the another one
<controls:DataGridContainer Content="{StaticResource DataGridOne}" DataContext="{Binding Products}"
x:Name="dataGridOne" SelectedItem="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type UserControl}},
Path=DataContext.SelectedItem, Mode=TwoWay}" CaptionVisibility="Collapsed"/>

Your style has x:Key attribute set. This means it won't apply to all controls of that type by-default. You should either remove the Key attribute to make the style default and apply to all CustomDataGrid controls, or reference Style in the CustomDataGrid definition like this:
<Window>
<Window.Resources>
<Style x:Key="CustomDataGridStyle" TargetType="{x:Type controls:CustomDataGrid}">
...
</Style>
</Window.Resources>
<controls:CustomDataGrid ... Style="{StaticResource CustomDataGridStyle}" ... />
</Window>

Related

WPF: ItemsControl.Resources Setter - binding to element's content

<ItemsControl>
<ItemsControl.Resources>
<Style TargetType="{x:Type RadioButton}">
<Setter Property="Command" Value="{Binding MyCommand}"/>
<Setter Property="CommandParameter" Value="{Binding RelativeSource={Problem}, Path=Content}"/>
</Style>
</ItemsControl.Resources>
<RadioButton Content="1"/>
<RadioButton Content="2"/>
<RadioButton Content="3"/>
<RadioButton Content="4"/>
<RadioButton Content="5"/>
<RadioButton Content="6"/>
</ItemsControl>
I want to set the CommandParameter of every RadioButton to it's Content.
Which RelativeSource should I use?
I thought it to be correct without setting RelativeSource. But if it's not, you can try following construction - RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type RadioButton}}

Bound ComboBoxItem not displaying

I have a ComboBox used for selecting a file, and based on the user requiremenst the full path should be displayed in the ComboBox, whereas only the filename (minus directory) should be shown in the selectable items. I'm following the MVVM pattern, and the ComboBox is bound to an instance of type FileInfo in the ViewModel, where there is also an ObservableCollection<FileInfo> that becomes the ItemsSource. The current XAML for this is like so:
<ComboBox SelectedItem="{Binding FilePath}" ItemsSource="{Binding AvailableFiles}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Name="FilePathText" Text="{Binding FullName}" TextWrapping="WrapWithOverflow"/>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ComboBoxItem}}, Path=IsSelected}" Value="False">
<Setter TargetName="FilePathText" Property="Text" Value="{Binding Name}"/>
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ComboBoxItem}}, Path=IsSelected}" Value="{x:Null}">
<Setter TargetName="FilePathText" Property="Text" Value="{Binding FullName}"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
The problem is, even though the default value for FilePath is a selectable item in the ItemsSource, and is bound properly (I've used Christian Moser's WPF Inspector to check the DataSource when the application starts), the ComboBox shows nothing until a value is selected. What is causing this? Since that ComboBoxItem's IsSelected property is null, it should be displaying the FullName of the FileInfo object.
Any help given would be greatly appreciated.
If SelectedItem is not contained within ItemsSource at the point of binding, then ComboBox has a nasty habit of setting SelectedItem back to null.
Try and hold off updating SelectedItem until ItemsSource is populated.
From what you are doing you may want to use SelectedValue and SelectedValuePath. This is what I did and it works for me.
I did this in code but this should still work with Binding.
In C#:
availableFiles.Add(new FileInfo(#"Program.cs"));
filebox.ItemsSource = availableFiles;
filebox.SelectedValue = new FileInfo(#"Program.cs");
filebox.SelectedValuePath = "FullName";
and my combobox is template
<ComboBox Name="filebox">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Name="FilePathText" Text="{Binding FullName}" TextWrapping="WrapWithOverflow"/>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ComboBoxItem}}, Path=IsSelected}" Value="False">
<Setter TargetName="FilePathText" Property="Text" Value="{Binding Name}"/>
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ComboBoxItem}}, Path=IsSelected}" Value="{x:Null}">
<Setter TargetName="FilePathText" Property="Text" Value="{Binding FullName}"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
In your case
<ComboBox Name="filebox" SelectedValue="{Binding FileInfoObject}" SelectedValuePath ="FullName">
Update This works
<ComboBox Name="filebox" SelectedValuePath="Name" SelectedItem="{Binding FileInfoObject}" ItemsSource="{Binding AvailableFiles}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Name="FilePathText" TextWrapping="WrapWithOverflow"/>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ComboBoxItem}}, Path=IsSelected}" Value="False">
<Setter TargetName="FilePathText" Property="Text" Value="{Binding Name}"/>
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ComboBoxItem}}, Path=IsSelected}" Value="True">
<Setter TargetName="FilePathText" Property="Text" Value="{Binding FullName}"/>
</DataTrigger>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ComboBoxItem}}, Path=IsSelected}" Value="{x:Null}">
<Setter TargetName="FilePathText" Property="Text" Value="{Binding FullName}"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ComboBox.ItemTemplate>

Stuck on XAML code for TreeView With Checkboxes

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>

Checkbox Command Not Firing When Initially Unchecked

I have a column of checkboxes in a datagrid.
<DataGridTemplateColumn CanUserResize="False" Header="" Width="auto">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<CheckBox Style="{StaticResource CheckBoxSelectTypeStyle}" IsChecked="{Binding Path=Selected}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
I have a command bound to unchecking and checking.
<Style x:Key="CheckBoxSelectTypeStyle" TargetType="{x:Type CheckBox}">
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Command" Value="{Binding DataContext.CheckedCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" />
<Setter Property="CommandParameter" Value="{Binding Path=SelectedItems, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}" />
</Trigger>
<Trigger Property="IsChecked" Value="False">
<Setter Property="Command" Value="{Binding DataContext.UncheckedCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" />
<Setter Property="CommandParameter" Value="{Binding Path=SelectedItems, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}" />
</Trigger>
</Style.Triggers>
</Style>
My problem is that if the checkboxes start as unchecked and you check one, then no commands are fired (This is the problem). If you then uncheck the same checkbox, the uncheck command will fire (As expected). If you then check the same checkbox again, the check command will fire (As expected). Everything will work fine for that checkbox at that point, but the others still have the same problem.
If a checkbox starts as checked it will work fine. My question is how do I make the command fire when the checkbox starts as unchecked. I can't find any reason for it not to work.
Response to suggestion:
I tried to add a trigger for Null, but it has the exact same problem, nothing changed.
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Command" Value="{Binding DataContext.CheckedCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" />
<Setter Property="CommandParameter" Value="{Binding Path=SelectedItems, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}" />
</Trigger>
<Trigger Property="IsChecked" Value="False">
<Setter Property="Command" Value="{Binding DataContext.UncheckedCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" />
<Setter Property="CommandParameter" Value="{Binding Path=SelectedItems, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}" />
</Trigger>
<Trigger Property="IsChecked" Value="{x:Null}">
<Setter Property="Command" Value="{Binding DataContext.UncheckedCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" />
<Setter Property="CommandParameter" Value="{Binding Path=SelectedItems, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}" />
</Trigger>
</Style.Triggers>
ViewModel Code
public ICommand CheckedCommand { get; set; }
public ICommand UncheckedCommand { get; set; }
CheckedCommand = new RelayCommand<IList>(Checked);
UncheckedCommand = new RelayCommand<IList>(Unchecked);
private void Checked(IList selectedItems)
{
ChangedChecked(selectedItems, true);
}
private void Unchecked(IList selectedItems)
{
ChangedChecked(selectedItems, false);
}
private void ChangedChecked(IList selectedItems, bool selected)
{
if (selectedItems.HasValue())
foreach (var item in selectedItems)
if(item is SelectedTypeModel) (item as SelectedTypeModel).Selected = selected;
}
RelayCommand implements ICommand. As I mentioned before, the Checked method is not called when the checkbox starts as unchecked, but it is called when it is checked, unchecked, and checked again or if it starts checked and is unchecked.
What I'm Trying To Do
I have a DataGrid with a column of CheckBoxs. I want to be able to highlight multiple rows, then check/uncheck a CheckBox in one of the selected rows and have all the other rows update to be the same. I also have a keyword filter for the datagrid, so the DataGrid is binding to a ListCollectionView.
Output Information
I enabled debug information for data binding and get this message:
System.Windows.Data Information: 10 : Cannot retrieve value using the binding and no valid fallback value exists; using default instead. BindingExpression:Path=Selected; DataItem=null; target element is 'CheckBox' (Name=''); target property is 'IsChecked' (type 'Nullable`1')
I'm still not sure how to use this information to correct the problem though.
SOLUTION
I did not fix my original problem and I still don't know why it doesn't work correctly, but I have used another method with the same desired result. Here is the changed code:
<Style x:Key="CheckBoxSelectTypeStyle" TargetType="{x:Type CheckBox}">
<Setter Property="Command" Value="{Binding DataContext.CheckedChangedCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" />
<Setter Property="CommandParameter">
<Setter.Value>
<MultiBinding Converter="{StaticResource SelectedItemsCheckedMultiValueConverter}">
<Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}" Path="SelectedItems"/>
<Binding RelativeSource="{RelativeSource Self}" Path="IsChecked"/>
</MultiBinding>
</Setter.Value>
</Setter>
</Style>
public ICommand CheckedChangedCommand { get; set; }
CheckedChangedCommand = new RelayCommand<Tuple<IList, bool>>(CheckedChanged);
Solution
I think you can achieve your goals without any need in triggers (I've tested this solution in small sample app):
so your style would looks like this:
<Style x:Key="CheckBoxSelectTypeStyle" TargetType="{x:Type CheckBox}">
<Setter Property="Command" Value="{Binding DataContext.CheckedCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" />
<Setter Property="CommandParameter" Value="{Binding Path=SelectedItems, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}}" />
...
There will be only one command in your view model. And as parameter that command will receive list of selected items. So only one thing is missing - whether user is about to check or uncheck checkbox. At the moment I can think of one possible way of passing this info along with SelectedItems - write MultiBinding with custom converter which will put selectedItems and current value of IsChecked in something like Tuple<..., bool>
<Setter Property="CommandParameter">
<Setter.Value>
<MultiBinding Converter="{x:Static PackTupleConverter.Instance}">
<Binding RelativeSource="{RelativeSource AncestorType=DataGrid}" Path="SelectedItems"/>
<Binding RelativeSource="{x:Static RelativeSource.Self}" Path="IsChecked"/>
</MultiBinding>
</Setter.Value>
</Setter>
end
I was able to repro your problem by simply putting same checkbox inside ListBox. Once that done first time I click on checkbox - command don't get called
here is sample window xaml:
<Window.Resources>
<Style x:Key="CheckBoxSelectTypeStyle" TargetType="{x:Type CheckBox}">
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Command" Value="{Binding DataContext.Test, RelativeSource={RelativeSource AncestorType=Window}}" />
</Trigger>
<Trigger Property="IsChecked" Value="False">
<Setter Property="Command" Value="{Binding DataContext.Test, RelativeSource={RelativeSource AncestorType=Window}}" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Grid>
<ListBox>
<ListBox.Items>
<CheckBox Style="{StaticResource CheckBoxSelectTypeStyle}" />
</ListBox.Items>
</ListBox>
</Grid>
and sode behaind:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = this;
Test = new DelegateCommand(TestCommand);
}
public ICommand Test { get; set; }
private void TestCommand()
{
}
}
Here is what I've discovered in output regarding binding:
System.Windows.Data Information: 10 : Cannot retrieve value using the binding and no valid fallback value exists; using default instead. BindingExpression:Path=DataContext.Test; DataItem=null; target element is 'CheckBox' (Name=''); target property is 'Command' (type 'ICommand')

How to get this binding for item instead of TreeViewItem?

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>

Categories