how to show selected text in combobox using custom template - wpf

I'm new in WPF, implementing application to show 2 combobox with different formated text.
I have created custom controltemplate for combobox
<ControlTemplate x:Key="GridGenreComboboxTemplate" TargetType="{x:Type ComboBox}">
<ControlTemplate.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent"/>
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Transparent"/>
</ControlTemplate.Resources>
<StackPanel>
<ToggleButton
IsTabStop="False" x:Name="DropDownToggle"
HorizontalContentAlignment="Left"
IsChecked="{Binding Path=IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}">
<ContentPresenter Content="{TemplateBinding SelectedItem}"
ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"
Margin="10,4"
VerticalAlignment="Center"
HorizontalAlignment="Left">
<ContentPresenter.Resources>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="{Binding Path=Foreground,RelativeSource={RelativeSource AncestorType={x:Type ComboBox}}}"/>
</Style>
</ContentPresenter.Resources>
<ContentPresenter.ContentTemplate>
<DataTemplate>
<TextBlock Text ="{Binding}"></TextBlock>
</DataTemplate>
</ContentPresenter.ContentTemplate>
</ContentPresenter>
</ToggleButton>
<!-- Popup for dropdown when combobox is clicked and open -->
<Popup x:Name="PART_Popup" AllowsTransparency="True"
Width="{Binding Path=ActualWidth, RelativeSource={RelativeSource TemplatedParent}}"
Placement="Bottom" IsOpen="{Binding Path=IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}}"
PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}">
<Grid MaxHeight="{TemplateBinding MaxDropDownHeight}">
<Border x:Name="Splitter" BorderThickness="0,3,0,0">
<Border.BorderBrush>
<SolidColorBrush>
<SolidColorBrush.Color>
<Color R="58" G="64" B="70" A="255"/>
</SolidColorBrush.Color>
</SolidColorBrush>
</Border.BorderBrush>
</Border>
<Grid Margin="0,3,0,0">
<Border CornerRadius="0,0,2,2" BorderThickness="1,0,1,1" x:Name="DropDownBorder"
Background="Green">
<Border.BorderBrush>
<SolidColorBrush Opacity="0.9">
<SolidColorBrush.Color>
<Color R="96" G="96" B="97" A="255"/>
</SolidColorBrush.Color>
</SolidColorBrush>
</Border.BorderBrush>
</Border>
<ScrollViewer CanContentScroll="true" HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" x:Name="Content"
KeyboardNavigation.DirectionalNavigation="Continue" HorizontalAlignment="Stretch"/>
</ScrollViewer>
</Grid>
</Grid>
</Popup>
</StackPanel>
</ControlTemplate>
in one combobox want to show formated text i.e. 1000 x 900, 200 x 300,.. and in another want to show
text like 1000 900 topology, 200 300 topology
I have formated combobox item and it shows correct value but selected value doesn't show on combobox.
how to do this using single combobox item template?
<ComboBox Grid.Row="0" ItemsSource="{Binding PossibleTopologysNew}"
SelectedItem="{Binding SelectedTopologyNew}"
Template="{StaticResource GridGenreComboboxTemplate}"
>
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Margin="10">
<TextBlock.Text>
<MultiBinding StringFormat="{}{0} x {1}">
<Binding Path="LeftNumber"/>
<Binding Path="RightNumber"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<ComboBox Grid.Row="0" ItemsSource="{Binding PossibleTopologysNew}"
SelectedItem="{Binding SelectedTopologyNew}"
Template="{StaticResource GridGenreComboboxTemplate}"
>
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Margin="10">
<TextBlock.Text>
<MultiBinding StringFormat="{}{0} {1} topology">
<Binding Path="LeftNumber"/>
<Binding Path="RightNumber"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>

Your fix is simple... just don't declare a new ControlTemplate for the ComboBox - use the default one. If you really need to provide your own ControlTemplate, then just define one that contains the TextBox used to display the selected value. If you are new to WPF, then I very much doubt that you actually need to define your own ControlTemplate.
If however, you do need to declare your own ControlTemplate, then you should start with the default one (which you can find in the ComboBox Styles and Templates page on MSDN) and slowly and carefully remove the bits that you don't need and add the new bits that you do need. However, when declaring a ControlTemplate, you have to replace like with like. For example, look at the ContentPresenter from the default ControlTemplate:
<ContentPresenter x:Name="ContentSite"
IsHitTestVisible="False"
Content="{TemplateBinding SelectionBoxItem}"
ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}"
ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"
Margin="3,3,23,3"
VerticalAlignment="Stretch"
HorizontalAlignment="Left">
Now look at yours:
<ContentPresenter
Content="{TemplateBinding SelectedItem}"
ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}"
Margin="10,4"
VerticalAlignment="Center"
HorizontalAlignment="Left">
To start with, you are attempting to data bind the ContentPresenter.Content property to a different property from the original ControlTemplate. So if I were you, I'd get rid of you non-working ControlTemplate and replace it with the original one. Ensure that it displays correctly before starting to change it and test it regularly as you continue to change it.

Related

VirtualizingPanel not Virtualizing using WPF XAML [duplicate]

This question already has answers here:
Virtualizing WPF Wrap Panel Issue
(3 answers)
Is there a virtualizing WrapPanel for WPF available? Commercial or free ones
(2 answers)
Virtualizing WrapPanel as ListView's ItemsTemplate
(3 answers)
Closed 4 years ago.
So no matter how hard I try I can't get virtualization in my view to work.
When I scroll through my Listbox, the items always keep populating from the top and carry on right to the bottom, rather than rendering what is on screen and just a bit above and bellow.
Any help would be very much appreciated.
Bellow is the code for the Viewbox. A point of note:
I am using a Viewbox inside a ListBox and a grid inside the ViewBox. This is because my items populate in a similar way to text with word warping turned on - it populates horizontally until the width, then moves on to the next line.
My items in the ListBox are scalable, and there position in the view changes dynamically depending on the scale size, whilst also, the TextBlocks text dose not scale.
Not sure if that effects virtualization in a way I am unaware.
If that is not clear, I apologise and am happy to answer any questions. Thanks for your time:
<ListBox x:Name="LibraryBox"
Grid.Column="1"
Grid.Row="0"
Grid.RowSpan="4"
Margin="0,-5,0,-10"
BorderBrush="Transparent"
Background="#1e1e1e"
ItemsSource="{Binding}"
ItemContainerStyle="{StaticResource ListBoxItemStyle}"
IsSynchronizedWithCurrentItem="True"
VirtualizingPanel.IsVirtualizing="True"
VirtualizingPanel.IsVirtualizingWhenGrouping="True"
VirtualizingPanel.IsContainerVirtualizable="True"
VirtualizingPanel.VirtualizationMode="Standard"
ScrollViewer.IsDeferredScrollingEnabled="False"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Visible"
SelectionMode="Extended"
SelectionChanged="LibraryBox_SelectionChanged"
MouseDoubleClick="LibraryBox_MouseDoubleClick">
<ListBox.Resources>
<!--#region scrollbar style-->
<Style TargetType="{x:Type ScrollBar}">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="#990000"/>
<Setter Property="Width" Value="25"/>
</Style>
<!--#endregion-->
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Red"/>
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Red"/>
</ListBox.Resources>
<ListBox.ContextMenu>
<ContextMenu>
<MenuItem Header="Edit" Click="ContextMenuItemEdit_Click"/>
<MenuItem Header="ComicVine Scraper" Click="MenuItemScraper_Click"/>
<Separator/>
<MenuItem Header="Delete" Click="ContextMenuItemDelete_Click"/>
</ContextMenu>
</ListBox.ContextMenu>
<!--#region Group Style-->
<ListBox.GroupStyle>
<GroupStyle>
<GroupStyle.ContainerStyle>
<Style TargetType="{x:Type GroupItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Expander IsExpanded="True">
<Expander.Header>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}"
FontWeight="Bold"
Foreground="#dbdbdb"
FontSize="16"
FontFamily="Cordia New"
VerticalAlignment="Bottom" />
<TextBlock Text="{Binding ItemCount}"
FontSize="16"
Foreground="#dbdbdb"
FontStyle="Italic"
Margin="10,0,0,0"
FontFamily="Cordia New"
VerticalAlignment="Bottom" />
</StackPanel>
</Expander.Header>
<ItemsPresenter />
</Expander>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</GroupStyle.ContainerStyle>
</GroupStyle>
</ListBox.GroupStyle>
<!--#endregion-->
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<Viewbox Height="100" Width="70" Margin="2">
<Viewbox.LayoutTransform>
<ScaleTransform ScaleX="{Binding Value, ElementName=ZoomSlider}"
ScaleY="{Binding Value, ElementName=ZoomSlider}"/>
</Viewbox.LayoutTransform>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="300"/>
<ColumnDefinition Width="32"/>
</Grid.ColumnDefinitions>
<!--This is for thumbnails-->
<Image x:Name="coverImage"
Grid.Column="0"
Grid.Row="0"
Source="{Binding CoverPath, Converter={StaticResource UriToBitmapConverter}, IsAsync=True}"/>
<Rectangle x:Name="ReadMarkerBottom"
Grid.Column="1"
Grid.Row="1"
Margin="-16,0,0,0"
Fill="#fff"
Width="32"
Height="32"
Loaded="CoverImage_Loaded"/>
<Rectangle x:Name="ReadMarkerTop"
Grid.Column="1"
Grid.Row="1"
Margin="-16,0,0,0"
Fill="#000"
Width="30"
Height="30"
Loaded="CoverImage_Loaded"/>
</Grid>
</Viewbox>
<TextBlock TextTrimming="CharacterEllipsis"
TextAlignment="Center"
Width="120"
Foreground="#dbdbdb"
Background="Transparent"
Margin="0,0,0,5"
Loaded="Text_Loaded"
FontFamily="Cordia New"
FontWeight="Bold">
</TextBlock>
<TextBlock TextTrimming="CharacterEllipsis"
TextAlignment="Center"
Width="120"
Foreground="#dbdbdb"
Background="Transparent"
Margin="0,0,0,5"
Loaded="IssueNumer_Loaded"
FontFamily="Cordia New"/>
<TextBlock TextTrimming="CharacterEllipsis"
TextAlignment="Center"
Width="120"
Foreground="#dbdbdb"
Background="Transparent"
Margin="0,0,0,5"
Loaded="CountStack_Loaded"
FontFamily="Cordia New"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True" Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
The answer is, as Clemens pointed out, "The ItemsPanel must support virtualization. WrapPanel does not."

Both 'ItemTemplate' and 'ItemTemplateSelector' are set; 'ItemTemplateSelector' will be ignored

Following this question, I have another question about TreeView.
What I already have is a TreeViewwith HierarchicalDataTemplate, in which I can change the HierarchicalDataTemplate of level2 (like explained in the question and the answer).
What I want now, is to change the look of the expander of the Treeview. For this, I have defined a ControlTemplate named ctForTreeViewItem, and I use it like this:
<Window.Resources>
<ControlTemplate x:Key="ctForTreeViewItem"
TargetType="{x:Type TreeViewItem}">
<Expander IsExpanded="True"
Background="Grey"
BorderBrush="Transparent"
Foreground="White"
BorderThickness="1,1,1,3">
<Expander.Header>
<Border BorderThickness="{TemplateBinding Border.BorderThickness}"
Padding="{TemplateBinding Control.Padding}"
BorderBrush="{TemplateBinding Border.BorderBrush}"
Background="{TemplateBinding Panel.Background}"
Name="Bd"
SnapsToDevicePixels="True"
Grid.Column="1">
<ContentPresenter Content="{TemplateBinding HeaderedContentControl.Header}"
ContentTemplate="{TemplateBinding HeaderedContentControl.HeaderTemplate}"
ContentStringFormat="{TemplateBinding HeaderedItemsControl.HeaderStringFormat}"
ContentSource="Header"
Name="PART_Header"
HorizontalAlignment="{TemplateBinding Control.HorizontalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
</Border>
</Expander.Header>
<Expander.Content>
<ItemsPresenter x:Name="ItemsHost" />
</Expander.Content>
</Expander>
</ControlTemplate>
<DataTemplate x:Key="Level3Template">
<Border Background="LightBlue">
<TextBlock Text="Level3"/>
</Border>
</DataTemplate>
<HierarchicalDataTemplate x:Key="Level2RedTemplate"
ItemsSource="{Binding Value}"
ItemTemplate="{StaticResource Level3Template}">
<Border Background="Red">
<TextBlock Text="Level2"/>
</Border>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate x:Key="Level2YellowTemplate"
ItemsSource="{Binding Value}"
ItemTemplate="{StaticResource Level3Template}">
<Border Background="Yellow">
<TextBlock Text="Level2"/>
</HierarchicalDataTemplate>
<HierarchicalDataTemplate x:Key="Level1Template"
ItemsSource="{Binding Value}"
ItemTemplateSelector="{StaticResource MySelector}">
<HierarchicalDataTemplate.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<Setter Property="Template"
Value="{StaticResource ctForTreeViewItem}" />
</Style>
</HierarchicalDataTemplate.ItemContainerStyle>
<Border Background="Green">
<TextBlock Text="Level1"/>
</Border>
</HierarchicalDataTemplate>
</Window.Resources>
<TreeView Grid.Row="1"
Name="tv"
ItemsSource="{Binding Items}"
ItemTemplate="{StaticResource Level1Template}">
<TreeView.ItemContainerStyle>
<Style TargetType="TreeViewItem">
<Setter Property="Template"
Value="{StaticResource ctForTreeViewItem}" />
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
This works for Level1 as expected, so on Level 1, I have TreeViewItems with the defined ControlTemplate and the Correct HierarchicalDataTemplate.
However, it doesn't work on Level2, where I have an ItemTemplateSelector. At this position, I get this error: System.Windows.Data Error: 25 : Both 'ItemTemplate' and 'ItemTemplateSelector' are set; 'ItemTemplateSelector' will be ignored.
Is there any way, that I can assign a ControlTemplate to the TreeViewItems, while keeping the ItemTemplateSelector? Or even
Is there any other way, that I can change the style of the expander of the TreeView?
Your TreeViewItem ControlTemplate is broken. It ignores the data template selector because you explicitly override that by setting ContentTemplate on the ContentPresenter. That's similar to what's causing the (harmless) errors in your debug output stream as well: The level 2 templates inherit an ItemTemplateSelector from their ancestors, in the same way that if you set ItemContainerStyle once on the TreeView, it will be inherited by all children of the treeview unless some intervening child overrides it explicitly. No need to set it more than once. Because the level 2 templates inherit ItemTemplateSelector and override it with a different property, you get an error, but it's harmless.
I fixed the control template by changing the ContentPresenter for the Header to match the default TreeViewItem control template: I removed the Content, ContentTemplate, and ContentStringFormat attributes. The ContentPresenter has default behavior for all that stuff so you don't need to specify it explicitly.
<ContentPresenter
ContentSource="Header"
Name="PART_Header"
HorizontalAlignment="{TemplateBinding Control.HorizontalContentAlignment}"
SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}"
/>
The template/template selector errors are harmless but I was able to silence them by setting ItemTemplateSelector explicitly to null on the level 2 hierarchical data templates:
<HierarchicalDataTemplate
x:Key="Level2RedTemplate"
ItemsSource="{Binding Value}"
ItemTemplateSelector="{x:Null}"
ItemTemplate="{StaticResource Level3Template}"
>
<Border Background="Red">
<TextBlock Text="Level2"/>
</Border>
</HierarchicalDataTemplate>

WPF - Radio button control template binding "IsChecked" not working

I have a control template like below, and I want to get IsChecked property when user selects a radio button.
But when user select radio button "A" it's IsChecked property still show false. Why?
<ControlTemplate x:Key="RadioBtnTemplate" TargetType="{x:Type RadioButton}">
<Grid>
<StackPanel Margin="5">
<RadioButton Name="tempbtn" IsChecked="{TemplateBinding IsChecked}" FontFamily="Segoe UI" FontSize="18.667" Content="{TemplateBinding Content}" GroupName="{TemplateBinding GroupName}"/>
</StackPanel>
</Grid>
</ControlTemplate>
and I use this template:
<RadioButton GroupName="CG" x:Name="_rdoBtnA" Content="A" Template="{DynamicResource RadioBtnTemplate}" IsChecked="True"/>
<RadioButton GroupName="CG" x:Name="_rdoBtnB" Content="B" Template="{DynamicResource RadioBtnTemplate}" />
<RadioButton GroupName="CG" x:Name="_rdoBtnC" Content="C" Template="{DynamicResource RadioBtnTemplate}" />
If we take your example as is then you have two problems which cause the problems you are seeing.
Issue 1:
Firstly your design has created six not three <RadioButton> controls. The three in the <StackPanel> and then three that are created as part of the control template. All six radio buttons are now linked as part of the GroupName="CG" group.
As you know because they all belong to the same CG group only one of the six radio buttons can have the IsChecked property set to True. The three named controls _rdoBtnA, _rdoBtnB and _rdoBtnC are not even visible on the screen so they can never be set to True (and in the case of _rdoBtnA is promptly set to False from the XAML declared True the moment the template control is bound).
To resolve this situation, remove the GroupName="{TemplateBinding GroupName}" from the control template definition leaving only the three top level radio buttons in the group.
Issue 2: This is the issue I thought was the root of your problem to begin with. IsChecked={TemplateBinding IsChecked} is only OneWay binding and will not update the other way. To make the binding TwoWay you need to use the long-hand version of the binding definition, IsChecked="{Binding IsChecked, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"
The control template now becomes this by making those two changes.
<ControlTemplate x:Key="RadioBtnTemplate" TargetType="{x:Type RadioButton}">
<Grid>
<StackPanel Margin="5">
<RadioButton Name="tempbtn" IsChecked="{Binding IsChecked, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" FontFamily="Segoe UI" FontSize="18.667" Content="{TemplateBinding Content}" />
</StackPanel>
</Grid>
</ControlTemplate>
you can use it this way:
<StackPanel Orientation="Horizontal">
<StackPanel.Resources>
<ControlTemplate x:Key="ButtonAsSwatchTemplate">
<Border x:Name="SwatchBorder" BorderThickness="1">
<Rectangle Fill="{TemplateBinding Property=Background}" Width="15" Height="15" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="ToggleButton.IsChecked" Value="True">
<Setter TargetName="SwatchBorder" Property="BorderBrush" Value="Yellow" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</StackPanel.Resources>
<RadioButton Template="{StaticResource ButtonAsSwatchTemplate}"
GroupName="CropGuidesColourRadioButtonGroup"
IsChecked="{Binding Checked}" Margin="2" Background="Red" />
<RadioButton Template="{StaticResource ButtonAsSwatchTemplate}"
GroupName="CropGuidesColourRadioButtonGroup"
IsChecked="{Binding Checked}" Margin="2" Background="Black" />
</StackPanel>
taken from StackOverFlow

Giving a button in a textbox functionality, without using a custom control but overiding the textbox template

I implemented a button into the textbox overriding the template with the code below:
<Style x:Key="{x:Type TextBox}" TargetType="{x:Type TextBoxBase}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBoxBase}">
<Border Name="Border"
CornerRadius="2"
Padding="2"
Background="{StaticResource WindowBackgroundBrush}"
BorderBrush="{StaticResource SolidBorderBrush}"
BorderThickness="1">
<Grid x:Name="LayoutGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<ScrollViewer x:Name="PART_ContentHost" Grid.Column="0" />
<Button x:Name="XButton"
Grid.Column="2"
Width="25"
Height="25"
Content="X"
Visibility="Visible"
BorderBrush="Transparent"
Command="{Binding ButtonClick}" />
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The button should delete all the content in the textbox when hit. For this I would like to use the command "Command="{Binding ButtonClick}""
Can the binding be done without creating a custom control and library ?
Or how can the binding or the functionality be done ?
I am using the MVVM pattern is there a way to for example use a ViewModel and create a property to bind that to ?
For bindings in the style like that I use AttachedCommandBehaviors "ACB"
http://marlongrech.wordpress.com/2008/12/13/attachedcommandbehavior-v2-aka-acb/
I use it for detecting clicks on items in a style that I want to detect clicks on. I haven't used it for buttons but I would think it should work just as well.
I am binding to the style's ancestor who's type is User Control this may need to be changed for your application.
You'll need to add the xmlns:acb namespace in your xaml as well see the link for details.
<ControlTemplate TargetType="{x:Type ListViewItem}">
<StackPanel x:Name="IconBorder"
acb:CommandBehavior.Event="PreviewMouseUp"
acb:CommandBehavior.Command="{Binding Path=DataContext.SelectedListItemSingleClickCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}}"
acb:CommandBehavior.CommandParameter="{Binding}">
<DockPanel LastChildFill="False" HorizontalAlignment="Left" Width="{Binding Width, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListViewItem}}}">
<TextBlock Text="{Binding Title}"
DockPanel.Dock="Left"
x:Name="ListItemText" />
<Image x:Name="ActionIcon"
Source="{Binding Path=DataContext.SelectedListActionIcon, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}}"
DockPanel.Dock="Right"
acb:CommandBehavior.Event="PreviewMouseUp"
acb:CommandBehavior.Command="{Binding Path=DataContext.SelectedListActionIconClickCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}}"
acb:CommandBehavior.CommandParameter="{Binding}">
</Image>
</DockPanel>
<ContentPresenter DockPanel.Dock="Left" />
</StackPanel>
</ControlTemplate>

Customize a TextBlock in WPF

I need to "decorate" a textBlock with a custom background (say, when IsSelected)
Actually I have two separate elements textBlock and its background rectangle:
<TextBlock x:Name="StopText" Text="Eiffel Tower"
Canvas.Left="17"
FontSize="14"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
FontFamily="Giddyup Std"
Canvas.Top="-16"
Padding="5">
</TextBlock>
<Rectangle x:Name="ShadowRectangle"
Fill="SkyBlue"
Canvas.Left="18"
Width="{Binding ElementName=StopText, Path=ActualWidth}"
Height="{Binding ElementName=StopText, Path=ActualHeight}"
RadiusX="5" RadiusY="5" Opacity="0.2" Canvas.Top="-17"
LayoutTransform="{Binding ElementName=StopText, Path=LayoutTransform}"/>
Now, when I want to Hide the textBlock I need to hide the rectangle too, etc. I think there is should be a more elegant way to do it.
Any remarks appreciated.
EDIT
Border approach
<Border x:Name="ShadowRectangle"
Background="Transparent"
Canvas.Left="18"
Canvas.Top="-17"
CornerRadius="5"
Opacity="0.2"
LayoutTransform="{Binding ElementName=StopText,
Path=LayoutTransform}">
<TextBlock x:Name="StopText" Text="Eiffel Tower"
FontSize="14" VerticalAlignment="Stretch"
HorizontalAlignment="Stretch" FontFamily="Giddyup Std"
Canvas.Top="-16" Padding="5">
</TextBlock>
</Border>
In a solution similar to your border approach, if you want no dependencies between the opacity of the border and the textblock, you could go with something like this:
<grid>
<rectangle />
<textblock />
<grid>
this should put the textblock over the rectangle since they are on the same grid cell.
They you only have to change the Rectangle.Fill when it's selected. You could do that using a DataTrigger on the Rectangle style.
You can make a Custom Control instead.
Here is a link for some ideers:
http://www.codeguru.com/cpp/i-n/internet/xml/article.php/c12521
Bind the visibility property for both the textblock and Rectangle to a bool in your viewmodel and use the BoolToVisibilityConverter to convert the bool value to a visibility value. Your XAML will look something like this:
<TextBlock x:Name="StopText" Text="Eiffel Tower"
Canvas.Left="17"
FontSize="14"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
FontFamily="Giddyup Std"
Canvas.Top="-16"
Padding="5"
Visibility="{Binding IsVis, Converter={StaticResource BooleanToVisibilityConverter}}">
</TextBlock>
<Rectangle x:Name="ShadowRectangle"
Fill="SkyBlue"
Canvas.Left="18"
Width="{Binding ElementName=StopText, Path=ActualWidth}"
Height="{Binding ElementName=StopText, Path=ActualHeight}"
RadiusX="5" RadiusY="5" Opacity="0.2" Canvas.Top="-17"
Visibility="{Binding IsVis, Converter={StaticResource BooleanToVisibilityConverter}}"/>
Using either the Border or Rectangle approach, you should be able to bind the Visibility of the decorator (Border or Rectangle) to the Visibility of the TextBlock.
<TextBlock x:Name="StopText" Text="Eiffel Tower"
Canvas.Left="17"
FontSize="14"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
FontFamily="Giddyup Std"
Canvas.Top="-16"
Padding="5">
</TextBlock>
<Rectangle x:Name="ShadowRectangle"
Fill="Red"
Canvas.Left="18"
Width="{Binding ElementName=StopText, Path=ActualWidth}"
Height="{Binding ElementName=StopText, Path=ActualHeight}"
RadiusX="5" RadiusY="5" Opacity="0.2" Canvas.Top="-17"
LayoutTransform="{Binding ElementName=StopText, Path=LayoutTransform}"
Visibility="{Binding ElementName=StopText}"/>
Let me suggest to use templated label (textblock wont accept templates and took more characters to type -). For your convenience, I wrapped it in a style:
<Window x:Class="_4203457.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Style TargetType="{x:Type Label}">
<Setter Property="FontSize" Value="14"/>
<Setter Property="FontFamily" Value="Giddyup Std"/>
<Setter Property="Padding" Value="5"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Label}">
<Grid>
<TextBlock Text="{TemplateBinding Content}"
FontSize="14"
Padding="5"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
FontFamily="Giddyup Std"
/>
<Rectangle x:Name="ShadowRectangle"
Fill="SkyBlue"
RadiusX="5" RadiusY="5" Opacity="0.5"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Grid Height="27" Width="454">
<Label Content="Eiffel Tower"/>
</Grid>

Resources