The following code throws an exception:
<TreeView
ItemsSource="{Binding TreeRootInstance}"
x:Name="Htree"
ItemTemplate="CellTemplate"
SelectedItemChanged="HTree_OnSelectedItemChanged"
KeyDown="HTree_KeyDown">
<TreeView.Resources>
<DataTemplate x:Key="CellTemplate">
<Border>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<ToggleButton x:Name="Expander"
HorizontalAlignment="Right"
Focusable="False"
Grid.Column="1"
IsChecked="{Binding Path=IsExpanded, RelativeSource={RelativeSource AncestorType={x:Type vw:TreeViewItem}}}"
ClickMode="Press"/>
<TextBlock
Text="{Binding Name}"
Grid.Column="0" />
</Grid>
</Border>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Path=HasItems, RelativeSource={RelativeSource AncestorType={x:Type TreeViewItem}}}" Value="False">
<Setter TargetName="Expander" Property="Visibility" Value="Hidden"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
<Style TargetType="{x:Type TreeViewItem}" x:Key="aa">
<Setter Property="IsTabStop" Value="True"/>
<Setter Property="TabIndex" Value="0"/>
<Setter Property="IsExpanded" Value="{Binding Path=IsExpanded,Mode=TwoWay}"/>
<Setter Property="ItemsSource" Value="{Binding Children}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TreeViewItem}">
<StackPanel>
<Border Name="Bd">
</Border>
<ItemsPresenter x:Name="ItemsHost" />
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsExpanded" Value="false">
<Setter TargetName="ItemsHost"
Property="Visibility"
Value="Collapsed"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type TreeView}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TreeView}">
<Border BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemContainerStyle" Value="{StaticResource aa}" />
</Style>
</TreeView.Resources>
</TreeView>
(I've omitted some of the code but the main hirerchy is still there...)
The exception is a xaml parse exception, on ItemsControl.ItemTemplate.
Could you please tell me how to make this code work?
Thanks,
Li
You can't use a plain string as a resource locator, you need to use either a StaticResource markup extension, i.e., ItemTempate="{StaticResource CellTemplate}"
The ItemTemplate line should read:
ItemTemplate="{StaticResource CellTemplate}"
Related
I have some textbox whith style from a template like this
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border Background="White" CornerRadius="8" x:Name="container">
<Grid>
<TextBox Background="White"
FontFamily="Poppins" FontSize="11"
VerticalAlignment="Center"
Padding="5"
Name="SearchBox"
Foreground="Black"
Margin="2"
BorderThickness="0"
Text="{TemplateBinding Text}"
/>
<TextBlock Text="{TemplateBinding Tag}" Name="Placeholder"
FontSize="11" FontFamily="Poppins"
Foreground="Gray"
VerticalAlignment="Center"
IsHitTestVisible="False"
Grid.Column="1" Padding="5" Margin="6,0,0,0">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding Text, ElementName=SearchBox}" Value="">
<Setter Property="Visibility" Value="Visible"></Setter>
</DataTrigger>
</Style.Triggers>
<Setter Property="Visibility" Value="Hidden"></Setter>
</Style>
</TextBlock.Style>
</TextBlock>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background" Value="#E6E6E6" TargetName="container"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Just to show an placeholder. This works but something goes wrong when I try to bind property Text to a view model.
<TextBox Text="{Binding NombreCliente}"
Style="{StaticResource SearchTextBox}"
Grid.Row="1"
Tag="Nombre"/>
I've done test and while the textbox have this style the binding always return null or "".
I find in other ask that there's something whith binding parent and they solve whith this
<TextBox Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Text,
UpdateSourceTrigger=PropertyChanged}"....
But if i bind text to a template parent, how do I bind to viewmodel?
A template of a TextBox should not contain another TextBox control.
Replace it with a ScrollViewer and set the FontFamily and FontSize properties using Style setters:
<ControlTemplate TargetType="{x:Type TextBox}">
<Border Background="White" CornerRadius="8" x:Name="container">
<Grid>
<ScrollViewer x:Name="PART_ContentHost" Margin="2" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
<TextBlock Text="{TemplateBinding Tag}" Name="Placeholder"
FontSize="11" FontFamily="Poppins"
Foreground="Gray"
VerticalAlignment="Center"
IsHitTestVisible="False"
Grid.Column="1" Padding="5" Margin="6,0,0,0">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding Text, ElementName=SearchBox}" Value="">
<Setter Property="Visibility" Value="Visible"></Setter>
</DataTrigger>
</Style.Triggers>
<Setter Property="Visibility" Value="Hidden"></Setter>
</Style>
</TextBlock.Style>
</TextBlock>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background" Value="#E6E6E6" TargetName="container"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
If this is a template for use in a TextBox, then you have created it incorrectly.
In fact, instead of giving the TextBox room to display the text, you have overlapped it on top with another TextBox that has nothing to do with the one this template will use.
TextBox to display text looks in its template for a ScrollViewer named PART_ContentHost.
And all the property settings of the TextBox must be moved to Setters outside the template.
Example template:
<Style TargetType="TextBox">
<Setter Property="Background" Value="White"/>
<Setter Property="FontFamily" Value="Poppins"/>
<Setter Property="FontSize" Value="11"/>
<Setter Property="Padding" Value="5"/>
<Setter Property="Foreground" Value="Black"/>
<Setter Property="Margin" Value="2"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Border Background="{TemplateBinding Background}"
CornerRadius="8" x:Name="container"
Padding="{TemplateBinding Padding}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<ScrollViewer x:Name="PART_ContentHost"
Focusable="false"
HorizontalScrollBarVisibility="Hidden"
VerticalScrollBarVisibility="Hidden"/>
<TextBlock Text="{TemplateBinding Tag}" Name="Placeholder"
FontSize="11" FontFamily="Poppins"
Foreground="Gray"
VerticalAlignment="Center"
IsHitTestVisible="False"
Grid.Column="1" Padding="5" Margin="6,0,0,0">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding Text, ElementName=SearchBox}" Value="">
<Setter Property="Visibility" Value="Visible"></Setter>
</DataTrigger>
</Style.Triggers>
<Setter Property="Visibility" Value="Hidden"/>
</Style>
</TextBlock.Style>
</TextBlock>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Background" Value="#E6E6E6" TargetName="container"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I have Listbox with a Checkbox. That's the way how I built it:
<Style x:Key="_ListBoxItemStyleCheckBox" TargetType="ListBoxItem">
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<CheckBox Name="_Border" Margin="5,2" IsChecked="{TemplateBinding IsSelected}">
<ContentPresenter />
</CheckBox>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
This is my ListBox:
<ListBox
VerticalAlignment="Stretch"
ItemsSource="{Binding Items}"
SelectionMode="Multiple"
ItemContainerStyle="{StaticResource _ListBoxItemStyleCheckBox}">
<ListBoxItem>ListBox Item #1</ListBoxItem>
<ListBoxItem>ListBox Item #2</ListBoxItem>
<ListBoxItem>ListBox Item #3</ListBoxItem>
</ListBox>
When I hover over the Checkbox I get the default color (blue). How can I change this color?
I don't want to change the color of the text. Only the border color of the Checkbox.
Thank you for any help!
You should create template.
CheckBox Template Sample
<Style TargetType="{x:Type CheckBox}" x:Key="chb">
<Setter Property="Margin" Value="5 2 5 2"/>
<Setter Property="IsChecked" Value="{Binding RelativeSource={RelativeSource AncestorType=ListBoxItem}, Path=IsSelected}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type CheckBox}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border x:Name="border"
Grid.Column="0"
Width="20"
Height="20"
Background="Transparent"
BorderBrush="Black"
BorderThickness="2">
<Viewbox x:Name="view"
Width="22"
Height="22"
Visibility="Collapsed"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<Canvas Width="24" Height="24">
<Path Data="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z" Fill="#333333"/>
</Canvas>
</Viewbox>
</Border>
<TextBlock Grid.Column="1"
Text="{Binding RelativeSource={RelativeSource AncestorType=ListBoxItem}, Path=Content}"
Margin="5 0 0 0"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="border" Property="BorderBrush" Value="Red"/>
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="view" Property="Visibility" Value="Visible"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Connnecting by using StaticResource
<Style x:Key="_ListBoxItemStyleCheckBox" TargetType="ListBoxItem">
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<CheckBox Name="_Border" Style="{StaticResource chb}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
It will be shown like this.
And I brought Path SVG Data in CheckBox at 'Material Design Icons'.
https://materialdesignicons.com/
<Style x:Key="_ListBoxItemStyleCheckBox" TargetType="ListBoxItem">
<Setter Property="OverridesDefaultStyle" Value="true" />
<Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<CheckBox Name="_Border" Margin="5,2" IsChecked="{TemplateBinding IsSelected}">
<CheckBox.Resources>
<Style TargetType="{x:Type CheckBox}">
<Setter Property="BorderBrush" Value="LightGray" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="BorderBrush" Value="Gray" />
</Trigger>
</Style.Triggers>
</Style>
</CheckBox.Resources>
<ContentPresenter />
</CheckBox>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Css helps you do this,for instance
ListBox tr.rowHover:hover
{
background-color: Yellow;
}
<asp ..... rowstyle-cssclass="rowHover" ...../>
I have a TreeView which simplified is defined as
<TreeView ItemsSource="{Binding TreeItems}">
<TreeView.Resources>
<DataTemplate DataType="{x:Type models:MyModel}">
<Border Margin="{Binding Margin}" >
<Grid>
<TextBlock Text="{Binding Path=Name}" Margin="3,3,3,3" />
</Grid>
</Border>
</DataTemplate>
</TreeView.Resources>
</TreeView>
It looks like this
As you can see due to the Margin, which is variable, there is space between the items. The problem is the dropdown arrow. It is not centered on the element. Well, it is centered on the element ignoring the margin. How do I adjust the arrow?
Your XAML markup is both incomplete and incorrect: the DataTemplate should be a HierarchicalDataTemplate and it should be placed in a <TreeView.ItemTemplate> tag. This doesn't apply after your edit.
You can apply the margin to the complete TreeViewItem content including the dropdown arrow:
<TreeView ItemsSource="{Binding Items}">
<TreeView.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<Setter Property="Margin" Value="{Binding Margin}"/>
</Style>
</TreeView.ItemContainerStyle>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding SubItems}">
<Border>
<Grid>
<TextBlock Margin="3,3,3,3"/>
</Grid>
</Border>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
Yes, I know the style below is too lengthy, but give it a try.
Just put it in a separate resource dictionary and merge it.
<TreeView ItemsSource="{Binding TreeItems}" ItemContainerStyle="{StaticResource CenteredExpanderTreeViewItemStyle}">
<TreeView.Resources>
<DataTemplate DataType="{x:Type models:MyModel}">
<Border Margin="{Binding Margin}" >
<Grid>
<TextBlock Text="{Binding Path=Name}" Margin="3,3,3,3" />
</Grid>
</Border>
</DataTemplate>
</TreeView.Resources>
</TreeView>
CenteredExpanderTreeViewItemStyle.xaml
<Style x:Key="TreeViewItemFocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Rectangle/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<SolidColorBrush x:Key="TreeViewItem.TreeArrow.Static.Checked.Fill" Color="#FF595959"/>
<SolidColorBrush x:Key="TreeViewItem.TreeArrow.Static.Checked.Stroke" Color="#FF262626"/>
<SolidColorBrush x:Key="TreeViewItem.TreeArrow.MouseOver.Stroke" Color="#FF27C7F7"/>
<SolidColorBrush x:Key="TreeViewItem.TreeArrow.MouseOver.Fill" Color="#FFCCEEFB"/>
<SolidColorBrush x:Key="TreeViewItem.TreeArrow.MouseOver.Checked.Stroke" Color="#FF1CC4F7"/>
<SolidColorBrush x:Key="TreeViewItem.TreeArrow.MouseOver.Checked.Fill" Color="#FF82DFFB"/>
<PathGeometry x:Key="TreeArrow" Figures="M0,0 L0,6 L6,0 z"/>
<SolidColorBrush x:Key="TreeViewItem.TreeArrow.Static.Fill" Color="#FFFFFFFF"/>
<SolidColorBrush x:Key="TreeViewItem.TreeArrow.Static.Stroke" Color="#FF818181"/>
<Style x:Key="ExpandCollapseToggleStyle" TargetType="{x:Type ToggleButton}">
<Setter Property="Focusable" Value="False"/>
<Setter Property="Width" Value="16"/>
<Setter Property="Height" Value="16"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border Background="Transparent" Height="16" Padding="5,5,5,5" Width="16">
<Path x:Name="ExpandPath" Data="{StaticResource TreeArrow}" Fill="{StaticResource TreeViewItem.TreeArrow.Static.Fill}" Stroke="{StaticResource TreeViewItem.TreeArrow.Static.Stroke}">
<Path.RenderTransform>
<RotateTransform Angle="135" CenterY="3" CenterX="3"/>
</Path.RenderTransform>
</Path>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="RenderTransform" TargetName="ExpandPath">
<Setter.Value>
<RotateTransform Angle="180" CenterY="3" CenterX="3"/>
</Setter.Value>
</Setter>
<Setter Property="Fill" TargetName="ExpandPath" Value="{StaticResource TreeViewItem.TreeArrow.Static.Checked.Fill}"/>
<Setter Property="Stroke" TargetName="ExpandPath" Value="{StaticResource TreeViewItem.TreeArrow.Static.Checked.Stroke}"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Stroke" TargetName="ExpandPath" Value="{StaticResource TreeViewItem.TreeArrow.MouseOver.Stroke}"/>
<Setter Property="Fill" TargetName="ExpandPath" Value="{StaticResource TreeViewItem.TreeArrow.MouseOver.Fill}"/>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="True"/>
<Condition Property="IsChecked" Value="True"/>
</MultiTrigger.Conditions>
<Setter Property="Stroke" TargetName="ExpandPath" Value="{StaticResource TreeViewItem.TreeArrow.MouseOver.Checked.Stroke}"/>
<Setter Property="Fill" TargetName="ExpandPath" Value="{StaticResource TreeViewItem.TreeArrow.MouseOver.Checked.Fill}"/>
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="CenteredExpanderTreeViewItemStyle" TargetType="{x:Type TreeViewItem}">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
<Setter Property="VerticalContentAlignment" Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
<Setter Property="Padding" Value="1,0,0,0"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="FocusVisualStyle" Value="{StaticResource TreeViewItemFocusVisual}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TreeViewItem}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth="19" Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<ToggleButton x:Name="Expander" VerticalAlignment="Center" ClickMode="Press" IsChecked="{Binding IsExpanded, RelativeSource={RelativeSource TemplatedParent}}" Style="{StaticResource ExpandCollapseToggleStyle}"/>
<Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Grid.Column="1" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
<ContentPresenter x:Name="PART_Header" ContentSource="Header" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
<ItemsPresenter x:Name="ItemsHost" Grid.ColumnSpan="2" Grid.Column="1" Grid.Row="1"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsExpanded" Value="false">
<Setter Property="Visibility" TargetName="ItemsHost" Value="Collapsed"/>
</Trigger>
<Trigger Property="HasItems" Value="false">
<Setter Property="Visibility" TargetName="Expander" Value="Hidden"/>
</Trigger>
<Trigger Property="IsSelected" Value="true">
<Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="true"/>
<Condition Property="IsSelectionActive" Value="false"/>
</MultiTrigger.Conditions>
<Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightBrushKey}}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.InactiveSelectionHighlightTextBrushKey}}"/>
</MultiTrigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="VirtualizingPanel.IsVirtualizing" Value="true">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<VirtualizingStackPanel/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
Use given style for TreeViewItem like give below
<Style TargetType="TreeViewItem" BasedOn="{StaticResource {x:Type TreeViewItem}}">
<Setter Property="Margin" Value="3,3,3,3"></Setter>
</Style>
Hope this help.
To add a margin to the ToggleButton in a TreeView, you have to add a custom ControlTemplate. There are several good tutorials on MSDN, for example here: https://msdn.microsoft.com/de-de/library/ms788727(v=vs.85).aspx
I stripped one example down to the necessary elements to match your requirements. Please note, that the ToggleButton is this example is not styled at all, so it appears a normal Button would do. But I am sure, you find several good examples on how to style this Button in a way that suites you the best.
The code:
<Window.Resources>
<Style x:Key="TreeViewItemStyle" TargetType="{x:Type TreeViewItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TreeViewItem}">
<Grid Margin="{Binding Margin}">
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth="20" Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<ToggleButton Grid.Column="0" x:Name="Expander" ClickMode="Press" IsChecked="{Binding IsExpanded, RelativeSource={RelativeSource TemplatedParent}}" />
<Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Grid.Row="0" Grid.Column="1" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
<ContentPresenter x:Name="PART_Header" ContentSource="Header" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
<ItemsPresenter x:Name="ItemsHost" Grid.ColumnSpan="2" Grid.Column="1" Grid.Row="1" Margin="-10,0,0,0"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsExpanded" Value="false">
<Setter Property="Visibility" TargetName="ItemsHost" Value="Collapsed"/>
</Trigger>
<Trigger Property="HasItems" Value="false">
<Setter Property="Visibility" TargetName="Expander" Value="Hidden"/>
</Trigger>
<Trigger Property="IsSelected" Value="true">
<Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}"/>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsSelected" Value="true"/>
<Condition Property="IsSelectionActive" Value="false"/>
</MultiTrigger.Conditions>
<Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
</MultiTrigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="VirtualizingStackPanel.IsVirtualizing" Value="true">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<VirtualizingStackPanel/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<TreeView ItemsSource="{Binding TreeItems}" ItemContainerStyle="{StaticResource TreeViewItemStyle}">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type library:MyModel}" ItemsSource="{Binding Children}" >
<TextBlock Text="{Binding Name}"></TextBlock>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
You should be able to do just this:
<Style TargetType="{x:Type TreeViewItem}" BasedOn="{StaticResource {x:Type TreeViewItem}}">
<Setter Property="Margin" Value="0,0,0,0" />
<!--Or edit Padding if Margin doesn't work-->
</Style>
It will use default style of a TreeViewItem and edit only defined properties. If you use explicitly defined style for TreeViewItem, use BaseOn="{StaticResource [YourStyleKey]}" (without [ ]).
If you need some more advanced styling I'd suggest you to use Blend to get the ControlTemplate of a TreeViewItem, then just edit it to your needs, without changing too much (keep in mind that names of controls used as a template may have a crucial meaning, so be careful what you are editing).
If you don't know how to use Blend to get your control's template, here is a simple tutorial described in a documentation of Telerik controls (don't worry, it works the same for all controls). You just need to create copy of a TreeViewItem ControlTemplate, paste it to your application and you are good to go (editing).
By using Blend you can get templates of all building blocks of a TreeView control and make them look like you want them to. You just need to do some digging.
I am overriding DataGrid row header style, and I’m been hindered with the following two issues:
1.The DataGrid row header contains an Image and a ToggleButton. When the ToggleButton is ‘Checked’ I want to change the background color of the whole row, however I only managed to change the background of the row header and couldn’t figure out a way to fire a trigger on the row level.
2.When a row is selected the row and the header background is set to different background, the other way around does not work. What I need to do is to change the background of the row when the row header is selected
Here is a the style code of the DataGridRowHeader
<Style x:Key="{x:Type DataGridRowHeader}" TargetType="{x:Type DataGridRowHeader}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridRowHeader}">
<Grid>
<Border Name="RowHeaderBorder"
BorderThickness="0,0,3,0"
Margin="0,0,0,0"
BorderBrush="{StaticResource DataGridRowBorder}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Source="{Binding ImageSource}" RenderOptions.BitmapScalingMode="HighQuality" Stretch="None" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<ToggleButton x:Name="tglButton" Visibility="{Binding ActiveCall}" Grid.Column="1" Content="Button" Focusable="True" BorderThickness="1" Width="80" Height="33" VerticalAlignment="Top" >
</ToggleButton>
</Grid>
</Border>
</Grid>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding ElementName=tglButton, Path=IsChecked}" Value="true">
<Setter Property="Background" TargetName="RowHeaderBorder" Value ="Green"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And here is the style of the DataGridRow:
<Style x:Key="DataGridRowStyle" TargetType="{x:Type DataGridRow}">
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="BorderBrush" Value="{StaticResource DataGridRowBorder}"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Background" Value="{StaticResource DataGridRowHoveredBackground}" />
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Effect">
<Setter.Value>
<DropShadowEffect ShadowDepth="0" BlurRadius="20"/>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsSelected" Value="true">
<Setter Property="Foreground" Value="Black"/>
<Setter Property="Background" Value="{StaticResource RowBackgroundSelectedBrush2}" />
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Effect">
<Setter.Value>
<DropShadowEffect ShadowDepth="0" BlurRadius="20"/>
</Setter.Value>
</Setter>
</Trigger>
<DataTrigger Binding="{Binding ElementName=DataGridRowHeader.tglButton, Path=IsChecked}" Value="true">
<Setter Property="Background" Value ="Green"/>
</DataTrigger>
</Style.Triggers>
</Style>
This is because tglButton is present in the row header, which is a child of the DataGridRow. A trigger defined in child row header is trying to update a property of the parent (DataGridRow) and is not able to find it.
One solution for this is to define the template for DataGridRowHeader inside the template for DataGridRow and supply a name for it, which can be used in the trigger. A very crude example:
<Style
TargetType="{x:Type DataGridRow}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridRow}">
<Border x:Name="DGR_Border"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}"
SnapsToDevicePixels="True"
CornerRadius="8,8,8,8">
<SelectiveScrollingGrid>
<SelectiveScrollingGrid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</SelectiveScrollingGrid.ColumnDefinitions>
<SelectiveScrollingGrid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</SelectiveScrollingGrid.RowDefinitions>
<DataGridCellsPresenter Grid.Column="1"
ItemsPanel="{TemplateBinding ItemsPanel}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
<DataGridDetailsPresenter Grid.Column="1"
Grid.Row="1"
SelectiveScrollingGrid.SelectiveScrollingOrientation="{Binding AreRowDetailsFrozen,
ConverterParameter={x:Static SelectiveScrollingOrientation.Vertical},
Converter={x:Static DataGrid.RowDetailsScrollingConverter},
RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"
Visibility="{TemplateBinding DetailsVisibility}" />
<DataGridRowHeader Name="RHeader" Grid.RowSpan="2"
SelectiveScrollingGrid.SelectiveScrollingOrientation="Vertical"
Visibility="{Binding HeadersVisibility,
ConverterParameter={x:Static DataGridHeadersVisibility.Row},
Converter={x:Static DataGrid.HeadersVisibilityConverter},
RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ToggleButton x:Name="tglButton"
Grid.Column="1"
Content="Button"
Focusable="True"
BorderThickness="1"
Width="80"
Height="33"
VerticalAlignment="Top">
</ToggleButton>
</Grid>
</DataGridRowHeader>
</SelectiveScrollingGrid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected"
Value="True">
<Setter TargetName="DGR_Border"
Property="Background"
Value="Gray" />
</Trigger>
<DataTrigger Binding="{Binding ElementName=tglButton, Path=IsChecked}"
Value="true">
<Setter Property="Background"
TargetName="RHeader"
Value="Green" />
<Setter Property="Background"
Value="Green" />
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="DataContext"
Value="{Binding RelativeSource={RelativeSource Self}}" />
<Setter Property="BorderThickness"
Value="1" />
<Setter Property="BorderBrush"
Value="Aqua" />
<Style.Triggers>
<Trigger Property="IsSelected"
Value="true">
<Setter Property="Foreground"
Value="Black" />
<Setter Property="Background"
Value="Pink" />
<Setter Property="FontWeight"
Value="Bold" />
<Setter Property="Effect">
<Setter.Value>
<DropShadowEffect ShadowDepth="0"
BlurRadius="20" />
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
I have the following code which supposed to display a TreeView (the original code is more complicated, thus the complex control hirerchy):
<TreeView ItemsSource="{Binding TreeRoot}"
HorizontalAlignment="Left">
<TreeView.Resources>
<DataTemplate x:Key="CTemplate">
<Border >
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<ToggleButton
Grid.Column="1"
x:Name="Expander"
HorizontalAlignment="Right"
ClickMode="Press"/>
<TextBlock Text="{Binding Name}"
Grid.Column="0" />
</Grid>
</Border>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Path=HasItems, RelativeSource={RelativeSource AncestorType={x:Type TreeViewItem}}}" Value="False">
<Setter TargetName="Expander" Property="Visibility" Value="Hidden"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
<Style TargetType="{x:Type TreeViewItem}" x:Key="aaa">
<Setter Property="ItemsSource" Value="{Binding Children}"/>
<Setter Property="IsExpanded" Value="{Binding Path=IsExpanded,Mode=TwoWay}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TreeViewItem}">
<StackPanel>
<Border Name="Bd"
Background="{TemplateBinding Background}">
</Border>
<ItemsPresenter x:Name="ItemsP" />
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsExpanded" Value="false">
<Setter TargetName="ItemsP"
Property="Visibility"
Value="Collapsed"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type TreeView}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TreeView}">
<Border BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<DockPanel>
<ItemsPresenter/>
</DockPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="ItemContainerStyle" Value="{StaticResource aaa}" />
<Setter Property="ItemTemplate" Value="{CTemplate}" />
</Style>
</TreeView.Resources>
</TreeView>
Could you please help me figure out why my items are not displayed?
(The page appears empty)
Thanks,
Li
You don't have anything showing the Header of the TreeViewItem:
<Style TargetType="{x:Type TreeViewItem}" x:Key="aaa">
...
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TreeViewItem}">
<StackPanel>
<Border Name="Bd" Background="{TemplateBinding Background}">
<ContentPresenter x:Name="PART_Header"
ContentSource="Header"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
<ItemsPresenter x:Name="ItemsP" />
</StackPanel>
...
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Above I added the ContentPresenter.