Replace part of default template in WPF - c#

is there any "best practice" way to replace a part of the default template. The current use case is a treeview. As default, the treeview has this small triangle shapes to expand and collapse.
I know how to replace these if I replace the whole control template, as shown in the code below. I am not sure if there is a way to "keep all default, just change XY". Its not a style, I basically need to replace a part of an existing control template.
To illustrate, take a look at the following XAML. The first smaller block is the relevant XAML I want to be able to adapt.
The bigger second and third part are basically a copy of the default templates, only to administer the "changed" part from the beginning.
Is there a better way to do this, saving the long and confusing XAML in the second half?
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<Style x:Key="ExpandCollapseToggleStyle" TargetType="ToggleButton">
<Setter Property="Focusable" Value="False"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Grid
Width="15"
Height="13"
Background="Transparent">
<Path x:Name="ExpandPath"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Margin="1,1,1,1"
Fill="Black"
Data="M 4 0 L 8 4 L 4 8 Z"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked"
Value="True">
<Setter Property="Data"
TargetName="ExpandPath"
Value="M 0 4 L 8 4 L 4 8 Z"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<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"
Style="{StaticResource ExpandCollapseToggleStyle}"
IsChecked="{Binding Path=IsExpanded,
RelativeSource={RelativeSource TemplatedParent}}"
ClickMode="Press"/>
<Border Name="Bd"
Grid.Column="1"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}">
<ContentPresenter x:Name="PART_Header"
ContentSource="Header"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/>
</Border>
<ItemsPresenter x:Name="ItemsHost"
Grid.Row="1"
Grid.Column="1"
Grid.ColumnSpan="2"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsExpanded"
Value="false">
<Setter TargetName="ItemsHost"
Property="Visibility"
Value="Collapsed"/>
</Trigger>
<Trigger Property="HasItems"
Value="false">
<Setter TargetName="Expander"
Property="Visibility"
Value="Hidden"/>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="HasHeader"
Value="false"/>
<Condition Property="Width"
Value="Auto"/>
</MultiTrigger.Conditions>
<Setter TargetName="PART_Header"
Property="MinWidth"
Value="75"/>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="HasHeader"
Value="false"/>
<Condition Property="Height"
Value="Auto"/>
</MultiTrigger.Conditions>
<Setter TargetName="PART_Header"
Property="MinHeight"
Value="19"/>
</MultiTrigger>
<Trigger Property="IsSelected"
Value="true">
<Setter TargetName="Bd"
Property="Background"
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 TargetName="Bd"
Property="Background"
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>

Unfortunately, I think you have to replace the entire template:
From MSDN: http://msdn.microsoft.com/en-us/library/aa970773.aspx
Controls in Windows Presentation
Foundation (WPF) have a
ControlTemplate that contains the
visual tree of that control. You can
change the structure and appearance of
a control by modifying the
ControlTemplate of that control. There
is no way to replace only part of the
visual tree of a control; to change
the visual tree of a control you must
set the Template property of the
control to its new and complete
ControlTemplate.

Actually there is a way (sort of). You can create your own custom control and override the OnApplyTemplate function to change the style dynamically.
For example, create a custom control like so (I am doing this in silverlight but it's all the same I presume):
namespace SilverlightClassLibrary1
{
public class MyButton: Button
{
public string BackgroundColor { get; set; }
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
if (BackgroundColor != null)
{
Rectangle r = this.GetTemplateChild("BackgroundGradient") as Rectangle;
if (r != null)
{
r.Fill = new SolidColorBrush(Color.FromArgb(255,
Convert.ToByte(BackgroundColor.Substring(1,2),16),
Convert.ToByte(BackgroundColor.Substring(3,2),16),
Convert.ToByte(BackgroundColor.Substring(5,2),16)));
}
}
}
}
}
The interesting part is the GetTemplateChild method, that's looking for a Rectangle control named "BackgroundGradient". (BTW, it's easier if you define custom controls in a separate project, so create a new "Silverlight class library" project if you haven't already done so and put it into that project.)
Then add a new resource dictionary file and override the control template and make sure you have a rectangle named "BackgroundGradient". In this case we're using the standard button control template that I've cut down a bit:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:custom="clr-namespace:SilverlightClassLibrary1;assembly=SilverlightClassLibrary1">
<Style TargetType="custom:MyButton">
<Setter Property="Background" Value="#FF1F3B53"/>
<Setter Property="Foreground" Value="#FF000000"/>
<Setter Property="Padding" Value="3"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="BorderBrush">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFA3AEB9" Offset="0"/>
<GradientStop Color="#FF8399A9" Offset="0.375"/>
<GradientStop Color="#FF718597" Offset="0.375"/>
<GradientStop Color="#FF617584" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<Border x:Name="Background" CornerRadius="3" Background="White" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}">
<Grid Background="{TemplateBinding Background}" Margin="1">
<Border Opacity="0" x:Name="BackgroundAnimation" Background="#FF448DCA" />
<Rectangle x:Name="BackgroundGradient" Fill="White" >
</Rectangle>
</Grid>
</Border>
<ContentPresenter
x:Name="contentPresenter"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Margin="{TemplateBinding Padding}"/>
<Rectangle x:Name="DisabledVisualElement" RadiusX="3" RadiusY="3" Fill="#FFFFFFFF" Opacity="0" IsHitTestVisible="false" />
<Rectangle x:Name="FocusVisualElement" RadiusX="2" RadiusY="2" Margin="1" Stroke="#FF6DBDD1" StrokeThickness="1" Opacity="0" IsHitTestVisible="false" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
So you can now declare a button control and override a style if you'd like:
<UserControl x:Class="SilverlightApplication1.MainPage"
...
xmlns:custom="clr-namespace:SilverlightClassLibrary1;assembly=SilverlightClassLibrary1">
<custom:MyButton>Normal Button 1</custom:MyButton>
<custom:MyButton>Normal Button 2</custom:MyButton>
<custom:MyButton BackgroundColor="#8888cc">Customized Background</custom:MyButton>
I presume you could get get even more clever and pass through a resource name or a style name and load it dynamically.
You then need to include your resource file as part of your application:
<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SilverlightApplication1.App"
>
<Application.Resources>
<ResourceDictionary >
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Dictionary1.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
and you'll see your custom property changes in your XAML designer.

I would redesign your template to be a Custom Control, using ContentPresenters as placeholders for the elements that will change.
To use these placeholders you must link them to dependency properties.
Check this post to see how this is done
http://www.codeproject.com/Articles/82464/How-to-Embed-Arbitrary-Content-in-a-WPF-Control
"Using Custom Control" explains my approach

2020 Update
I came across this question on my search for an answer and this is how I did it:
To override the default control templates: use Microsoft Blend > Via the Designer right click on the control you wish to override > Edit Template > Edit Current or Edit a Copy (If you're using the same control multiple times like in my case a Menu Item) save the template in a Resource Dictionary and use it as a Dynamic Resource on the controls you wish to override. and of course, edit the template the way you want.

Related

Change BorderBrush when button IsPressed

I'm creating a WPF application for a touchscreen.
There should be a button on the screen with an Icon (image).
The code below shows how the button should look like.
So far so good..
What I would like to achieve is that when you press the button, the first BorderBrush color should change from “#0070b8” to “#00395c” and the second BorderBrush color should change from “#e3e3e3” to “#727272”.
Could someone please help me how to achieve this?
<Button Width="64" Height="64" Grid.Row="1" Margin="1,1" HorizontalAlignment="Left" VerticalAlignment="Top">
<Image Source="Resources\Home_Icon_2.bmp" Width="54" Height="54"></Image>
<Button.Style>
<Style TargetType="{x:Type Button}" >
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ButtonBase}">
<Border CornerRadius="6" Background="{TemplateBinding Background}" Name="button" Width="64">
<Grid>
<Border BorderThickness="0,0,2,2" BorderBrush="#0070b8" CornerRadius="{Binding ElementName=button, Path=CornerRadius}">
<Border.Effect>
<BlurEffect Radius="1" KernelType="Gaussian"/>
</Border.Effect>
</Border>
<Border BorderThickness="2,2,0,0" BorderBrush="#e3e3e3" Opacity="0.5" CornerRadius="{Binding ElementName=button, Path=CornerRadius}">
<Border.Effect>
<BlurEffect Radius="1" KernelType="Gaussian"/>
</Border.Effect>
</Border>
<ContentPresenter TextBlock.FontSize="{TemplateBinding FontSize}" TextBlock.FontFamily="{TemplateBinding FontFamily}" TextBlock.Foreground="{TemplateBinding Foreground}" VerticalAlignment="Center" HorizontalAlignment="Center" Content="{TemplateBinding Content}"></ContentPresenter>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="button" Property="Background" Value="#e3e3e3" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Background" Value="#c6c3c6" />
</Style>
</Button.Style>
</Button>
You could always set the brush color in your click event:
private void btnYourButton_Click(object sender, RoutedEventArgs e)
{
btnYourButton.BorderBrush = (Brush)new BrushConverter().ConvertFrom("#00395c");
}
This would be one solution. Note that we've assigned our brushes to separate resources so that we don't have magic numbers in our style. This is ideal for when you need to use the same colour scheme across multiple controls, and saves a lot of time when you want to change said colour scheme.
<Style x:Key="AdtakrButton" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border Name="ButtonBorder" CornerRadius="5" BorderThickness="{DynamicResource AdtakrButtonBorderThickness}" BorderBrush="{DynamicResource AdtakrBlack}" Background="{DynamicResource AdtakrWhite}" Margin="{DynamicResource ButtonMargin}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" Margin="6,0,6,0" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Foreground" Value="{DynamicResource AdtakrGrey2}"/>
<Setter Property="BorderBrush" Value="{DynamicResource AdtakrGrey2}" TargetName="ButtonBorder"/>
<Setter Property="Background" Value="{DynamicResource AdtakrGrey1}" TargetName="ButtonBorder"/>
<Setter Property="Visibility" Value="Collapsed"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{DynamicResource AdtakrGrey2}" TargetName="ButtonBorder"/>
<Setter Property="BorderBrush" Value="{DynamicResource AdtakrGrey2}" TargetName="ButtonBorder"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" Value="{DynamicResource AdtakrLightBlue}" TargetName="ButtonBorder"/>
<Setter Property="BorderBrush" Value="{DynamicResource AdtakrLightBlue}" TargetName="ButtonBorder"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="FontSize" Value="{DynamicResource AdtakrDefFontSize}"/>
<Setter Property="MinWidth" Value="90"/>
<Setter Property="Height" Value="40"/>
<Setter Property="ToolTipService.ShowOnDisabled" Value="True"/>
</Style>
If you need to have it change between more than 1 colour, then your best bet is to have a command on your databound VM and the command changes a colour property that the button also binds to. Alternatively, if it's supposed to reflect 3 states, using a toggle button with the three state option is probably your better bet, as then you can set triggers against the IsChecked property of the button.
Found the solution!
By giving the borders a name and then they are accessible in the Trigger Property
<Button Width="64" Height="64" Grid.Row="1" HorizontalAlignment="Left" VerticalAlignment="Top">
<Image Source="Images\Home_Icon_2.png" Width="54" Height="54"></Image>
<Button.Style>
<Style TargetType="{x:Type Button}" >
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ButtonBase}">
<Border x:Name="button" CornerRadius="6" Background="{TemplateBinding Background}" Width="64">
<Grid>
<Border x:Name="border1" BorderThickness="0,0,2,2" BorderBrush="#0070b8" CornerRadius="{Binding ElementName=button, Path=CornerRadius}">
<Border.Effect>
<BlurEffect Radius="1" KernelType="Gaussian"/>
</Border.Effect>
</Border>
<Border x:Name="border2" BorderThickness="2,2,0,0" BorderBrush="#e3e3e3" Opacity="0.5" CornerRadius="{Binding ElementName=button, Path=CornerRadius}">
<Border.Effect>
<BlurEffect Radius="1" KernelType="Gaussian"/>
</Border.Effect>
</Border>
<ContentPresenter TextBlock.FontSize="{TemplateBinding FontSize}" TextBlock.FontFamily="{TemplateBinding FontFamily}" TextBlock.Foreground="{TemplateBinding Foreground}" VerticalAlignment="Center" HorizontalAlignment="Center" Content="{TemplateBinding Content}"></ContentPresenter>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="button" Property="Background" Value="#e3e3e3" />
<Setter TargetName="border1" Property="BorderBrush" Value="#00395c" />
<Setter TargetName="border2" Property="BorderBrush" Value="#727272" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Background" Value="#c6c3c6" />
</Style>
</Button.Style>
</Button>

C# WPF Dynamic Button STYLE that has different pictures based on the x:name or x:key they have

I would like to make a game like Shakes & Fidgets. I got stuck at the Main menu, where I already overcomplicated stuff as I always do. I made a grid layout, where I will put the buttons, but every button is a picture. I use ImageBrush for every button's picture I want to create.
I would like to create ONE style for every button so they change their backgrounds based on the x:Name or x:Key they have. So a Button with x:Name or x:Key "PlayGame" would find it's as the PlayGame.png, PlayGame_Hover, PlayGame_OnClick where "PlayGame" is a variable.
In other words I would like to have a style that can filter the x:name, or x:key of a button, and uses it as a variable later on so I can do this: {StaticResource VARIABLENAME}
The Code I have now is:
<ImageBrush x:Key="PlayGame">
<ImageBrush.ImageSource>
<BitmapImage UriSource="./Pictures/PlayGameButton.png"/>
</ImageBrush.ImageSource>
</ImageBrush>
<ImageBrush x:Key="PlayGame_Hover">
<ImageBrush.ImageSource>
<BitmapImage UriSource="./Pictures/PlayGameButton_Hover.png"/>
</ImageBrush.ImageSource>
</ImageBrush>
<ImageBrush x:Key="PlayGame_OnClick">
<ImageBrush.ImageSource>
<BitmapImage UriSource="./Pictures/PlayGameButton_OnClick.png"/>
</ImageBrush.ImageSource>
</ImageBrush>
<Style TargetType="{x:Type Button}">
<Setter Property="Background" Value="{StaticResource PlayGame}" />
<Setter Property="FontSize" Value="15" />
<Setter Property="SnapsToDevicePixels" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border CornerRadius="4" Background="{TemplateBinding Background}">
<Grid>
<ContentPresenter x:Name="MyContentPresenter" Content="{TemplateBinding Content}" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,0,0,0" />
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{StaticResource PlayGame_Hover}" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" Value="{StaticResource PlayGame_OnClick}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I found a not very effective solution, but not the one I actually want
You can give the Style an
x:Key="styleKey"
and you have to give the button this part:
Style="{StaticResource styleKey}"
This way you will have to make a style for every different button you want to have, but it will work, and you will be happy about it if efficency is not key.:D

Change the size of CheckBox's CheckMark WPF

I have implemented this style for my CheckBox:
<Style x:Key="{x:Type CheckBox}" TargetType="CheckBox">
<Setter Property="SnapsToDevicePixels" Value="true"/>
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="FontFamily" Value="{DynamicResource MetroFontRegular}"/>
<Setter Property="FocusVisualStyle" Value="{StaticResource CheckBoxFocusVisual}"/>
<Setter Property="Foreground" Value="#999999"/>
<Setter Property="Background" Value="#3f3f3f"/>
<Setter Property="FontSize" Value="12"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="CheckBox">
<BulletDecorator Background="Transparent">
<BulletDecorator.Bullet>
<Border x:Name="Border"
Width="13"
Height="13"
CornerRadius="6,6,6,6"
Background="#ffffff"
BorderBrush="#999999"
BorderThickness="1" >
<Image x:Name="CheckMark" Source="Images/CheckMark.png" Width="15" Height="15" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</BulletDecorator.Bullet>
<ContentPresenter Margin="8,0,0,0" VerticalAlignment="Center" HorizontalAlignment="Left" RecognizesAccessKey="True"/>
</BulletDecorator>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="false">
<Setter TargetName="CheckMark" Property="Visibility" Value="Collapsed"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="true">
<Setter TargetName="Border" Property="Background" Value="#91814E" />
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="#c1c1c1"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
So now my checkbox looks like a circle and it's checkmark is actually an image named "CheckMark". So I'm pleased with it's look but what i would like to manage is to make my checkmark little bit bigger than my checkbox. For example something like this:
I tried to change the size of my image but when I change it it only get changed inside of checkbox. It does't get outside of it's border. How can I manage this?
If your Border element is constraining the size of the Image that is declared inside it, you can simply move the Image outside of the Border and increase it's size:
<Border x:Name="Border"
Width="13"
Height="13"
CornerRadius="6,6,6,6"
Background="#ffffff"
BorderBrush="#999999"
BorderThickness="1" >
</Border>
<Image x:Name="CheckMark" Source="Images/CheckMark.png" Width="30" Height="30"
HorizontalAlignment="Center" VerticalAlignment="Center"/>
based on assumptions this should work
<Border x:Name="Border"
Width="13"
Height="13"
CornerRadius="6,6,6,6"
Background="#ffffff"
BorderBrush="#999999"
BorderThickness="1">
<Canvas>
<Image x:Name="CheckMark"
Canvas.Bottom="0"
Width="20"
Height="20"
Source="Images/CheckMark.png"/>
</Canvas>
</Border>
I have placed a canvas as the content of the Border and placed the check mark within it and aligned the bottom of check image to its bottom. since a Canvas does not clip its content by default this would result in overflow and since we have set a larger size it would give us the desired effect.

Disable Control's Selection Background Effect in WPF

I have a ListView which shows a collection of objects. I want to disable the "Blue effect" or "Blue rectangle" when clicking on the ListViewItem, and Let only the object in this Item enabled. Does anyone has an idea about that ??
Here is an Example of one of my ListViewItems:
Here is my listView:
<ListView SelectionMode="Single" IsManipulationEnabled="True" HorizontalAlignment="Left" HorizontalContentAlignment="Stretch" VerticalAlignment="Stretch" ScrollViewer.VerticalScrollBarVisibility="Auto" ItemsSource="{Binding ChildrenList}" Background="Transparent" BorderBrush="Transparent" >
<ListView.LayoutTransform>
<RotateTransform Angle="{Binding IsVertical, Converter={StaticResource AngleOfBool}}"></RotateTransform>
</ListView.LayoutTransform>
<ListView.ItemTemplate>
<DataTemplate>
<Grid HorizontalAlignment="Stretch" Background="Transparent" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<CheckBox Content="{Binding Id}" Height="auto" Name="Flag" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Column="0" IsChecked="{Binding IsVisible}"/>
<Grid Grid.Column="1">
<area:Area HorizontalAlignment="Stretch" Visibility="{Binding IsVisible, Converter={StaticResource VisibilityOfBool}}" />
</Grid>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Setting the IsEnabled property of a parent control to False will automatically set the IsEnabled property of every child control to False as well. The only way around this is to set the IsEnabled property of the individual controls that you want to be disabled to False, instead of that of the parent control.
However, you can create one bool property to Bind to the IsEnabled property of all of the relevant controls so that at least, you can disable and enable them all using the one property:
<Grid Name="Parent">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="auto"></ColumnDefinition>
<ColumnDefinition Width="auto"></ColumnDefinition>
</Grid.ColumnDefinitions>
<ContentControl IsEnabled="AreInnerControlsEnabled" Grid.Column="0" Content="{Binding}" Visibility="{Binding IsVisible, Converter= {StaticResource VisibilityOfBool} }"></ContentControl>
<Grid Grid.Column="1" Visibility="{Binding IsVisible, Converter= {StaticResource VisibilityOfBool} }" HorizontalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="0.5*"></RowDefinition>
<RowDefinition Height="0.5*"></RowDefinition>
</Grid.RowDefinitions>
<Label IsEnabled="AreInnerControlsEnabled" Grid.Row="0" Background="Transparent" Content="{Binding Top}" VerticalAlignment="Top" HorizontalAlignment="Stretch"></Label>
<Label Grid.Row="1" Background="Transparent" Content="{Binding Bottom}" VerticalAlignment="Bottom" HorizontalAlignment="Stretch"></Label>
</Grid>
</Grid>
Using this method, only the controls using the AreInnerControlsEnabled property will be affected.
UPDATE >>>
So it turns out that you actually want to remove the default selection colour of the ListView... that is very different to what you 'appeared' to be asking. However, now I know that, you can achieve that very easily by using a simple Style:
<Style x:Key="HiddenDefaultSelectionStyle" TargetType="{x:Type ListViewItem
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent" />
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Transparent
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="Black" />
<SolidColorBrush x:Key="{x:Static SystemColors.ControlTextBrushKey}" Color="Black" />
</Style.Resources>
</Style>
You only need one of these to hide that colour, but I have shown you the rest for future reference. You can use it like this:
<ListView ItemContainerStyle="{StaticResource HiddenDefaultSelectionStyle}" ... />
As I stated at the comments, I would change the ListViewItem template.
The code is very verbose, so let's do it:
First, create a ResourceDictionary and set a reference to it in you App.xaml.
Having done that, paste the code below at the ResourceDictionary:
<SolidColorBrush x:Key="Item.MouseOver.Background" Color="#1F26A0DA"/>
<SolidColorBrush x:Key="Item.MouseOver.Border" Color="#a826A0Da"/>
<SolidColorBrush x:Key="Item.SelectedInactive.Background" Color="#3DDADADA"/>
<SolidColorBrush x:Key="Item.SelectedInactive.Border" Color="#FFDADADA"/>
<SolidColorBrush x:Key="Item.SelectedActive.Background" Color="#3D26A0DA"/>
<SolidColorBrush x:Key="Item.SelectedActive.Border" Color="#FF26A0DA"/>
<Style x:Key="ListViewItemStyle1" TargetType="{x:Type ListViewItem}">
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="Padding" Value="4,1"/>
<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="Background" Value="Transparent"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="FocusVisualStyle" Value="{StaticResource FocusVisual}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="True"/>
</MultiTrigger.Conditions>
<Setter Property="Background" TargetName="Bd" Value="{StaticResource Item.MouseOver.Background}"/>
<Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource Item.MouseOver.Border}"/>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Selector.IsSelectionActive" Value="False"/>
<Condition Property="IsSelected" Value="True"/>
</MultiTrigger.Conditions>
<Setter Property="Background" TargetName="Bd" Value="{StaticResource Item.SelectedInactive.Background}"/>
<Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource Item.SelectedInactive.Border}"/>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="Selector.IsSelectionActive" Value="True"/>
<Condition Property="IsSelected" Value="True"/>
</MultiTrigger.Conditions>
<Setter Property="Background" TargetName="Bd" Value="{StaticResource Item.SelectedActive.Background}"/>
<Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource Item.SelectedActive.Border}"/>
</MultiTrigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="TextElement.Foreground" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Notice that the first 6 tags (SolidColorBrush) have the references to the colors according to the state of the ListViewItem.
From here, you can take 2 paths, change the SolidColorBrush Color to whatever you want to, in your case Transparent OR remove the Triggers altogether (not recommended).
When you're done, set the Style property of your ListBoxItem to the x:Key you named. In the code the name is x:Key="ListViewItemStyle1".
I hope that this guide you!

WPF Tree view, how to change indention

My Treeview basically has "folder" nodes, and one level below items which do NOT contain other items.
Therefor the space for the expand / collapse icons is not required (on level 2). Can I give up this icon space and hence reduce the indention. The items (in the example "airports") shall be shifted some pixels to the left.
Important: Basically looking for the code solution (C#), not the XAML version.
Really what you want to do is edit the HierarchicalDataTemplate and change the way it behaves. The following page, has a pretty good high level view of editing the Hierarchical Data Template.
I have also found this one to be pretty good to start out with. While neither of the pages specifically say what to do, you are essentially changing the layout properties in the items presenter.
Edit
Whoops, I was incorrect. Not HierarchicalDataTemplate, but TreeViewItem template.
See below for an example. This is just the simplest way to do it if you KNOW that there are not going to be any third level nodes.
Pay special attention to the ItemsPresenter element named ItemsHost. It has a margin of -12,0,0,0. That means that its left margin is negative and thus spills out of the grid column containing it in the left direction. Thus all of the child nodes will be pulled to the left a little. If you have third level nodes in the future, they also will be pulled to the left. If you don't want that, then you will have to supply different templates for different levels of nodes. But that is outside the scope of this answer.
<Style x:Key="TreeViewItemStyle1" TargetType="{x:Type TreeViewItem}">
<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" 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" Margin="-12,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>

Categories