DataGridRowDetails - Toggling issue - c#

I am having a DataGrid containing some Jobs.
What every job is doing is shown in the RowDetails.
Here I got multiple problems:
Problem: Why is the Imageon the ToggleButton only shown on the Selected and the last Row ?
This is my xaml:
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ToggleButton IsChecked="{Binding RelativeSource={RelativeSource AncestorType=DataGridRow}, Path=DetailsVisibility, Converter={StaticResource BoolToVisConverter}, Mode=TwoWay}">
<ToggleButton.Style>
<Style TargetType="ToggleButton">
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Content">
<Setter.Value>
<Image Source="..\Resources\ic_expand_less_48px.png" Height="16" Width="16" />
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsChecked" Value="{x:Null}">
<Setter Property="Content">
<Setter.Value>
<Image Source="..\Resources\ic_expand_more_48px.png" Height="16" Width="16" />
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsChecked" Value="False">
<Setter Property="Content">
<Setter.Value>
<Image Source="..\Resources\ic_expand_more_48px.png" Height="16" Width="16" />
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</ToggleButton.Style>
</ToggleButton>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

when Style uses a UIElement for Content property (Image in this case), it creates a single instance of that element. When Style is applied to multiple controls only one of them display Content because UIElement cannot have multiple parents.
That is why in most cases custom templates are used. ToggleButton has ContentTemplate property to customize the appearance of content part: (the same code for other two triggers)
<Trigger Property="IsChecked" Value="False">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Image Source="..\Resources\ic_expand_more_48px.png" Height="16" Width="16" />
</DataTemplate>
</Setter.Value>
</Setter>
</Trigger>
I know another method with non-shared resource:
<Image x:Key="ExpandMoreImg" x:Shared="False"
Source="..\Resources\ic_expand_more_48px.png" Height="16" Width="16" />
<Trigger Property="IsChecked" Value="False">
<Setter Property="Content" Value="{StaticResource ExpandMoreImg}"/>
</Trigger>
Shared is set to false and there will be an instance of Image for each usage

Related

Change listbox item style when selected in WPF

I'm not entirely sure what I'm doing incorrect but it appears that my style trigger is not being recognized. I want to change the color of the Stroke when the listbox item is selected.
<ListBox ItemsSource="{Binding CityList}" DisplayMemberPath="Name" SelectionMode="Extended"
VirtualizingPanel.IsVirtualizing="true"
VirtualizingPanel.VirtualizationMode="Recycling"
Background="Brown">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Canvas.Left" Value="{Binding Longitude, Converter={StaticResource longValueConverter}, ConverterParameter={StaticResource mapWidth}}"/>
<Setter Property="Canvas.Top" Value="{Binding Latitude, Converter={StaticResource latValueConverter}, ConverterParameter={StaticResource mapHeight}}"/>
<Setter Property="BorderThickness" Value="3" />
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Grid>
<Ellipse x:Name="indicator"
Fill="#FF000000"
Height="10"
Width="10"
Stroke="Transparent"
StrokeThickness="2"/>
</Grid>
</DataTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="indicator" Property="Stroke" Value="Red"/>
</Trigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<Canvas IsItemsHost="True"
Width="{StaticResource mapWidth}"
Height="{StaticResource mapHeight}"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
You can't use TargetName in a Style Setter.
Instead of setting the ContentTemplate property, you may set the Template property and add the Trigger to the ControlTemplate.Triggers collection:
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Grid>
<Ellipse x:Name="indicator"
Fill="#FF000000"
Height="10"
Width="10"
Stroke="Transparent"
StrokeThickness="2"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="indicator" Property="Stroke" Value="Red"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
You may also add a ContentPresenter to the Grid in the ControlTemplate, which would display the elements of the ItemTemplate (if you later decide to declare one).

WPF ItemsControl and Togglebuttons weird behaviour

I've been working on a WPF application but encountered some weird behaviour when using ItemsControl to display a list of togglebuttons with binding. It works just fine when it is displaying a collection of 1 element, but when I have two elements it behaves very strange. It will not show the image of both togglebuttons at once if they are in the same state (i.e. toggled on).
The relevant XAML. I have checked that the property behind is updated correctly, but let me know if there is any code that is needed.
<ItemsControl x:Name="ServiceItemsControl" Grid.Row="0" ItemsSource="{Binding DraftMessage.Services}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<ToggleButton IsChecked="{Binding Path=Selected}">
<ToggleButton.Style>
<Style TargetType="ToggleButton">
<Setter Property="Focusable" Value="False"/>
<!--Setter Property="BorderThickness" Value="0"/-->
<Setter Property="Opacity" Value="1"/>
<Setter Property="Content">
<Setter.Value>
<Image Source="{Binding Path=Service.OtherLogo}" Width="25" Height="25"/>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Content">
<Setter.Value>
<Image Source="{Binding Path=Service.Logo}" Width="25" Height="25"/>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</ToggleButton.Style>
</ToggleButton>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
You need to use a DataTrigger on the Image to change its Source property when the ToggleButton.IsChecked value is changed instead. Try this:
<DataTemplate>
<ToggleButton IsChecked="{Binding Path=IsSelected}">
<Image Width="25" Height="25">
<Image.Style>
<Style TargetType="{x:Type Image}">
<Setter Property="Source" Value="{Binding Service.OtherLogo}" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked,
RelativeSource={RelativeSource AncestorType={x:Type
ToggleButton}}}" Value="True">
<Setter Property="Source" Value="{Binding Service.Logo}" />
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
<ToggleButton.Style>
<Style TargetType="ToggleButton">
<Setter Property="Focusable" Value="False"/>
<!--Setter Property="BorderThickness" Value="0"/-->
<Setter Property="Opacity" Value="1"/>
</Style>
</ToggleButton.Style>
</ToggleButton>
</DataTemplate>

Customising ToggleButton state images using XAML

I am currently using the XAML below to change the image on a toggle button for each state. How can I define a template or style that will allow me to define the images that are to be used in the button definition such that I don't have to repeat everything below for each button. Is this even possible ?
Ideally I would like to define a template with properties such as 'checkedImage', 'uncheckedImage' and then set these properties in the button definition in Designer.
I would also like the button to prevent the display of any other states or animations but I can't seem to prevent the background changing when the button is selected or when there is a mouseover. Are there some additional states that I don't have defined below?
Sample code (XAML, C#) for the style or template and for the actual toggle button definition would be appreciated. Also any references to 'simple' samples and explanations would be appreciated.
Thanks
EDIT: Update with my latest attempt...
This almost works - the correct image never gets displayed when the button is Checked. Any ideas what I am missing here?
<Style x:Key="ImgToggleButton" TargetType="ToggleButton">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Grid x:Name="GD" Background="White">
<ContentPresenter x:Name="CP" Content="{TemplateBinding Content}"></ContentPresenter>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Content">
<Setter.Value>
<Image Source="{Binding Path=Tag, RelativeSource={RelativeSource AncestorType=ToggleButton}}" Stretch="Uniform"/>
</Setter.Value>
</Setter>
<Setter TargetName="GD" Property="Background" Value="{DynamicResource ThemeSolidColorBrushBlue}"/>
</Trigger>
<Trigger Property="IsChecked" Value="False">
<Setter TargetName="GD" Property="Background" Value="White"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<!-- Nothing so we have no change-->
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And here is the button definition
<ToggleButton x:Name="allTestsToggleButton" Tag="Asset/AllTestsButton_1.png" Style="{DynamicResource ImgToggleButton}" ClickMode="Press" Checked="allTestsToggleButton_Checked" Unchecked="allTestsToggleButton_Unchecked" Grid.Row="2" Grid.Column="3" Grid.ColumnSpan="5">
<ToggleButton.Content>
<Image Source="Assets/AllTestsButton_0.png" Stretch="Uniform"/>
</ToggleButton.Content>
</ToggleButton>
Setting TargetName="CP" does not work either
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="CP" Property="Content">
<Setter.Value>
<Image Source="{Binding Path=Tag, RelativeSource={RelativeSource AncestorType=ToggleButton}}" Stretch="Uniform"/>
</Setter.Value>
</Setter>
<Setter TargetName="GD" Property="Background" Value="{DynamicResource ThemeSolidColorBrushBlue}"/>
</Trigger>
<Trigger Property="IsChecked" Value="False">
<Setter TargetName="GD" Property="Background" Value="White"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<!-- Nothing so we have no change-->
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
Update1
You can use this style for multiple button with different images and I have used tag for storing image for checked state true and use templatebinding for default look i.e state=false
<Window.Resources>
<BitmapImage x:Key="imag1" UriSource="image1.jpg"></BitmapImage>
<BitmapImage x:Key="imag2" UriSource="path.jpg"></BitmapImage>
<Style TargetType="ToggleButton">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Grid x:Name="GD" Background="{TemplateBinding Background}">
<ContentPresenter></ContentPresenter>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="GD" Property="Background">
<Setter.Value>
<ImageBrush ImageSource="{Binding Path=Tag, RelativeSource={RelativeSource AncestorType=ToggleButton}}"></ImageBrush>
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<ToggleButton x:Name="sampleTestToggleButton" Tag="{StaticResource imag2}" ClickMode="Press" Grid.Row="4" Grid.Column="3" BorderBrush="Transparent" Foreground="Transparent">
<ToggleButton.Background>
<ImageBrush ImageSource="{StaticResource imag1}"></ImageBrush>
</ToggleButton.Background>
</ToggleButton>
Update2:
Hope this helps.Run this code separately.It is working fine here.
<Window.Resources>
<Style x:Key="ImgToggleButton" TargetType="ToggleButton">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Image Stretch="Uniform" Source="{Binding Content,RelativeSource={RelativeSource TemplatedParent}}"></Image>
</DataTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Grid x:Name="GD" Background="White">
<ContentPresenter></ContentPresenter>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Image Stretch="Uniform" Source="{Binding Path=Tag, RelativeSource={RelativeSource AncestorType=ToggleButton}}"></Image>
</DataTemplate>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsChecked" Value="False">
<Setter TargetName="GD" Property="Background" Value="White"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<!-- Nothing so we have no change-->
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<ToggleButton x:Name="allTestsToggleButton" Content="imag2.jpg" Tag="imag1.jpg" Style="{DynamicResource ImgToggleButton}" ClickMode="Press" Grid.Row="2" Grid.Column="3" Grid.ColumnSpan="5"/>
I think, you need for the ability to use vector graphics in WPF. 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
Do not store this files in Resources
Dynamically changing color, size and the whole shape
The Minuses, in my opinion:
You can not always find the right Data for the Path
About minus: There are special sites, like www.modernuiicons.com and utilities for converting the image to Data. For converting Image to Vector graphics (Path) use Inkscape, him free and very useful. For more information see this link:
Vectorize Bitmaps to XAML using Potrace and Inkscape
Example
<Window.Resources>
<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>
</Window.Resources>
<StackPanel Orientation="Vertical" HorizontalAlignment="Center">
<CheckBox Height="35"
Style="{StaticResource styleCustomCheckBox}"
Content="MySolution1" />
<CheckBox Height="35"
Style="{StaticResource styleCustomCheckBox}"
Content="MySolution2" />
</StackPanel>
Output

ToggleButton style not working when in treeview

I have a treeview with buckets and parts. Everything looks great except one feature. A property on bucket (bool IsEditable) allows the user to toggle editing on or off within the tree view for that node. But for some reason when wpf displays the collection of buckets in the treeview the togglebuttons do not show the proper text
Here is my xaml:
<Style TargetType="{x:Type ToggleButton}" x:Key="Editor">
<Style.Triggers>
<Trigger Property="IsChecked" Value="False">
<Setter Property="Content">
<Setter.Value>
<TextBlock Text="Edit"/>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Content">
<Setter.Value>
<TextBlock Text="Done"/>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
<DataTemplate x:Key="HierarchialItemTemplate">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding BucketQty, UpdateSourceTrigger=PropertyChanged}"/>
<TextBlock Text=" "/>
<TextBlock Text="{Binding PartNum}"/>
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="DisplayBucket">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Sequence}"/>
<TextBlock Text=" "/>
<TextBlock Text="{Binding Description}"/>
<ToggleButton IsChecked="{Binding IsEditable}" Width="25" Style="{StaticResource Editor}"/>
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="EditBucket">
<StackPanel Orientation="Horizontal">
<TextBox Text="{Binding Sequence}"/>
<TextBlock Text=" "/>
<TextBox Text="{Binding Description}"/>
<ToggleButton IsChecked="{Binding IsEditable}" Width="25" Style="{StaticResource Editor}"/>
</StackPanel>
</DataTemplate>
<HierarchicalDataTemplate x:Key="TreeTemplate"
DataType="{x:Type domain:Bucket}"
ItemsSource="{Binding Parts}"
ItemTemplate="{StaticResource HierarchialItemTemplate}"
>
<ContentPresenter Content="{Binding}"
Style="{DynamicResource TreeNodeStyle}"/>
</HierarchicalDataTemplate>
<Style TargetType="{x:Type ContentPresenter}" x:Key="TreeNodeStyle">
<Setter Property="ContentTemplate" Value="{StaticResource DisplayBucket}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsEditable}" Value="True">
<Setter Property="ContentTemplate" Value="{StaticResource EditBucket}"/>
</DataTrigger>
</Style.Triggers>
</Style>
The above is window.resources. In the Grid is
<TreeView x:Name="Buckets"
ItemsSource="{Binding Model.Job.Buckets}"
ItemTemplate="{StaticResource TreeTemplate}"
>
So for whatever reason when I add nodes I get a bucket with a toggle button, but the toggle button text only shows up for the last node added. If I click a toggle button, the text disappears out of the previous toggle button and shows up in the one just clicked. The effect is similar to what this person experienced, but I have no idea what the guy was talking about who answered the question ToggleButton Style only works on last ToggleButton.
Any thoughts?
You have couple of options (ordered from least to most dramatic):
1) Content
<Style TargetType="{x:Type ToggleButton}" x:Key="Editor">
<Style.Triggers>
<Trigger Property="IsChecked" Value="False">
<Setter Property="Content" Value="Edit" />
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Content" Value="Done" />
</Trigger>
</Style.Triggers>
</Style>
2) ContentTemplate
<Style TargetType="{x:Type ToggleButton}" x:Key="Editor">
<Style.Triggers>
<Trigger Property="IsChecked" Value="False">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="Edit"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="Done"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
3) ControlTemplate
<Style TargetType="{x:Type ToggleButton}" x:Key="Editor">
<Style.Triggers>
<Trigger Property="IsChecked" Value="False">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<TextBlock Text="Edit"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<TextBlock Text="Done"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
The reason why your approach didn't work is that TextBlock control is created only once (i.e. not created as part of template - ControlTemplate or DataTemplate).

How to make value of a custom control editable upon receiving focus

I created a custom WPF control which displays the value of the Weight property which is an int. When the user clicks on the custom control or when the control gets the focus, the user should be able to edit the value of the Weight property.
To accomplish this, I tried the following:
If the control is "inactive", the Weight property will be displayed
in a TextBlock.
If the control gets the focus, the Weight property
will be displayed in a TextBox.
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfCustomControlLibrary1">
<Style TargetType="{x:Type local:CustomControl1}">
<Style.Resources>
<ControlTemplate x:Key="Control_Focused" >
<Border Background="Green"
BorderBrush="Black"
CornerRadius="50" Width="40" Height="40">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBox Width="35"
Text="{Binding Mode=TwoWay,Path=Model.Weight,UpdateSourceTrigger=PropertyChanged,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type local:CustomControl1}}
,Converter={x:Static local:CustomControl1.IntToStringConverter}}" />
</StackPanel>
</Border>
</ControlTemplate>
<ControlTemplate x:Key="Control">
<Border Background="Green"
BorderBrush="Black"
CornerRadius="50" Width="40" Height="40">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock x:Name="PART_TextBlockWeighted" Text="{Binding Mode=TwoWay,Path=Model.Weight,UpdateSourceTrigger=PropertyChanged,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type local:CustomControl1}}}"
HorizontalAlignment="Center" VerticalAlignment="Center" />
</StackPanel>
</Border>
</ControlTemplate>
</Style.Resources>
<Style.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="Template" Value="{StaticResource Control_Focused}" ></Setter>
</Trigger>
<Trigger Property="IsFocused" Value="False">
<Setter Property="Template" Value="{StaticResource Control}" ></Setter>
</Trigger>
</Style.Triggers>
</Style>
The problem with this custom control style is that when the user clicks into the TextBox, the trigger will change the control template to the TextBlock. How can I fix this?
Try using the IsKeyboardFocusWithin property instead. I believe this will do what you need.
<Style.Triggers>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="Template" Value="{StaticResource Control_Focused}" ></Setter>
</Trigger>
<Trigger Property="IsKeyboardFocusWithin" Value="False">
<Setter Property="Template" Value="{StaticResource Control}" ></Setter>
</Trigger>
</Style.Triggers>

Categories