Change property of "super/base" style wpf - wpf

I am creating a base style. I am using inheritance to implement my base style. I know how to add properties on my derived class but I don't know how to just change a property. Let me give you an example:
let say I have this base style:
<!-- SrollViewer ScrollBar Repeat Buttons (at each end) -->
<Style x:Key="ScrollBarLineButton" TargetType="{x:Type RepeatButton}">
<Setter Property="SnapsToDevicePixels" Value="True"/>
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="Focusable" Value="false"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RepeatButton}">
<Border
Name="Border"
Margin="1"
CornerRadius="2"
Background="WhiteSmoke"
BorderThickness="1">
<Image Stretch="Uniform" Source="/FilesPro;component/Images/scrollArrow.png" Height="40" VerticalAlignment="Center" HorizontalAlignment="Center" Width="52" >
<Image.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleY="-1" />
<TranslateTransform Y="40"/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</Image.RenderTransform>
</Image>
<!--
<Path
HorizontalAlignment="Center"
VerticalAlignment="Center"
Fill="{StaticResource GlyphBrush}"
Data="{Binding Path=Content,
RelativeSource={RelativeSource TemplatedParent}}" >
</Path>
-->
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I would like to create a new style that has the same properties as ScrollBarLineButton but with the image transfrom scaleY=1 instead of -1.
when I do:
<Style x:Key="ScrollBarLineButtonVerticalUp" BasedOn="{StaticResource ScrollBarLineButton}" TargetType="{x:Type RepeatButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RepeatButton}">
<Border>
<Image Stretch="Uniform" Source="/FilesPro;component/Images/scrollArrow.png" Height="40" VerticalAlignment="Center" HorizontalAlignment="Center" Width="52" >
<Image.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleY="1" />
....
...
border no longer has its base style margin, Background color etc.. How could I inherit from the style and just change one property. I know I can copy paste but I will change this a lot and it is convenient that if I change it in one place it changes in all the other places.

You can create a DynamicResource reference to do something like this, here's an example:
<StackPanel>
<StackPanel.Resources>
<Style x:Key="ButtonStyleA" TargetType="{x:Type Button}">
<Style.Resources>
<SolidColorBrush x:Key="TextBrush" Color="Yellow" />
</Style.Resources>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border CornerRadius="10" BorderThickness="1" BorderBrush="Red">
<ContentPresenter TextElement.Foreground="{DynamicResource TextBrush}"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ButtonStyleB" TargetType="{x:Type Button}" BasedOn="{StaticResource ButtonStyleA}">
<Style.Resources>
<SolidColorBrush x:Key="TextBrush" Color="Blue" />
</Style.Resources>
</Style>
</StackPanel.Resources>
<Button Style="{StaticResource ButtonStyleA}" Content="Lorem Ipsum" />
<Button Style="{StaticResource ButtonStyleB}" Content="Lorem Ipsum" />
</StackPanel>
In StyleB the TextBrush is overridden which causes the template to change as well since it references this resource.

Related

Change the image of the radio button after checked

<StackPanel Name="StpAddDel" Orientation="Horizontal" HorizontalAlignment="Right" Margin="5">
<RadioButton Name="rdbactive" GroupName="actinact" VerticalAlignment="Center" Margin="5,0" Width="50" Height="15" Foreground="Blue">
<RadioButton.Style>
<Style TargetType="{x:Type RadioButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RadioButton}">
<Grid>
<Image Source="c:\image.png" Width="32" Height="32"/>
<ContentPresenter/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</RadioButton.Style>
</RadioButton>
<RadioButton Name="rdbinactive" GroupName="actinact" VerticalAlignment="Center" Margin="5,0" Width="60" Height="15" Foreground="Blue">
<RadioButton.Style>
<Style TargetType="{x:Type RadioButton}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RadioButton}">
<Grid>
<Image Source="c:\image.png" Width="32" Height="32"/>
<ContentPresenter/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</RadioButton.Style>
</RadioButton>
<Button Name="BtnAdd" Height="20" Width="20" Margin="5,0" Template="{StaticResource AddImgBtnTemplate}" />
<Button Name="BtnDel" Height="20" Width="20" Margin="5,0" Template="{StaticResource DelImgBtnTemplate}" />
</StackPanel>
In the above code i have 2 radio button i put images on radio buttons , My requirement is i want to change the image of the radio button after it is checked, Please help me with this......
You can use ControlTemplate.Triggers for that
<ControlTemplate TargetType="{x:Type RadioButton}">
<Grid>
<Image x:Name="PART_Image" Source="c:\image.png" Width="32" Height="32"/>
<ContentPresenter/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="PART_Image" Property="Source" Value="new source"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
Give Image some name and change Source property of that control when IsChecked is true
EDIT
If you want to also "highlight" when mouse is over then you can add for example DropShadowEffect with another Trigger, this time when IsMouseOver is true
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="PART_Image" Property="Effect">
<Setter.Value>
<DropShadowEffect ShadowDepth="0" Color="Yellow" Opacity="0.5"/>
</Setter.Value>
</Setter>
</Trigger>

WPF Button style with Image

I want to create a style for button with different images inside. I try to do following:
<Style TargetType="Button"
x:Key="PaintButton">
<Setter Property="Width"
Value="40"></Setter>
<Setter Property="Height"
Value="40"></Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid>
<Border CornerRadius="3"
BorderThickness="2"
BorderBrush="Green">
<Image Source="{TemplateBinding Button.Content}" />
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
and try to use:
<Button Content="images/pen.png"
HorizontalAlignment="Left"
Style="{DynamicResource PaintButton}" />
but images is not shown. Why and how to do it correctly?
The "Image" is not a correct source for another Image.
Either use BitmapImage as Button's contents or use ContentPresenter in the template.
Option 1.
<Button Style="{StaticResource PaintButton}">
<BitmapImage UriSource="Back_Forward.png"/>
</Button>
Option 2.
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Grid>
<Border CornerRadius="3"
BorderThickness="2"
BorderBrush="Green">
<ContentPresenter Content="{TemplateBinding Button.Content}" />
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
Please try this
<Style TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<StackPanel Orientation="Horizontal">
<Grid Height="30" Width="30" Background="{TemplateBinding Background}"/>
<TextBlock Text="{TemplateBinding Content}" TextAlignment="Center" VerticalAlignment="Center"/>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Cursor" Value="Hand"/>
</Trigger>
</Style.Triggers>
</Style>
<Button Name="btnPrintCard" Margin="2" Content="Print Card">
<Button.Background>
<ImageBrush ImageSource="images/ic_print_black_48dp.png"/>
</Button.Background>
</Button>

Volume Slider CustomControl

I searched the last hours for a custom control that looks like this:
Triangular volume control
It's like a simple slider, but this growing size to the right side is my problem.
I don't know how to do this.
Have anyone an idea?
You can define a geometry that has the shape of a triangle and use that as a OpacityMask of the Track. The Track has a repeat button on the left to decrease the value and on the right to increase it. You just need to bind the background of the left button to the background of your slider along with the background of the thumb. You also should make the templates of both the thumb and the repeaters very simple to only show the background color.
Here is an example style:
<Style TargetType="{x:Type Slider}">
<Setter Property="Background" Value="Gray"/>
<Setter Property="Height" Value="20"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Slider}">
<ControlTemplate.Resources>
<Style TargetType="{x:Type RepeatButton}">
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="IsTabStop" Value="false"/>
<Setter Property="Focusable" Value="false"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RepeatButton}">
<Border Background="{TemplateBinding Background}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<PathGeometry x:Key="Triangle">
<PathFigure StartPoint="0,1">
<LineSegment Point="1,1"/>
<LineSegment Point="1,0"/>
<LineSegment Point="0,1"/>
</PathFigure>
</PathGeometry>
</ControlTemplate.Resources>
<Grid>
<Grid>
<Grid.OpacityMask>
<DrawingBrush>
<DrawingBrush.Drawing>
<GeometryDrawing Brush="Black" Geometry="{StaticResource Triangle}"/>
</DrawingBrush.Drawing>
</DrawingBrush>
</Grid.OpacityMask>
<Track Name="PART_Track" Value="{TemplateBinding Value}">
<Track.Thumb>
<Thumb Width="10" Background="{TemplateBinding Background}">
<Thumb.Template>
<ControlTemplate TargetType="{x:Type Thumb}">
<Border Background="{TemplateBinding Background}"/>
</ControlTemplate>
</Thumb.Template>
</Thumb>
</Track.Thumb>
<Track.DecreaseRepeatButton>
<RepeatButton Background="{TemplateBinding Background}" Command="Slider.DecreaseLarge"/>
</Track.DecreaseRepeatButton>
<Track.IncreaseRepeatButton>
<RepeatButton Background="Transparent" Command="Slider.IncreaseLarge"/>
</Track.IncreaseRepeatButton>
</Track>
</Grid>
<Path
Data="{StaticResource Triangle}"
Stretch="Fill"
Stroke="Black"
StrokeThickness="1"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
(This is just an example which disregards a lot of things like e.g. the Orientation)

How to create a WPF-tab control as chevron list?

I have a WPF tab control. but I would like to change the tab item style. The default style is square. I need to make it like a chevron list. Each block in that as hexagon.
EDIT:
Here's a quick example made with Kaxaml:
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Page.Resources>
<Style x:Key="chevronTabItemStyle" TargetType="{x:Type TabItem}">
<Setter Property="Foreground" Value="White" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<StackPanel Orientation="Horizontal" Margin="0,0,-7,0" Height="30">
<Path Data="M0,0 10,0 10,30 0,30 10,15"
Fill="{TemplateBinding Background}"/>
<Grid>
<Rectangle Fill="{TemplateBinding Background}" />
<TextBlock Text="{TemplateBinding Header}" Margin="10,5" VerticalAlignment="Center" />
</Grid>
<Path Data="M0,0 10,15 0,30"
Fill="{TemplateBinding Background}" />
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Page.Resources>
<Grid>
<TabControl ItemContainerStyle="{StaticResource chevronTabItemStyle}">
<TabItem Header="Design" Background="DarkSlateBlue" />
<TabItem Header="Plan" Background="DarkCyan" />
<TabItem Header="Build" Background="LightSkyBlue" />
<TabItem Header="Test" Background="SandyBrown" />
<TabItem Header="Evaluate" Background="SteelBlue" />
</TabControl>
</Grid>
</Page>
You will probably need to adjust a few properties, but it's roughly what you described...
Thomas Levesque your answer is beautiful!
There is a little problem with foreground color, move property into TextBlock prevent all tab to be colored White
In this way we can change the color of the header if properties IsEnable or Selected are valued.
<Style x:Key="TestNewTabStyle" TargetType="{x:Type TabItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<StackPanel Orientation="Horizontal" Margin="0,0,-7,0" Height="30">
<Path Data="M0,0 10,0 10,30 0,30 10,15" Fill="{TemplateBinding Background}"/>
<Grid >
<Rectangle Fill="{TemplateBinding Background}" />
<TextBlock Name="HeaderArrow" Text="{TemplateBinding Header}" Margin="15,5" VerticalAlignment="Center" Foreground="White"**/>
</Grid>
<Path Data="M0,0 10,15 0,30" Fill="{TemplateBinding Background}" />
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="HeaderArrow" Property="FontWeight" Value="Bold" />
<Setter TargetName="HeaderArrow" Property="Foreground" Value="Yellow" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="HeaderArrow" Property="Foreground" Value="DarkGray" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Buttons are disabled in Custom control

I have made a custom control in wpf however I am having an issue with the button that forms a part of the item control (the x in each item element in the attached picture is the button) basically the button is disabled, but I am not disabling it!
If I just place one of the inner items (MultiSelectionItem) into a grid by itself then the button works fine, so it must have something to do with my usage of the ItemsControl element in the Template for the outer control (MultiSelectionBox)
Image:
<Style TargetType="{x:Type local:MultipleSelectionBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:MultipleSelectionBox}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<ItemsControl ItemsSource="{Binding multipleSelectionItems}">
<ItemsControl.Template>
<ControlTemplate>
<WrapPanel IsItemsHost="True"/>
</ControlTemplate>
</ItemsControl.Template>
</ItemsControl>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type local:MultipleSelectionItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:MultipleSelectionItem}">
<Border BorderBrush="#FFC0CBD9" BorderThickness="1" Margin="0,0,2,2" CornerRadius="0">
<Border.Style>
<Style TargetType="Border">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFDFE9F5" Offset="0" />
<GradientStop Color="#FFEEF3FC" Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</Border.Style>
<Grid VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button Command="{x:Static local:MultipleSelectionItemCommands.RemoveCommand}" IsEnabled="True">
<Button.Template>
<ControlTemplate>
<Image Source="/CustomFormResearch;component/Images/x_no_hover.jpg" Margin="2,0,0,0" Height="11" Width="11">
<Image.Style>
<Style TargetType="{x:Type Image}">
<Setter Property="Source" Value="/CustomFormResearch;component/Images/x_no_hover.jpg" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Source" Value="/CustomFormResearch;component/Images/x_with_hover.jpg" />
</Trigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</ControlTemplate>
</Button.Template>
</Button>
<TextBlock Text="{Binding DisplayData}" VerticalAlignment="Stretch" Margin="5,0,5,0" Grid.Column="1" />
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
My first guess is that since your button is bound to a Command, the CanExecute of the command should return false.
This is the principle and benefit of a Command: When the can execute returns false it automaticaly disable the associated button.
Check this links for more about commands and MVVM :
http://msdn.microsoft.com/en-us/magazine/dd419663.aspx
http://msdn.microsoft.com/fr-fr/magazine/cc785480.aspx#id0190094

Resources