wp7 c# implement trigger on control template - c#

I'm building a small wp7 application in which I have a star user control, when the star is clicked its color changes.
Here's the code I've got:
<Grid.Resources>
<ControlTemplate x:Key="starTemplate" TargetType="ToggleButton">
<Viewbox>
<Path Name="star" Fill="Gray" Data="F1 M 145.637,174.227L 127.619,110.39L 180.809,70.7577L 114.528,68.1664L 93.2725,5.33333L 70.3262,67.569L 4,68.3681L 56.0988,109.423L 36.3629,172.75L 91.508,135.888L 145.637,174.227 Z"/>
</Viewbox>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="star" Property="Fill" Value="White"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Grid.Resources>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<ToggleButton Grid.Column="0" Tag="1" Cursor="Hand" Template="{StaticResource starTemplate}" Click="RatingButtonClickEventHandler"/>
the problem is that its giving me an error on the trigger:
The attachable property 'Triggers' was not found in type 'ControlTemplate'
I've read in this link that silverlight 3 doesn't support style triggers and that I have to implement DataTrigger somewhere. The question is How?

Related

How can I apply style based on a trigger property to a content control?

In the current WPF application that I am working on, I have to invert the color of an icon when the mouse is pressed on (when property isPressed=true ). The reason why I need to do is I want to keep the consistency of the application with regard to the icon color and background. But this icon is embedded within a button which when clicked displays a similar color and hence the icon is not visible
As my style trigger picks up the red color that I have set but the color of the geometry is not changed. Is there any way I can use this style trigger to set the color of the geometry also to Red when (isPressed=true)?
Here is my code
My Style is as follows
<Style x:Key="ButtonBackground" TargetType="{x:Type Button}">
<Style.Triggers>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Foreground" Value="Red" />
<Setter Property="Content" Value="yellow" />
</Trigger>
</Style.Triggers>
</Style>
I tried setting a setter property to content as yellow just to see if it works but it did not work
The part where it is being used is as follows
<Border BorderBrush="{StaticResource ContentBackground}" BorderThickness="0,0,0,1">
<Button
x:Name="NameButton"
Style="{StaticResource ButtonBackground}"
>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Orientation="Horizontal">
<ContentControl x:Name="Icon"
Width="25"
Height="25"
">
</ContentControl>
<TextBlock Text="{Binding Name}"
"/>
</StackPanel>
</Grid>
</Button>
</Border>
As shown in the images as well the style is picked up by the textblock but I do not know how I can add this style to the contentcontrol which has the icons
Edit :- Example of icon specified in the application
<DataTemplate x:Key="FolderIcon">
<Path
Fill="#047F89"
Data="....."/>
</DataTemplate>
You have to bind the Fill property of the Path to the parent Control element's Control.Foreground (or Button.Foreground) instead of setting it directly. Now the icon color will adapt to the Foreground value assigned by the trigger. I also removed the redundant Grid of the Button.Content and the Content Setter of the Trigger as it would remove the icon Path element every time the Button is pressed and added the default Forground value to the Style (moved from Path.Fill to Style-Setter):
<Style x:Key="ButtonBackground" TargetType="{x:Type Button}">
<Setter Property="Foreground" Value="#047F89" />
<Style.Triggers>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Foreground" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
<Button x:Name="NameButton"
Style="{StaticResource ButtonBackground}">
<Button.Content>
<StackPanel Orientation="Horizontal">
<Path Fill="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Control}, Path=Foreground}"
Height="16"
Width="16"
Stretch="Uniform"
VerticalAlignment="Center"
Margin="5,0,0,0"
Data="....."/>
<TextBlock Text="{Binding Name}"
TextTrimming="WordEllipsis"
VerticalAlignment="Center"
Margin="5,0,0,0"/>
<StackPanel>
<Button.Content>
</Button>
The Binding on Path.Fill would still work in case you decide to move the Path to a ResourceDictionary.

WPF Expander Templating - Display Content above ToggleButton

I'm about to create a new Expander Control (learning purpose) by creating different templates but can't figure out what I'm doing wrong...
ToggleButtonTemplate:
<ToggleButton>
<ToggleButton.Template>
<ControlTemplate TargetType="ToggleButton">
<Border x:Name="eBB" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<Path x:Name="Sign" Data="M 0,10 L 7.5,2.5 L 15, 10" Stroke="Black" Width="15">
<Path.RenderTransform>
<RotateTransform Angle="0"/>
</Path.RenderTransform>
</Path>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Data" TargetName="Sign" Value="M 0,2.5 L 7.5,10 L 15,2.5"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Stroke" Value="#222" TargetName="Sign"/>
<Setter Property="Background" Value="#666" TargetName="eBB"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Stroke" Value="#FF003366" TargetName="Sign"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</ToggleButton.Template>
</ToggleButton>
Expander Template:
<Expander>
<Expander.Template>
<ControlTemplate TargetType="Expander">
<Grid>
<Grid.RowDefinitions>
<RowDefinition x:Name="ContentRow" Height="*"/>
<RowDefinition Height="20"/>
</Grid.RowDefinitions>
<ContentPresenter Grid.Row="0" Visibility="Collapsed" Content="{TemplateBinding Content}"/>
<local:FullSizeExpanderToggleButton Grid.Row="1" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsExpanded" Value="True">
<Setter Property="Visibility" Value="Visible"/>
<Setter Property="Height" Value="*" TargetName="ContentRow"/>
</Trigger>
<Trigger Property="IsExpanded" Value="False">
<Setter Property="Height" Value="0" TargetName="ContentRow"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Expander.Template>
</Expander>
Now when I want to add the Expander in my Main View:
<custom:FullSizeExpander Width="300">
<Button/>
</custom:FullSizeExpander>
the whole space inside the Control gets filled by the Button (the ToggleButton isn't visible anymore).
What am i doing wrong?
In addition I have some questions regarding this issue:
What does "ContentSource="Content"" do? What is it for? Whats different to "Content="{Templatebinding Content}""?
Does the Expander's Property "IsExpanded" get changed when the ToggleButtons Property "IsPressed" gets changed? What if there is no Togglebutton in the Expander at all?
first off, consider modifying your Expander template to look something like this:
<Expander>
<Rectangle Height="500" Width="500" Fill="Red"/>
<Expander.Template>
<ControlTemplate TargetType="Expander">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="20"/>
</Grid.RowDefinitions>
<ContentPresenter Grid.Row="0" x:Name="ContentPresenter"/>
<ToggleButton Grid.Row="1" IsChecked="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsExpanded}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsExpanded" Value="True">
<Setter TargetName="ContentPresenter" Property="Visibility" Value="Visible"/>
</Trigger>
<Trigger Property="IsExpanded" Value="False">
<Setter TargetName="ContentPresenter" Property="Visibility" Value="Collapsed"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Expander.Template>
</Expander>
I'll explain how it works, and why it wasn't working before from the top-down.
First off, you'll want to actually put something in the expander to make sure it's working - i put a rectangle here with fixed sizes for now.
Next, i changed the first RowDefinition to be auto instead of *, as you want the expander to actually expand when opened. (rather than just hide its content in a big empty area). Auto uses exactly as much space as the content in the row needs, so when it's collapsed, that size will be 0, and when it's expanded, auto will become 500 to fit the rectangle.
The third thing i did was remove your bindings from the ContentPresenter. As it happens, Windows' content-bearing templates (as in anything that can have something else placed inside of it) will automatically look for the first ContentPresenter / ItemsPresenter tag inside its template and shove content into it.
As for the togglebutton however (i kept it simple and left it as a standard togglebutton), this one does actually need a binding.
What i did was a Relativesource Templatebinding to the property "IsExpanded".
Togglebuttons have 2 main states: "Checked" and "Unchecked" (true/false), and Expanders have 2 main states: "Expanded" and "Collapsed" (true/false).
So essentially all i did was tell the ToggleButton to share its true/false state of being checked or unchecked with the parent it sits inside of.
The full binding again is "{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsChecked}", which in english is essentially saying "Bind to a related source, and the related source is the parent you're in the template of, and bind so to said template;s "IsChecked" property.
Lastly i changed your triggers which were going the long way around to get the ContentPresenter to become hidden (trying to squash it by reducing the size of the Grid.Row it sits in), and instead just told it to hide when the expander's "IsExpanded" (and thanks to our binding, the ToggleButton's "IsChecked") is set to false, and the opposite when they're set to true.
.
As for your other questions:
1) The ContentSource is used to give the ContentPresenter an alias/alternate name, and i doubt you'll need it anytime soon. The property name is sort of misleading, i grant you.
2) As we saw above, no - the ToggleButton needs to be bound to the templated parent's "IsExpanded" property in order to work.
If you were to take the button out, the Expander simply would not work until you created a binding or made an instruction in code to tell it to open/close.

Change color of subelements by mouseover

I have the following Window bar with four buttons and one image (a littlebit like ribbon):
this is the code (XAML) and the code behind (in C#) is not interesting :
<Button Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}" Focusable="False"
Click="SaveClicked" Margin="10, 0">
<StackPanel Orientation="Horizontal" >
<Image x:Name="ImageSave" Height="20" VerticalAlignment="Bottom" HorizontalAlignment="Left" Width="20"
Source="images/titlebar/SaveIconWhite.png" Margin="0,0,0,5" />
<Label x:Name="LbSave" Content="Save" VerticalAlignment="Stretch" FontSize="14"
HorizontalAlignment="Left" Foreground="White" />
</StackPanel>
<Button.Template>
<ControlTemplate TargetType="Button">
<ContentPresenter Content="{TemplateBinding Content}"/>
</ControlTemplate>
</Button.Template>
</Button>
The code is nearly the same for the other buttons.
The buttons feel a littlebit unhandy because they have no mouseover effects.
I would like to implement a color change of the labels when the mouse is over the buttons. a change of the images for file load and save would be great too, but i think i am able to do it myself when i know how to implement the mouse over color change of the label.
under normal conditions i'd try to archieve a mouse over color change with these code:
<Button.Style>
<Style TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="DarkGoldenrod"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
But this does not work, because i already have the Button.Template and i am also a littlebit confused about the Button.Template at all (haven't understood it - only copied..). How is the Button.Template working and what is it usage?
Is anybody able to give me a hint in the right direction?
We have MouseEnter and MouseLeave Events.
Use MouseEnter to Change the Color When Mouse is inside control.
Use MouseLeave to Change back the Color When Mouse comes out of the control.
Never Used but Put Trigger inside ControlTemplate of button:
Something Like This:
<Button.Template>
<ControlTemplate TargetType="Button">
<ContentPresenter Content="{TemplateBinding Content}"/>
<ControlTemplate.Triggers>
<Trigger Property="Button.IsMouseOver" Value="True">
<Setter TargetName="buttonLabel" Property="Foreground" Value="Red"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
and How is the Button.Template working and what is it usage?
visit the link below
http://www.codeproject.com/Articles/84630/WPF-Customize-your-Application-with-Styles-and-Con
https://msdn.microsoft.com/en-us/library/cc295273.aspx
Hope it may help you.

WPF ComboBox EditTemplate - TextBox border is not going away

I am using a DEVExpress combobox and have enabled type ahead (Auto search functioanlity). In combo box I am showing two things. First item is an image and second item is a value(id).
Mine problem is that the value border is getting outside to combo box while showing at UI at run time. I tried setting margin but its of no use. My application is having option to select theme and for some of the theme its getting hazy.
Any idea how to get rid of this ?
see the first one is looking fine however the below one is bit hazy if i change the theme.
I am using below code for the same.
<dvEx:ComboBoxEdit.EditTemplate>
<ControlTemplate>
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Path=(dxe:BaseEdit.OwnerEdit).SelectedItem.Image, RelativeSource={RelativeSource Self}}" Margin="8, 0, 4, 0"/>
<TextBox x:Name="PART_Editor" BorderBrush="Transparent"/>
</StackPanel>
</ControlTemplate>
</dvEx:ComboBoxEdit.EditTemplate>
<dvEx:ComboBoxEdit.ItemTemplate>
<DataTemplate DataType="{x:Type vm:DesignSelectViewModel}">
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Image}" Margin="8, 0, 4, 0"/>
<TextBlock Text="{Binding Name}"/>
</StackPanel>
</DataTemplate>
</dvEx:ComboBoxEdit.ItemTemplate>
To accomplish your task I suggest you to override the TextBox.Template as follows to make it theme-independent and remove it's focused state (border and background):
<TextBox x:Name="PART_Editor">
<TextBox.Template>
<ControlTemplate TargetType="{x:Type TextBox}">
<Grid x:Name="Root" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}">
<ScrollViewer x:Name="PART_ContentHost" Margin="1" Padding="{TemplateBinding Padding}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsReadOnly" Value="True">
<Setter Property="Opacity" TargetName="PART_ContentHost" Value="0.75"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter Property="Opacity" TargetName="Root" Value="0.5"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</TextBox.Template>
</TextBox>
Related MSDN article: TextBox Styles and Templates

Change Images on Custom CheckBox in WPF

All I have created the following custom CheckBox which uses images instead of a CheckBox. This works well however, I want to be able to change the images as required. Ideally I would like to use application resources Properties.Resources.SomeImage16 (a .png file). The XAML is
<Style x:Key="styleCustomCheckBox"
TargetType="{x:Type CheckBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type CheckBox}">
<StackPanel Orientation="Horizontal">
<Image x:Name="imageCheckBox"
Width="16"
Height="16"
Source="F:\Camus\ResourceStudio\Graphics\Images\UnPinned16.png"/>
<ContentPresenter VerticalAlignment="Center"/>
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="False">
<Setter TargetName="imageCheckBox"
Property="Source"
Value="F:\Camus\ResourceStudio\Graphics\Images\Pinned16.png"/>
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="imageCheckBox"
Property="Source"
Value="F:\Camus\ResourceStudio\Graphics\Images\UnPinned16.png"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
With implementation
<ListBox SelectionMode="Single" >
<StackPanel Orientation="Horizontal">
<CheckBox Style="{StaticResource styleCustomCheckBox}"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Margin="4,0,4,0"/>
<TextBlock VerticalAlignment="Top"
Text="SomeRecentDocument.resx"/>
</StackPanel>
</ListBox>
How can I change the images used for the custom CheckBox (i.e. change the pinned/un-pinned to tick/cross etc.) without having to create a new style/template?
Thanks for your time.
As already mentioned #HighCore the need for the ability to use vector graphics. In this case, to use the Path, where in Data to the specified coordinates on which the object is drawn (MSDN).
Advantages:
Do not store it in the files, smaller size
Dynamically changing color, size and the whole shape
Minuses (in my opinion):
You can not always find the right Data for the Path
About minus: There are special sites (www.modernuiicons.com) and utilities for converting the image to Data.
Change the style of CheckBox using the Path:
Style
<Style x:Key="styleCustomCheckBox" TargetType="{x:Type CheckBox}">
<Setter Property="FontFamily" Value="Verdana" />
<Setter Property="FontSize" Value="14" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type CheckBox}">
<StackPanel Orientation="Horizontal">
<Path x:Name="MyPin" Width="18" Height="18" Stretch="Fill" Fill="#FF000000"
Data="F1 M 56.1355,32.5475L 43.4466,19.8526C 42.7886,20.4988 42.298,21.2123 41.9749,21.9932C 41.6519,22.7741 41.4903,23.5729 41.4903,24.3895C 41.4903,25.1942 41.6529,25.987 41.9779,26.7679L 34.0577,34.6821C 33.3918,34.3372 32.6991,34.0776 31.9796,33.9032C 31.2601,33.7288 30.5298,33.6415 29.7885,33.6415C 28.623,33.6415 27.4953,33.8526 26.4052,34.2748C 25.315,34.697 24.3419,35.3342 23.4856,36.1865L 30.2344,42.9174L 25.9027,47.9032L 22.6532,51.8425L 20.5988,54.5836C 20.1212,55.2892 19.8823,55.753 19.8823,55.975L 19.8645,56.0701L 19.9002,56.088L 19.9002,56.1474L 19.9358,56.1058L 20.0131,56.1236C 20.2351,56.1236 20.6989,55.8888 21.4045,55.419L 24.1457,53.3765L 28.0849,50.1151L 33.0945,45.7775L 39.8016,52.5025C 40.6579,51.6462 41.2961,50.6731 41.7163,49.5829C 42.1365,48.4928 42.3466,47.367 42.3466,46.2056C 42.3466,45.4603 42.2603,44.729 42.0879,44.0115C 41.9155,43.294 41.6548,42.6003 41.3069,41.9304L 49.2202,34.0161C 50.0011,34.3372 50.7939,34.4978 51.5986,34.4978C 52.4192,34.4978 53.2189,34.3362 53.9979,34.0132C 54.7768,33.6901 55.4894,33.2015 56.1355,32.5475 Z "/>
<ContentPresenter VerticalAlignment="Center" Margin="10,0,0,0" />
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="False">
<Setter TargetName="MyPin" Property="Data" Value="F1 M 32.3691,30.2225L 33.2253,29.3901L 15.361,11.5258C 13.9814,12.7067 12.6951,13.9936 11.5148,15.3738L 26.6252,30.4842C 27.743,30.1631 28.8767,30.0025 30.0263,30.0025C 30.8191,30.0025 31.6,30.0759 32.3691,30.2225 Z M 45.5039,49.3629L 60.6292,64.4826C 62.0123,63.2996 63.3017,62.0101 64.4846,60.6268L 46.6218,42.7866L 45.7834,43.619L 45.9439,44.7726L 45.9915,45.9261L 45.8785,47.6713L 45.5039,49.3629 Z M 56.1355,32.5475L 43.4466,19.8526C 42.7886,20.4987 42.298,21.2123 41.9749,21.9932C 41.6519,22.7741 41.4903,23.5729 41.4903,24.3895C 41.4903,25.1942 41.6529,25.987 41.9779,26.7679L 34.0577,34.6821C 33.3918,34.3372 32.6991,34.0776 31.9796,33.9032C 31.2601,33.7288 30.5298,33.6415 29.7885,33.6415C 28.623,33.6415 27.4953,33.8526 26.4052,34.2748C 25.315,34.697 24.3419,35.3342 23.4856,36.1865L 30.2344,42.9174L 25.9027,47.9032L 22.6532,51.8425L 20.5988,54.5836C 20.1212,55.2892 19.8823,55.753 19.8823,55.975L 19.8645,56.0701L 19.9002,56.0879L 19.9002,56.1474L 19.9358,56.1058L 20.0131,56.1236C 20.2351,56.1236 20.6989,55.8888 21.4045,55.419L 24.1457,53.3765L 28.0849,50.1151L 33.0945,45.7775L 39.8016,52.5025C 40.6579,51.6462 41.2961,50.6731 41.7163,49.5829C 42.1365,48.4928 42.3466,47.367 42.3466,46.2056C 42.3466,45.4603 42.2603,44.729 42.0879,44.0115C 41.9155,43.294 41.6548,42.6003 41.306,41.9304L 49.2202,34.0161C 50.0011,34.3372 50.7939,34.4978 51.5986,34.4978C 52.4192,34.4978 53.219,34.3362 53.9979,34.0132C 54.7768,33.6901 55.4894,33.2015 56.1355,32.5475 Z " />
<Setter TargetName="MyPin" Property="Fill" Value="Gray" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Using
<StackPanel Orientation="Vertical" HorizontalAlignment="Center">
<CheckBox Height="35"
Style="{StaticResource styleCustomCheckBox}"
Content="MySolution1" />
<CheckBox Height="35"
Style="{StaticResource styleCustomCheckBox}"
Content="MySolution2" />
</StackPanel>
Output
We can also store the Path's in resources, and refer to them as like this:
<Path x:Key="MyPath" Data="F1 M 38,19C 48.4934,19 57,27.5066 ... />
...
<Setter TargetName="MainPath" Property="Data"
Value="{Binding Source={StaticResource MyPath}, Path=Data}" />
Edit
To specify arbitrary icons, I created two attached dependency properties (string type):
IsCheckedOnData
IsCheckedOffData
IsCheckedOnData contains Data value by IsChecked = "True", IsCheckedOffData value by IsChecked = "False".
Now you need only to determine the strings of icons and define such a resource (for example).
Full example:
XAML
<Window x:Class="CustomCheckBoxHelp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CustomCheckBoxHelp"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
WindowStartupLocation="CenterScreen"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<sys:String x:Key="Up">
F1 M 37.8516,35.625L 34.6849,38.7917L 23.6016,50.2708L
23.6016,39.9792L 37.8516,24.9375L 52.1016,39.9792L 52.1016,
50.2708L 41.0182,38.7917L 37.8516,35.625 Z
</sys:String>
<sys:String x:Key="Down">
F1 M 37.8516,39.5833L 52.1016,24.9375L 52.1016,35.2292L
37.8516,50.2708L 23.6016,35.2292L 23.6016,24.9375L 37.8516,39.5833 Z
</sys:String>
<Style x:Key="styleCustomCheckBox" TargetType="{x:Type CheckBox}">
<Setter Property="FontFamily" Value="Verdana" />
<Setter Property="FontSize" Value="14" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type CheckBox}">
<StackPanel Orientation="Horizontal">
<Path x:Name="MyPin" Width="18" Height="18" Stretch="Fill" Fill="#FF000000"
Data="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(local:CustomCheckBoxClass.IsCheckedOnData)}" />
<ContentPresenter VerticalAlignment="Center" Margin="10,0,0,0" />
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="False">
<Setter TargetName="MyPin" Property="Data"
Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(local:CustomCheckBoxClass.IsCheckedOffData)}" />
<Setter TargetName="MyPin" Property="Fill" Value="Gray" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid>
<StackPanel Orientation="Vertical" HorizontalAlignment="Center" Background="Beige">
<CheckBox Height="35"
local:CustomCheckBoxClass.IsCheckedOnData="{StaticResource Up}"
local:CustomCheckBoxClass.IsCheckedOffData="{StaticResource Down}"
Style="{StaticResource styleCustomCheckBox}"
Content="MySolution1" />
<CheckBox Height="35"
local:CustomCheckBoxClass.IsCheckedOnData="{StaticResource Up}"
local:CustomCheckBoxClass.IsCheckedOffData="{StaticResource Down}"
Style="{StaticResource styleCustomCheckBox}"
Content="MySolution2" />
</StackPanel>
</Grid>
</Window>
Code behind
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
public class CustomCheckBoxClass : DependencyObject
{
#region IsCheckedOnDataProperty
public static readonly DependencyProperty IsCheckedOnDataProperty;
public static void SetIsCheckedOnData(DependencyObject DepObject, string value)
{
DepObject.SetValue(IsCheckedOnDataProperty, value);
}
public static string GetIsCheckedOnData(DependencyObject DepObject)
{
return (string)DepObject.GetValue(IsCheckedOnDataProperty);
}
#endregion
#region IsCheckedOffDataProperty
public static readonly DependencyProperty IsCheckedOffDataProperty;
public static void SetIsCheckedOffData(DependencyObject DepObject, string value)
{
DepObject.SetValue(IsCheckedOffDataProperty, value);
}
public static string GetIsCheckedOffData(DependencyObject DepObject)
{
return (string)DepObject.GetValue(IsCheckedOffDataProperty);
}
#endregion
static CustomCheckBoxClass()
{
PropertyMetadata MyPropertyMetadata = new PropertyMetadata(string.Empty);
IsCheckedOnDataProperty = DependencyProperty.RegisterAttached("IsCheckedOnData",
typeof(string),
typeof(CustomCheckBoxClass),
MyPropertyMetadata);
IsCheckedOffDataProperty = DependencyProperty.RegisterAttached("IsCheckedOffData",
typeof(string),
typeof(CustomCheckBoxClass),
MyPropertyMetadata);
}
}
Note: In the style I have not used TemplateBinding because TemplateBinding doesn’t work outside a template or outside its VisualTree property, so you can’t even use TemplateBinding inside a template’s trigger. Therefore, we must use the construction {RelativeSource TemplatedParent} and a Path equal to the dependency property whose value you want to retrieve.
Sorry, I don't yet know how to reference an image in those resources, but if you can add the images into a folder named Images in your application root directory, then you will be able to reference the images simply like this:
<Image Source="/ApplicationName;component/Images/SomeImage16.png" />
As you mention you can change the checkbox trigger by checked and unchecked. And the image will display corresponding trigger. Your xml code is good for me.I just remove the trigger true portion.because the false portion by default in focus and after click the checkbox image UnPinned16.png is visible. And agan click image Pinned16.png is visibale .
<Style x:Key="styleCustomCheckBox"
TargetType="{x:Type CheckBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type CheckBox}">
<StackPanel Orientation="Horizontal">
<Image x:Name="imageCheckBox"
Width="16"
Height="16" Source="F:\Camus\ResourceStudio\Graphics\Images\UnPinned16.png"/>
<ContentPresenter VerticalAlignment="Center"/>
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="False">
<Setter TargetName="imageCheckBox"
Property="Source"
Value="F:\Camus\ResourceStudio\Graphics\Images\Pinned16.png"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And I am using this checkbox under a textblock
<CheckBox Style="{StaticResource styleCustomCheckBox}"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Margin="4,0,4,0"/>

Categories

Resources