How to overlay items in StackPanel or ListView? - c#

I am making a card game and I want to display cards in player's hand half-covered be each other. How can I do that using ListView or StackPanel? Here is an example how I would like to display player hand.
<Grid Background="Green" >
<Image x:Name="One" Width="100" Height="100" Margin="10,10,250,210"/>
<Image x:Name="Two" Width="100" Height="100" Margin="10,10,210,210"/>
</Grid>
UPDATE
I set margins for ListView's ItemContainerStyle and it worked, but I have another problem. Width of ListView items doesn't fit the image and there is some spacing. How do I remove that. See image below the XAML code.
<ListView Grid.Row="0" Grid.Column="0">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Margin" Value="0, 0, -80, 0"></Setter>
<Setter Property="Height" Value="100"></Setter>
<Setter Property="Width" Value="100"></Setter>
</Style>
</ListView.ItemContainerStyle>
<Image x:Name="One" MaxWidth="100" Height="100" />
<Image x:Name="Two" MaxWidth="100" Height="100" />
</ListView>

I would use Canvas in the list, and draw your card to the canvas, because things drawn in a canvas are not clipped, and instead managed through the canvas ZIndex etc.
Size the canvas based on your desired spacing, and oversize the contents. I'd also recommend binding to Items-source when using listboxes and using templates.
BTW I'm defining my cards using solidColorBrushes so I can just draw rectangles, replace this with your image source. I've defined my source in the resources, but in reality it would be bound to an ObservableCollection (Say, PlayersCurrentHand or something):
<UserControl.Resources>
<x:Array Type="{x:Type SolidColorBrush}" x:Key="Cards">
<SolidColorBrush Color="Blue"/>
<SolidColorBrush Color="Red"/>
<SolidColorBrush Color="White"/>
<SolidColorBrush Color="White"/>
<SolidColorBrush Color="White"/>
<SolidColorBrush Color="White"/>
</x:Array>
</UserControl.Resources>
Now, I presume you are using ListBox because you want to support selection? If so, the way WPF highlights list box items will mess up with this overlap, so we will need to replace it. If you don't want selection, just use an itemsControl and you can skip all the selection stuff.
Here's our basic listbox:
<ListView ItemsSource="{StaticResource Cards}" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="112,98,-325,-25" Width="513" Height="227">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" IsItemsHost="True" VerticalAlignment="Top"/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Black" BorderThickness="1">
<Rectangle Fill="{Binding}" Width="60" Height="100"/>
</Border>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Which gives us this:
Now, we want to have all the list items to be drawn in a canvas, so let's define our ItemContainerStyle:
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<StackPanel>
<Canvas Width="15" Height="100">
<ContentPresenter />
</Canvas>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
See how we've set the canvas Width to 15? That defines the spacing of our cards. All the canvases are stacked at intervals of 15. However, the Rectangles we are drawing in our DateTemplate is Width 60, so these spill off to the right.
We've overridden the messy standard selection and highlighting styles. But no we don't know what's highlighted and selected, so let's add some functionality back in. We can also add things like shadows etc:
<ControlTemplate TargetType="{x:Type ListViewItem}">
<StackPanel>
<Canvas Width="15" Height="100">
<Rectangle x:Name="Highlight" Width="60" Height="5" Canvas.Top="105"/>
<Rectangle Fill="#50000000" Width="60" Height="100" Margin="5,0,-5,0"/>
<ContentPresenter />
</Canvas>
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Highlight" Property="Fill" Value="Yellow"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Panel.ZIndex" Value="99"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
So now we have this:
Note, the gif didn't render the selection exactly right. The width issue is going to be tricky to fix without some code behind I think. One option is to make an IValueConverter that calculates width given the List of cards, and binding it to the Listview's Width property.
Edit
Found a way to get around the size issue! Padding! Of course. However, I found the scroll viewer clips even the canvas it contains (which makes sense if you think about it) but leaves all our effort hidden:
So you have to overwrite the scroll viewer functionality by setting the ControlTemplate manually:
<ListBox.Template>
<ControlTemplate>
<Border Padding="5,25,55,15" BorderBrush="Gray" BorderThickness="1">
<ItemsPresenter />
</Border>
</ControlTemplate>
</ListBox.Template>
So now the padding accounts for the last card sticking out an extra 50.
Total code, with some more visual tweaks:
<ListView ItemsSource="{StaticResource Cards}" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="20" BorderBrush="Black">
<ListBox.Template>
<ControlTemplate>
<Border Padding="5,25,55,15" BorderBrush="Gray" BorderThickness="1">
<ItemsPresenter />
</Border>
</ControlTemplate>
</ListBox.Template>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" IsItemsHost="True" ClipToBounds="False" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<StackPanel>
<Canvas Width="15" Height="100">
<Rectangle x:Name="Highlight" Width="60" Height="5" Canvas.Top="105"/>
<ContentPresenter x:Name="CardPresenter"/>
</Canvas>
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Panel.ZIndex" Value="99"/>
<Setter TargetName="CardPresenter" Property="Canvas.Top" Value="-5"/>
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Highlight" Property="Fill" Value="Yellow"/>
<Setter TargetName="CardPresenter" Property="Canvas.Top" Value="-20"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Border Background="#60000000" BorderThickness="0" CornerRadius="5" Height="100" Margin="5,0,-5,0"/>
<Border BorderBrush="Black" BorderThickness="1" CornerRadius="5" Background="{Binding}" Width="60" Height="100"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
It's pretty flexible, it was easy to add the "sticking out" functionality. Animations would be the next big step.
Edit 2
I'm just playing now. I'm not sure I like the "jump to the front" functionality, would be better if they just peeked out. Also, fanning them out (using a multi-binding):
Using the following template:
<ControlTemplate TargetType="{x:Type ListViewItem}">
<StackPanel>
<Canvas Width="15" Height="100">
<Rectangle x:Name="Highlight" Width="60" Height="5" Canvas.Top="105"/>
<ContentPresenter x:Name="CardPresenter">
<ContentPresenter.RenderTransform>
<TransformGroup>
<TranslateTransform x:Name="TranslateTransformHighlight"/>
<RotateTransform x:Name="RotateTransformHighlight" CenterY="100"/>
<TranslateTransform x:Name="TranslateTransformSelect"/>
</TransformGroup>
</ContentPresenter.RenderTransform>
</ContentPresenter>
</Canvas>
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True" >
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="TranslateTransformHighlight" Duration="0:0:0.200" To="-5" Storyboard.TargetProperty="Y" />
<DoubleAnimation Storyboard.TargetName="RotateTransformHighlight" Duration="0:0:0.200" To="-5" Storyboard.TargetProperty="Angle" />
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="TranslateTransformHighlight" Duration="0:0:0.200" To="0" Storyboard.TargetProperty="Y" />
<DoubleAnimation Storyboard.TargetName="RotateTransformHighlight" Duration="0:0:0.200" To="0" Storyboard.TargetProperty="Angle" />
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="Highlight" Property="Fill" Value="Yellow"/>
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="TranslateTransformSelect" Duration="0:0:0.200" To="-15" Storyboard.TargetProperty="Y" />
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="TranslateTransformSelect" Duration="0:0:0.200" To="0" Storyboard.TargetProperty="Y" />
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>

Related

How to use behaviors in Universal Windows Platform?

I'm trying to add behaviors for my card game, but don't understand how to use them in proper way - where to put the behavior etc.
I have a listbox of cards (cards are loaded from images) and want to move card up when its clicked and move down when its clicked again.
Can anyone suggest me guide on how to use behaviors in UWP apps or give me an example on my code ( which is not working:( ).
<Page.Resources>
<Storyboard x:Key="storyboard1" >
</Storyboard>
</Page.Resources>
<ListView x:Name="list" Grid.Row="0" Grid.Column="0" Padding="50,0" ScrollViewer.VerticalScrollBarVisibility="Disabled" VerticalAlignment="Center" HorizontalContentAlignment="Stretch" ItemClick="ListView_ItemClick" >
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Margin" Value="0,0,-70,0"></Setter>
<Setter Property="MaxHeight" Value="100"></Setter>
<Setter Property="MaxWidth" Value="68"></Setter>
<Setter Property="Padding" Value="0,0,0,0"></Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<ListViewItemPresenter>
<interactivity:Interaction.Behaviors>
<interactions:EventTriggerBehavior EventName="GotFocus">
<media:ControlStoryboardAction Storyboard="{StaticResource storyboard1}">
</media:ControlStoryboardAction>
</interactions:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</ListViewItemPresenter>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
<ListViewItem>
</ListViewItem>
<Image x:Name="One" MaxWidth="68" Height="100" >
<interactivity:Interaction.Behaviors>
<interactions:EventTriggerBehavior>
<media:ControlStoryboardAction Storyboard="{StaticResource storyboard1}">
</media:ControlStoryboardAction>
</interactions:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</Image>
<Image x:Name="Two" MaxWidth="68" Height="100" />
<Image x:Name="Three" MaxWidth="68" Height="100" />
</ListView>

How to customize Pivot headers?

I am new to Windows phone 8.1 app development, I want to know how to customize the pivot header with properties like Font, Foreground Colour, Size, etc. I can't find any of these properties. So, hope someone will help me.
Create a Resource Dictionary ( if you don't have one )
Add-New Item-Resource Dictionary
Apply it on your App.XAML
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!--
Styles that define common aspects of the platform look and feel
Required by Visual Studio project and item templates
-->
<ResourceDictionary Source="Assets/Style/CustomStyle.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
Add this template to your Resource Dictionary
<Style x:Key="CustomPivotStyle" TargetType="Pivot">
<Setter Property="Margin" Value="0,0,0,0"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="Foreground" Value="{ThemeResource PhoneForegroundBrush}"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderBrush" Value="#FF1F1F1F"/>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<Grid/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Pivot">
<Grid x:Name="RootElement"
Background="{TemplateBinding Background}"
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
VerticalAlignment="{TemplateBinding VerticalAlignment}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="Orientation">
<VisualState x:Name="Portrait">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Margin" Storyboard.TargetName="TitleContentControl">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource PivotPortraitThemePadding}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentControl x:Name="TitleContentControl" ContentTemplate="{TemplateBinding TitleTemplate}" Content="{TemplateBinding Title}" Style="{StaticResource PivotTitleContentControlStyle}"/>
<ScrollViewer x:Name="ScrollViewer" HorizontalSnapPointsAlignment="Center" HorizontalSnapPointsType="MandatorySingle" HorizontalScrollBarVisibility="Hidden" Margin="{TemplateBinding Padding}" Grid.Row="1" Template="{StaticResource ScrollViewerScrollBarlessTemplate}" VerticalSnapPointsType="None" VerticalScrollBarVisibility="Disabled" VerticalScrollMode="Disabled" VerticalContentAlignment="Center" ZoomMode="Disabled">
<PivotPanel x:Name="Panel" VerticalAlignment="Stretch">
<PivotHeaderPanel x:Name="Header"
Background="{TemplateBinding BorderBrush}">
<PivotHeaderPanel.RenderTransform>
<CompositeTransform x:Name="HeaderTranslateTransform" TranslateX="0"/>
</PivotHeaderPanel.RenderTransform>
</PivotHeaderPanel>
<ItemsPresenter x:Name="PivotItemPresenter">
<ItemsPresenter.RenderTransform>
<TranslateTransform x:Name="ItemsPresenterTranslateTransform" X="0"/>
</ItemsPresenter.RenderTransform>
</ItemsPresenter>
</PivotPanel>
</ScrollViewer>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="TextBlock"
x:Key="CustomPivotHeader">
<Setter Property="FontSize" Value="20"/>
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="FontFamily" Value="Segoe UI"/>
<Setter Property="Margin" Value="10,10,0,0"/>
<Setter Property="VerticalAlignment" Value="Bottom"/>
</Style>
Apply it to your pivot
<Pivot x:Name="pivot"
Margin="0,0,0,0"
Style="{StaticResource CustomPivotStyle}">
<Pivot.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" Style="{StaticResource CustomPivotHeader}"/>
</DataTemplate>
</Pivot.HeaderTemplate>
</Pivot>
I'm using following code for my windows phone app, Brain Lightener. It should work :)
<phone:Pivot Foreground="#4b240a" FontFamily="Comic Sans MS">
<phone:Pivot.Title>
<TextBlock Text="Brain Lightener" FontFamily="Comic Sans MS" FontWeight="Bold"></TextBlock>
</phone:Pivot.Title>
<!--Pivot item one-->
<phone:PivotItem>
<phone:PivotItem.Header>
<TextBlock Text="Test" FontFamily="Comic Sans MS"></TextBlock>
</phone:PivotItem.Header>
</phone:PivotItem>
</phone:Pivot>
You don't have to change/code much for decorating your pivot page ;)

Mouseover-trigger on Slider Template

I'm changing the Standard WPF Slider's template. And I want it where you move your mouse over the area the slider occupies and the thumb starts an animation to change its size, even if the cursor isn't directly on top of the thumb.
But I don't know how to bind to a parent like that.
I'll try to post what I got without making it look nasty. Here's what I got that's relevant (I think. If you need more, tell me)
<ControlTemplate x:Key="SliderHorizontal" TargetType="{x:Type Slider}" x:Name="SliderHorizontal">
<Track x:Name="PART_Track" Grid.Row="1">
<Track.DecreaseRepeatButton>
<RepeatButton Command="{x:Static Slider.DecreaseLarge}" Style="{StaticResource LeftRepeatButtonTransparent}">
</RepeatButton>
</Track.DecreaseRepeatButton>
<Track.IncreaseRepeatButton>
<RepeatButton Command="{x:Static Slider.IncreaseLarge}" Style="{StaticResource RightRepeatButtonTransparent}"/>
</Track.IncreaseRepeatButton>
<Track.Thumb>
<Thumb x:Name="Thumb" Focusable="False" Height="20" OverridesDefaultStyle="True" Template="{StaticResource SliderThumbHorizontalDefault}" VerticalAlignment="Center" Width="Auto" Margin="0,0,-5.5,0">
</Thumb>
</Track.Thumb>
</Track>
</Grid>
</Border>
<ControlTemplate.Triggers>
triggers galore
</ControlTemplate.Triggers>
</ControlTemplate>
And here is the template for the thumb itself. It's the ellipse grip I want to change the size of.
<ControlTemplate x:Key="SliderThumbHorizontalDefault" TargetType="{x:Type Thumb}">
<Ellipse x:Name="grip" Fill="White" Height="15" Width="15" Effect="{StaticResource z-depth1}">
</Ellipse>
<ControlTemplate.Triggers>
more triggers
</ControlTemplate.Triggers>
</ControlTemplate>
How would I go about doing this binding?
Any help would be appreciated!!
Within the RenderTransform block I would add a scaleTransform
<Style x:Key="HorizontalSliderThumbStyle" TargetType="{x:Type Thumb}">
.....
.....
<ControlTemplate TargetType="{x:Type Thumb}">
<Canvas x:Name="canvas" SnapsToDevicePixels="true">
<Canvas.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="1" ScaleY="1"/>
<TranslateTransform X="5.5" Y="11"/>
</TransformGroup>
</Canvas.RenderTransform>
Then within the control template's triggers I would add the scaling up of the canvas.
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Trigger.EnterActions>
<BeginStoryboard Name="EnlargeThumb">
<Storyboard TargetName="canvas"
TargetProperty="RenderTransform.Children[1].ScaleX" >
<DoubleAnimation To="2" Duration="0:0:0" />
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<StopStoryboard BeginStoryboardName="EnlargeThumb" />
</Trigger.ExitActions>
</Trigger>
Note the style and what not that I got is from the template extracted via visual studio.

WPF Selected ListBoxItem with custom border

I'm trying to create a ListBoxItem template, that will be with rounded border at selection.
I got this xaml, which doesn't work on selection:
<ListBox x:Name="filtersListBox" Grid.Row="1"
Background="Transparent" BorderThickness="0"
ItemsSource="{Binding FilterItems}">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent"/>
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Transparent"/>
</Style.Resources>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid HorizontalAlignment="Center">
<Border CornerRadius="8" BorderThickness="0" BorderBrush="Orange"
Margin="2" Background="Transparent" Name="itemBorder"
Width="275" VerticalAlignment="Center"
FocusManager.IsFocusScope="True" Focusable="True">
<Border.Effect>
<DropShadowEffect BlurRadius="1" ShadowDepth="2" Color="DarkOrange" Opacity="0.3"/>
</Border.Effect>
<Border.Style>
<Style TargetType="Border">
<Style.Triggers>
<Trigger Property="UIElement.IsFocused" Value="True">
<Setter Property="Background" Value="Blue"/>
</Trigger>
<EventTrigger RoutedEvent="Border.MouseEnter">
<BeginStoryboard>
<Storyboard>
<ThicknessAnimation Duration="0:0:0.25"
To="2"
Storyboard.TargetProperty="BorderThickness"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="Border.MouseLeave">
<BeginStoryboard>
<Storyboard>
<ThicknessAnimation Duration="0:0:0.25"
To="0"
Storyboard.TargetProperty="BorderThickness"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<TextBlock Text="{Binding Text}" Margin="10, 2"/>
</Border>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
So this is the ListBox that I'm working on.
The MouseEnter and MouseLeave events, work great!
However, the trigger of UIElement.IsFocused is not working.
Any advice would be very appreciated! :)
Thanks, Alex.
This is so easy to do, I'm quite surprised that nobody suggested this yet. Either define two DataTemplates or two ControlTemplates, one for the default look and one for the selected look. Then just add this Style (this first example uses DataTemplates):
<Style x:Key="SelectionStyle" TargetType="{x:Type ListBoxItem}">
<Setter Property="ContentTemplate" Value="{StaticResource DefaultTemplate}" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="ContentTemplate" Value="{StaticResource SelectedTemplate}" />
</Trigger>
</Style.Triggers>
</Style>
You would use it like this:
<ListBox ItemContainerStyle="{StaticResource SelectionStyle}" ... />
Here is the other example using two ControlTemplates (used in the same way):
<Style x:Key="SelectionStyle" TargetType="{x:Type ListBoxItem}">
<Setter Property="Template" value="{StaticResource DefaultTemplate}" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Template" value="{StaticResource SelectedTemplate}" />
</Trigger>
</Style.Triggers>
</Style>
I'll leave you to define what you want the items to look like as you know that best. One last note... if you use this method (using ControlTemplates), make sure that you add a ContentPresenter so that the content of the items will still be shown. See the Control.Template Property page on MSDN for an example.
Have you tried setting Focusable property to true. By default the propery is false.
Take a look at this link:
http://msdn.microsoft.com/en-us/library/system.windows.uielement.focusable%28v=vs.110%29.aspx
If that doesnt help then maybe this approach will fit you more.
<ListBox.Resources>
<Style TargetType="{x:Type ListBoxItem}">
<EventSetter Event="GotFocus" Handler="ListBoxItem_GotFocus"/>
<EventSetter Event="LostFocus" Handler="ListBoxItem_LostFocus"/>
</Style>
</ListBox.Resources>
Why dont you set the Template for ItemContainerStyle, then you can use the Trigger with property IsSelected = true. See code below:
<Window x:Class="WpfApplication7.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib"
xmlns:collections="clr-namespace:System.Collections;assembly=mscorlib"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<collections:ArrayList x:Key="StringArray">
<system:String>Hei</system:String>
<system:String>Hei</system:String>
<system:String>Hei</system:String>
<system:String>Hei</system:String>
</collections:ArrayList>
</Window.Resources>
<Grid>
<ListBox x:Name="filtersListBox" Grid.Row="1"
Background="Transparent" BorderThickness="0"
ItemsSource="{StaticResource StringArray}">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border CornerRadius="8" BorderThickness="0" BorderBrush="Orange"
Margin="2" Background="Transparent" Name="itemBorder"
Width="275" VerticalAlignment="Center"
FocusManager.IsFocusScope="True" Focusable="True">
<Border.Effect>
<DropShadowEffect BlurRadius="1" ShadowDepth="2" Color="DarkOrange" Opacity="0.3"/>
</Border.Effect>
<ContentPresenter />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="itemBorder" Property="Background" Value="Blue"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent"/>
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Transparent"/>
</Style.Resources>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid HorizontalAlignment="Center">
<Border CornerRadius="8" BorderThickness="0" BorderBrush="Orange"
Margin="2" Background="Transparent" Name="itemBorder"
Width="275" VerticalAlignment="Center"
FocusManager.IsFocusScope="True" Focusable="True">
<Border.Effect>
<DropShadowEffect BlurRadius="1" ShadowDepth="2" Color="DarkOrange" Opacity="0.3"/>
</Border.Effect>
<Border.Style>
<Style TargetType="Border">
<Style.Triggers>
<Trigger Property="UIElement.IsFocused" Value="True">
<Setter Property="Background" Value="Blue"/>
</Trigger>
<EventTrigger RoutedEvent="Border.MouseEnter">
<BeginStoryboard>
<Storyboard>
<ThicknessAnimation Duration="0:0:0.25"
To="2"
Storyboard.TargetProperty="BorderThickness"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="Border.MouseLeave">
<BeginStoryboard>
<Storyboard>
<ThicknessAnimation Duration="0:0:0.25"
To="0"
Storyboard.TargetProperty="BorderThickness"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Style.Triggers>
</Style>
</Border.Style>
<TextBlock Text="{Binding }" Margin="10, 2"/>
</Border>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>

WPF Storyboard - Offset Textblock

I'm new to WPF and have been looking at a lot of articles and videos but I've been unable to find a solution. What I have is a button which displays an image and text within a stackpanel. I would like to make ONLY the textblock move one pixel to the right and down when the button is pressed but I cant seem to figure out a way to target only the TextBlock. Any help would be greatly appreciated. THANKS
<Style x:Key="appFlatButtonLarge" TargetType="{x:Type localUI:ImageButton}">
<Setter Property="SnapsToDevicePixels" Value="true"/>
<Setter Property="OverridesDefaultStyle" Value="true"/>
<Setter Property="MinHeight" Value="23"/>
<Setter Property="MinWidth" Value="75"/>
<Setter Property="Foreground" Value="{StaticResource appPrimaryBackColorDark}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type localUI:ImageButton}">
<Border Name="Border" BorderBrush="LightGray" BorderThickness="1" Background="White" >
<StackPanel Name="Panel" Height="Auto" Orientation="Horizontal" Background="Transparent">
<Image Name="ibImage" Source="{TemplateBinding ImageSource}" Margin="5" Width="Auto" Height="Auto" Stretch="None" RenderOptions.BitmapScalingMode="NearestNeighbor" RenderOptions.EdgeMode="Aliased"/>
<TextBlock Name="ibTextBlock" Text="{TemplateBinding Content}" HorizontalAlignment="Left" FontWeight="Bold" Margin="5,0,0,0" VerticalAlignment="Center" FontSize="12" />
</StackPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsKeyboardFocused" Value="true">
<Setter TargetName="Border" Property="BorderBrush" Value="{StaticResource appPrimaryBackColorDark}" />
</Trigger>
<Trigger Property="IsMouseOver" Value="true">
<Setter TargetName="Panel" Property="Background" Value="{StaticResource appButtonBackColorPressed}" />
<Setter TargetName="Border" Property="BorderBrush" Value="{StaticResource appPrimaryBackColorDark}" />
<Setter TargetName="ibImage" Property="Source" Value="{Binding Path=ImageSourceHot, RelativeSource={RelativeSource AncestorType={x:Type localUI:ImageButton}} }" />
</Trigger>
<Trigger Property="IsPressed" Value="true">
<Setter TargetName="Border" Property="BorderBrush" Value="Green" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Just use a TranslateTransform animation. make sure to use RenderTransform and not LayoutTransform as LayoutTransform will actually change the Layout which might not be desirable when the parent of your TextBlock and Image is a StackPanel
So in your Style if I switch the ControlTemplate definition to:
<ControlTemplate TargetType="{x:Type localUI:ImageButton}">
<Border x:Name="Border"
Background="White"
BorderBrush="LightGray"
BorderThickness="1">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver" />
<VisualState x:Name="Pressed">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="ibTextBlock"
Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
<EasingDoubleKeyFrame KeyTime="0"
Value="5" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="ibTextBlock"
Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)">
<EasingDoubleKeyFrame KeyTime="0"
Value="5" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<StackPanel x:Name="Panel"
Height="Auto"
Background="Transparent"
Orientation="Horizontal">
<Image Name="ibImage"
Width="Auto"
Height="Auto"
Margin="5"
RenderOptions.BitmapScalingMode="NearestNeighbor"
RenderOptions.EdgeMode="Aliased"
Source="{TemplateBinding ImageSource}"
Stretch="None" />
<TextBlock x:Name="ibTextBlock"
Margin="5,0,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
FontSize="12"
FontWeight="Bold"
RenderTransformOrigin="0.5,0.5"
Text="{TemplateBinding Content}">
<TextBlock.RenderTransform>
<TransformGroup>
<ScaleTransform />
<SkewTransform />
<RotateTransform />
<TranslateTransform />
</TransformGroup>
</TextBlock.RenderTransform>
</TextBlock>
</StackPanel>
</Border>
<ControlTemplate.Triggers>
...
you should get what you're after.
Note
In both the Animation steps I've set
<EasingDoubleKeyFrame KeyTime="0" Value="5" />
you can change the Value to "1" or whatever you desire.
You could change the Margin-Property of your TextBlock with the same trigger that changes the BorderBrush.
Say you set Margin = "2,2,2,2" initially, and then you set it to "3,2,1,2" when the button is pressed.
Your TextBlock will 'move' by 1/96 inch (usually, you don't pixel in WPF).
You can also use negative margins, if needed.

Categories