I have LongListSelector with GroupHeaderTemplate and ItemTemplate.
I would like to add 'Selected' effect on selected item in group. For example my element called RightArrow can go grey (now it's blue).
I was trying to do that with Expression Blend but effect didn't apply on selected item, but on every item.
<phone:LongListSelector x:Name="longListSelectorState" RenderTransformOrigin="-0.893,0.033" ItemTemplate="{StaticResource StateItemTemplate}" JumpListStyle="{StaticResource StateJumpListStyle}" LayoutMode="List" IsGroupingEnabled="true" HideEmptyGroups ="true" GroupHeaderTemplate="{StaticResource StateGroupHeaderTemplate}" Style="{StaticResource LongListSelectorStyle}"/>
<Style x:Key="LongListSelectorStyle" TargetType="phone:LongListSelector">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="{StaticResource PhoneForegroundBrush}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="phone:LongListSelector">
<Grid Background="{TemplateBinding Background}" d:DesignWidth="480" d:DesignHeight="800">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="ScrollStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="00:00:00.5"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="Scrolling">
<Storyboard>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="VerticalScrollBar"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Selected">
<Storyboard>
<DoubleAnimation Duration="0" To="48" Storyboard.TargetProperty="(Control.FontSize)"
Storyboard.TargetName="textBlock" />
<ColorAnimation Duration="0" To="Red" Storyboard.TargetProperty="(Control.Foreground).(SolidColorBrush.Color)" Storyboard.TargetName="textBlock" />
</Storyboard>
</VisualState>
<VisualState x:Name="NotScrolling"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid Margin="{TemplateBinding Padding}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<ViewportControl x:Name="ViewportControl" HorizontalContentAlignment="Stretch" VerticalAlignment="Top"/>
<ScrollBar x:Name="VerticalScrollBar" Grid.Column="1" Margin="4,0,4,0" Opacity="0" Orientation="Vertical"/>
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<DataTemplate x:Key="StateItemTemplate">
<StackPanel VerticalAlignment="Top">
<Grid x:Name="grid">
<StackPanel x:Name="stackPanel" Orientation="Vertical" HorizontalAlignment="Left">
<TextBlock x:Name="textBlock" Text="{Binding ItemName}" Foreground="#DE000000" FontFamily="Segoe WP SemiLight" FontSize="29.333" Padding="0,5,0,0" Margin="4,0,0,0" />
<TextBlock x:Name="textBlock1" Text="{Binding SubItemNames}" Visibility="{Binding HasSubItems, Converter={StaticResource BoolVisibilityConverter}}" Foreground="#DE000000" FontFamily="Segoe WP SemiLight" FontSize="21.333" Padding="0,4" LineHeight="2.667" />
</StackPanel>
<Ellipse x:Name="RightArrow" Visibility="{Binding HasSubItems, Converter={StaticResource BoolVisibilityConverter}}" Fill="#FF0202EA" Stroke="Black" HorizontalAlignment="Right" Width="44" Height="44"/>
</Grid>
</StackPanel>
</DataTemplate>
From what I see the problem is that you are applying the storyboard to the whole LongListSelector control instead of the single item. Your VisualStateManager should be placed into a ItemTemplate (DataTemplate).
Unluckily it seems that no hooks are provided from the box, so you'll have to manually manage your item state using VisualStateManager.GoToState method.
First of all you should remove the storyboard assigned to the Selected state of your LongListSelector as this part affects the whole list.
Then you should create simple control with two visual states: Normal and Selected.
<UserControl x:Class="PhoneApp2.CustomLongListSelectorItem"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
d:DesignHeight="480" d:DesignWidth="480">
<Grid x:Name="LayoutRoot">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="Selected">
<Storyboard>
<ColorAnimation Duration="0" To="Red"
Storyboard.TargetProperty="(Control.Foreground).(SolidColorBrush.Color)"
Storyboard.TargetName="ContentTextBlock" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<StackPanel Margin="12,12">
<TextBlock x:Name="ContentTextBlock" Text="{Binding}" TextWrapping="Wrap"/>
</StackPanel>
</Grid>
</UserControl>
Then add this control to your DataTemplate as below:
<phone:LongListSelector x:Name="ListSelector" SelectionChanged="HandleSelectionChanged">
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<phoneApp2:CustomLongListSelectorItem/>
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>
And finally you will have to add little code to the code-behind of your page that will manage the states of your custom control.
Basically you need to implement the HandleSelectionChanged method and GetItemsRecursive as a little helper to easily get control`s children.
private void HandleSelectionChanged(Object sender, SelectionChangedEventArgs e)
{
var userControlList = new List<CustomLongListSelectorItem>();
GetItemsRecursive(ListSelector, ref userControlList);
// Selected.
if (e.AddedItems.Count > 0 && e.AddedItems[0] != null)
{
foreach (var userControl in userControlList)
{
if (e.AddedItems[0].Equals(userControl.DataContext))
{
VisualStateManager.GoToState(userControl, "Selected", true);
}
}
}
// Unselected.
if (e.RemovedItems.Count > 0 && e.RemovedItems[0] != null)
{
foreach (var userControl in userControlList)
{
if (e.RemovedItems[0].Equals(userControl.DataContext))
{
VisualStateManager.GoToState(userControl, "Normal", true);
}
}
}
}
public static void GetItemsRecursive<T>(DependencyObject parents, ref List<T> objectList) where T : DependencyObject
{
var childrenCount = VisualTreeHelper.GetChildrenCount(parents);
for (int i = 0; i < childrenCount; i++)
{
var child = VisualTreeHelper.GetChild(parents, i);
if (child is T)
{
objectList.Add(child as T);
}
GetItemsRecursive(child, ref objectList);
}
}
The code provided above is mostly from this sample Highlight a selected item in the LongListSelector on WP8. It might be slightly different from the sample as I wanted to make sure this will work properly.
Related
I'm using the following GridView and have an ItemTemplate with 3 Elements inside.
Now what i would like to do, is to animate the MyTextBlock opacity on PointerOver from the GridViewItem.
<GridView x:Name="MyList" ItemContainerStyle="{StaticResource GridViewItemContainerStyle}" ItemsSource="{Binding MyList}">
<GridView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="200" />
<RowDefinition Height="3" />
<RowDefinition Height="80" />
</Grid.RowDefinitions>
<Image Grid.Row="0" Source="{Binding Url}" />
<ProgressBar Grid.Row="1" IsIndeterminate="True" />
<TextBlock Name="MyTextBlock" Opacity="0" Text="Test" />
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
The ItemContainerStyle is like this. Problem is, i can't access MyTextBlock with Storyboard.TargetName="MyTextBlock" from here since it's inside the ContentPresenter.
How can i do a visualstate animation of an element inside the ContentPresenter?
<Style TargetType="GridViewItem" x:Key="GridViewItemContainerStyle">
...
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="GridViewItem">
<Grid x:Name="ContentBorder" Control.IsTemplateFocusTarget="True" RenderTransformOrigin="0.5,0.5">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal">
<Storyboard>
<PointerUpThemeAnimation Storyboard.TargetName="ContentPresenter" />
</Storyboard>
</VisualState>
<VisualState x:Name="PointerOver">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="BorderRectangle" Storyboard.TargetProperty="Opacity" Duration="0" To="1" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Rectangle x:Name="BorderRectangle" Fill="{ThemeResource SystemControlHighlightListAccentLowBrush}" Opacity="0" />
<ContentPresenter x:Name="ContentPresenter" ContentTransitions="{TemplateBinding ContentTransitions}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Margin="{TemplateBinding Padding}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Edit:
I tried using the following TargetProperty, but it's just setting the opacity of the whole ContentPresenter
and not just TextBlock inside of it.
<DoubleAnimation Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="(TextBlock.Opacity)" Duration="0" To="1" />
Problem is, i can't access MyTextBlock with Storyboard.TargetName="MyTextBlock" from here since it's inside the ContentPresenter. How can i do a visualstate animation of an element inside the ContentPresenter?
You can add two visualstates inside DataTemplate(PointerEntered and PointerExited):
<GridView x:Name="MyList" Grid.Row="1" ItemContainerStyle="{StaticResource GridViewItemContainerStyle}" >
<GridView.ItemTemplate>
<DataTemplate>
<Grid PointerExited="Grid_PointerExited" PointerEntered="Grid_PointerEntered">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState x:Name="PointerEntered">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="MyTextBlock" Storyboard.TargetProperty="Opacity" Duration="0" To="1" />
</Storyboard>
</VisualState>
<VisualState x:Name="PointerExited">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="MyTextBlock" Storyboard.TargetProperty="Opacity" Duration="0" To="0" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid.RowDefinitions>
<RowDefinition Height="200" />
<RowDefinition Height="3" />
<RowDefinition Height="80" />
</Grid.RowDefinitions>
<Image Grid.Row="0" Source="{Binding Url}" />
<ProgressBar Grid.Row="1" IsIndeterminate="True" />
<TextBlock Grid.Row="2" Name="MyTextBlock" Opacity="0" Text="Test" />
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
And using the following codes in Grid.PointerEntered and Grid.PointerExited events to get the storyboard start:
private void Grid_PointerExited(object sender, PointerRoutedEventArgs e)
{
Grid grid = sender as Grid;
var visualStateGroups = VisualStateManager.GetVisualStateGroups(grid);
var visualStateGroup = visualStateGroups[0];
visualStateGroup.States[1].Storyboard.Begin();
}
private void Grid_PointerEntered(object sender, PointerRoutedEventArgs e)
{
Grid grid = sender as Grid;
var visualStateGroups = VisualStateManager.GetVisualStateGroups(grid);
var visualStateGroup = visualStateGroups[0];
visualStateGroup.States[0].Storyboard.Begin();
}
DataTemplate can come from anywhere (App Resource, Window Resource, Local Resource, Code), so it uses its own NameScope.
You are unable to use MyTextBlock because of Namescope issues. So, best would be to define VisualStates as part of DataTemplate itself.
I am trying to center the text Content of a Button in Center,in my universal app,but this is what I get:
and this is my code:
<StackPanel Orientation="Vertical" >
<Border VerticalAlignment="Center" Height="40" >
<Button Background="Transparent" Content="Resultats" FontSize="16" VerticalAlignment="Stretch" Foreground="#727271" x:Name="res" Style="{Binding Source={StaticResource ButtontopStyle}}" HorizontalAlignment="Stretch" Click="res_Click" HorizontalContentAlignment="Left" VerticalContentAlignment="Center" Height="40"/>
</Border>
<StackPanel x:Name="stackVisible" Orientation="Vertical" >
<Border Margin="0" >
<Button Background="Transparent" Content="Tous les résultats" FontSize="14" VerticalAlignment="Top" Foreground="#727271" Margin="0" x:Name="ttres" Style="{Binding Source={StaticResource ButtonMenuStyle}}" HorizontalAlignment="Stretch" HorizontalContentAlignment="Left" Padding="10" VerticalContentAlignment="Center" Height="40"/>
</Border>
<Border>
<Button Background="Transparent" Content="Recherches Avancées" FontSize="14" VerticalAlignment="Top" Foreground="#727271" Margin="0" x:Name="rechavan" HorizontalAlignment="Stretch" Style="{Binding Source={StaticResource ButtonMenuStyle}}" HorizontalContentAlignment="Left" Padding="10" VerticalContentAlignment="Center" Height="40"/>
</Border>
</StackPanel>
</StackPanel>
I tried to use VerticalContentAlignment="Center",but like you see,I didn't get the result that I want
thanks for help
my styles for buttons:
<Style x:Key="ButtonMenuStyle" TargetType="Button">
<Setter Property="Foreground" Value="#e6e6e6"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="PointerOver">
<Storyboard>
<ColorAnimation Duration="0" To="#e6e6e6" Storyboard.TargetProperty="(Rectangle.Fill).(SolidColorBrush.Color)" Storyboard.TargetName="Border" />
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ColorAnimation Duration="0" To="#e6e6e6" Storyboard.TargetProperty="(Rectangle.Fill).(SolidColorBrush.Color)" Storyboard.TargetName="Border" />
<ColorAnimation Duration="0" To="#e6e6e6" Storyboard.TargetProperty="(TextBlock.Foreground).(SolidColorBrush.Color)" Storyboard.TargetName="Content" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid>
<Rectangle x:Name="Border" Stroke="Transparent" Fill="Transparent" Margin="0"/>
<ContentPresenter x:Name="Content"/>
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ButtontopStyle" TargetType="Button">
<Setter Property="Foreground" Value="#e6e6e6"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="PointerOver">
<Storyboard>
<ColorAnimation Duration="0" To="#e6e6e6" Storyboard.TargetProperty="(Rectangle.Fill).(SolidColorBrush.Color)" Storyboard.TargetName="Button" />
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ColorAnimation Duration="0" To="#e6e6e6" Storyboard.TargetProperty="(Rectangle.Fill).(SolidColorBrush.Color)" Storyboard.TargetName="Button" />
<ColorAnimation Duration="0" To="#e6e6e6" Storyboard.TargetProperty="(TextBlock.Foreground).(SolidColorBrush.Color)" Storyboard.TargetName="Content" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid>
<Rectangle x:Name="Button" Stroke="Transparent" Fill="Transparent" Margin="0"/>
<ContentPresenter x:Name="Content"/>
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
You're putting too much effort into it, and most likely the ButtonMenuStyle has something that messes up your layout. By default the content of a Button is vertically centered.
I've thrown out all your unnecessary alignments, unnecessary borders (and you could even remove the inner StackPanel as well). I've also changed the font size to 8 on one button to show multiple sizes to prove they're all aligned correctly.
<StackPanel Orientation="Vertical">
<Button Background="Transparent" Content="Resultats" FontSize="16" VerticalAlignment="Stretch" Foreground="#727271" HorizontalAlignment="Stretch" HorizontalContentAlignment="Left" Height="40"/>
<StackPanel Orientation="Vertical" >
<Button Background="Transparent" Content="Tous les résultats" FontSize="14" Foreground="#727271" HorizontalAlignment="Stretch" HorizontalContentAlignment="Left" Height="40"/>
<Button Background="Transparent" Content="Recherches Avancées" FontSize="8" Foreground="#727271" HorizontalAlignment="Stretch" HorizontalContentAlignment="Left" Height="40" />
</StackPanel>
</StackPanel>
Edit: as you posted your styles, I looked into them. I'd strongly advise against using them (as they break several things), but if you really want to use them, you should change your ContentPresenter too:
<ContentPresenter x:Name="Content" VerticalContentAlignment="Center" Content="{TemplateBinding Content}"/>
If you want to modify the button control template, look at default template in following file (line 2147) for a starting point:
C:\Program Files (x86)\Windows Kits\10\DesignTime\CommonConfiguration\Neutral\UAP\10.0.10240.0\Generic\generic.xaml
I have the following ListBox below. I am not sure how to change the Foreground of a selected item's textblock text when an item is selected, and then back to the original foreground color when an item is unselected (most likely occurring when another item in the ListBox is selected afterwards)?
<ListBox Name="ListBox" SelectionMode="Single" ItemsSource="{Binding}" Margin="{Binding}"
toolkit:TiltEffect.IsTiltEnabled="True" SelectionChanged="ListBox_SelectionChanged" >
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<toolkit:WrapPanel ItemWidth="159" ItemHeight="Auto" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical" >
<Image Source="{Binding Thumbnail}" Width="155" Height="155" />
<TextBlock Text="{Binding Name}" TextWrapping="Wrap" FontSize="{StaticResource PhoneFontSizeNormal}" VerticalAlignment="Center" HorizontalAlignment="Center" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
You have to edit ItemContainerStyle (Edit additional templates > Edit generated Item Container (ItemContainerStyle)).
Within ItemContainerStyle is Selected visual state and you can change it.
<Style x:Key="ListBoxItemStyle1" TargetType="ListBoxItem">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="VerticalContentAlignment" Value="Top"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border x:Name="LayoutRoot" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" HorizontalAlignment="{TemplateBinding HorizontalAlignment}" VerticalAlignment="{TemplateBinding VerticalAlignment}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver"/>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="LayoutRoot">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource TransparentBrush}"/>
</ObjectAnimationUsingKeyFrames>
<DoubleAnimation Duration="0" To=".5" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="ContentContainer"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="SelectionStates">
<VisualState x:Name="Unselected"/>
<VisualState x:Name="Selected">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentContainer">
<DiscreteObjectKeyFrame KeyTime="0" Value="YOUR_NEW_COLOR"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentControl x:Name="ContentContainer" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I am considering that the ItemsSource of your ListBox is bound to an ObservableCollection of an examle class test.cs as below
ObservableCollection<test> coll = new ObservableCollection<test>();
and the DataContext is ListBox.DataContext = coll;
Bind the Foreground property of your TextBlock in the ListBoxItemTemplate
<TextBlock Text="{Binding Name}" Foreground="{Binding foreground}" TextWrapping="Wrap" FontSize="{StaticResource PhoneFontSizeNormal}" VerticalAlignment="Center" HorizontalAlignment="Center" />
Now define your SelectionChanged event
private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
test tItem = (sender as ListBox).SelectedItem as test;
test.foreground = "#FFCB202D"; //this will change the color of the TextBlock
}
Make sure you extend your class test.cs with INotifyPropertyChanged and define the property foreground with the same or else dynamic changes will not be reflected.
private string tmpforeground;
public string foreground
{
get
{
return tmpforeground;
}
set
{
if (tmpforeground== value)
return;
tmpforeground= value;
NotifyPropertyChanged("foreground");
}
}
Also note that if you want the textblock to change color to green on one tap and then change its color again by tapping again, SelectionChanged event won't work, because it works only when a different item is selected. So if you want change of color on consecutive taps then use Tap event instead
<ListBox Name="ListBox" SelectionMode="Single" ItemsSource="{Binding}" Margin="{Binding}"
toolkit:TiltEffect.IsTiltEnabled="True" Tap="ListBox_Tap" >
private void ListBox_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
test tItem = (sender as ListBox).SelectedItem as test;
test.foreground = "#FFCB202D";
}
This code throw always exception. Is a way to get TextBox (x:Name = "MyBox") to hide (fadeout) when we click in its container (here ListViewItem)? What's wrong with my code?
<ListView x:Name="ListViewMy" IsItemClickEnabled="True" ItemsSource="{Binding list, Mode=TwoWay}" HorizontalAlignment="Left" Height="223" Margin="240,350,0,0" VerticalAlignment="Top" Width="582" >
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<Grid x:Name="GridMy">
<ContentPresenter x:Name="MyContentPresenter">
<ContentPresenter.ContentTemplate>
<DataTemplate x:Key="DataTemplate">
<Grid Background="#FF25C1D1" Margin="-30,0,0,0" x:Name="GridBlue">
<TextBox x:Name="MyBox" HorizontalAlignment="Left" Margin="135,0,0,0" TextWrapping="Wrap" Text="{Binding}" VerticalAlignment="Top" Width="352" Height="81" Background="{x:Null}" BorderBrush="#FF25C1D1" FontFamily="Segoe WP Semibold" FontSize="32" FontWeight="Bold" Foreground="White"/>
</Grid>
</DataTemplate>
</ContentPresenter.ContentTemplate>
</ContentPresenter>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver"/>
<VisualState x:Name="Pressed" >
<Storyboard>
<FadeOutThemeAnimation TargetName="MyBox" Duration="0:0:5"></FadeOutThemeAnimation>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
</ListView>
The problem with your code is that your animation, in the ControlTemplate for ListViewItem, should only target other elements within the ControlTemplate for ListViewItem. The DataTemplate won't work here because x:Name="MyBox" won't resolve. DataTemplates are reusable pieces of UI so Name expansion is skipped on them.
A good way to achieve your scenario is to target the animation to the ContentPresenter that is in fact part of your ControlTemplate, i.e.:
<FadeOutThemeAnimation TargetName="MyContentPresenter" Duration="0:0:5" />
This question has been asked before but in most cases no more recent than 2 years ago and often specific to WPF. The answer might still be there same, but here it goes. I'm trying to build a triangular (arrow) button that changes color and grows in size when the mouse is over it. I've got that working for a single button. But now I need buttons with the arrow pointing different directions. I want to reuse as much of the code as possible. Without using a custom button control, I couldn't think of a way to use the same style completely, so I'm trying to just reuse the mouse over animation by making it a resource. When I reference the Storyboard as a StaticResource in the VisualStateManager of my button template, it makes my button disappear completely. Why doesn't this work?
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:System="clr-namespace:System;assembly=mscorlib" mc:Ignorable="d"
x:Class="SilverlightTest.MainPage"
Width="640" Height="480">
<UserControl.Resources>
<Storyboard x:Key="ArrowMouseOver">
<DoubleAnimation Duration="0:0:0.165" To="1.25" Storyboard.TargetProperty="(UiElement.RenderTransform).(ScaleTransform.ScaleX)" Storyboard.TargetName="polygon"/>
<DoubleAnimation Duration="0:0:0.165" To="1.25" Storyboard.TargetProperty="(UiElement.RenderTransform).(ScaleTransform.ScaleY)" Storyboard.TargetName="polygon"/>
<ColorAnimation Duration="0:0:0.165" To="#FF9BD6FF" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[1].(GradientStop.Color)" Storyboard.TargetName="polygon" d:IsOptimized="True"/>
<ColorAnimation Duration="0:0:0.165" To="#FF70ACDF" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[0].(GradientStop.Color)" Storyboard.TargetName="polygon" d:IsOptimized="True"/>
<ColorAnimation Duration="0:0:0.165" To="#FF7DAEFF" Storyboard.TargetProperty="(Shape.Stroke).(GradientBrush.GradientStops)[1].(GradientStop.Color)" Storyboard.TargetName="polygon" d:IsOptimized="True"/>
<ColorAnimation Duration="0:0:0.165" To="#FF2B5CB4" Storyboard.TargetProperty="(Shape.Stroke).(GradientBrush.GradientStops)[0].(GradientStop.Color)" Storyboard.TargetName="polygon" d:IsOptimized="True"/>
</Storyboard>
<Style x:Key="LeftArrow" TargetType="Button">
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid x:Name="grdRoot" RenderTransformOrigin="0.5,0.5">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualStateGroup.Transitions>
<VisualTransition From="MouseOver" GeneratedDuration="0:0:0.165"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver" Storyboard="{StaticResource ArrowMouseOver}">
</VisualState>
<VisualState x:Name="Pressed"/>
<VisualState x:Name="Disabled"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Polygon x:Name="polygon" Grid.Row="0" Margin="1" StrokeThickness="{TemplateBinding BorderThickness}" HorizontalAlignment="Center" RenderTransformOrigin="0.5,0.5">
<Polygon.Points>
<Point X="10"/>
<Point X="0" Y="5" />
<Point Y="10" X="10" />
</Polygon.Points>
<Polygon.RenderTransform>
<ScaleTransform />
</Polygon.RenderTransform>
<Polygon.Fill>
<LinearGradientBrush EndPoint="0.5,0" StartPoint="0.5,1">
<GradientStop Color="#FFA9A9A9"/>
<GradientStop Color="#FFD3D3D3" Offset="1"/>
</LinearGradientBrush>
</Polygon.Fill>
<Polygon.Stroke>
<LinearGradientBrush EndPoint="0.5,0" StartPoint="0.5,1">
<GradientStop Color="#FF696969"/>
<GradientStop Color="#FF939393" Offset="1"/>
</LinearGradientBrush>
</Polygon.Stroke>
</Polygon>
<ContentPresenter Grid.Row="1" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White">
<Button Style="{StaticResource LeftArrow}" HorizontalAlignment="Left" VerticalAlignment="Top">
</Button>
</Grid>
This sounds like you should introduce your own Button class.
I would do it like so:
<my:GlowingArrowButton ArrowDirection="Left"/>
And your generic.xaml:
<Style TargetType="my:GlowingArrowButton">
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="my:GlowingArrowButton">
<Grid x:Name="grdRoot" RenderTransformOrigin="0.5,0.5">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualStateGroup.Transitions>
<VisualTransition From="MouseOver" GeneratedDuration="0:0:0.165"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver"
<Storyboard>
<DoubleAnimation Duration="0:0:0.165" To="1.25" Storyboard.TargetProperty="(UiElement.RenderTransform).(ScaleTransform.ScaleX)" Storyboard.TargetName="polygon"/>
<DoubleAnimation Duration="0:0:0.165" To="1.25" Storyboard.TargetProperty="(UiElement.RenderTransform).(ScaleTransform.ScaleY)" Storyboard.TargetName="polygon"/>
<ColorAnimation Duration="0:0:0.165" To="#FF9BD6FF" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[1].(GradientStop.Color)" Storyboard.TargetName="polygon" d:IsOptimized="True"/>
<ColorAnimation Duration="0:0:0.165" To="#FF70ACDF" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[0].(GradientStop.Color)" Storyboard.TargetName="polygon" d:IsOptimized="True"/>
<ColorAnimation Duration="0:0:0.165" To="#FF7DAEFF" Storyboard.TargetProperty="(Shape.Stroke).(GradientBrush.GradientStops)[1].(GradientStop.Color)" Storyboard.TargetName="polygon" d:IsOptimized="True"/>
<ColorAnimation Duration="0:0:0.165" To="#FF2B5CB4" Storyboard.TargetProperty="(Shape.Stroke).(GradientBrush.GradientStops)[0].(GradientStop.Color)" Storyboard.TargetName="polygon" d:IsOptimized="True"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed"/>
<VisualState x:Name="Disabled"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<LayoutTransformer
LayoutTransform="{Binding Path=ArrowDirection,
RelativeSource={RelativeSource TemplatedParent},
Converter={StaticResource RotationTranslator_ToBeImplemented}}"
Grid.Row="0"
HorizontalAlignment="Center">
<Polygon
x:Name="polygon"
Margin="1"
StrokeThickness="{TemplateBinding BorderThickness}"
RenderTransformOrigin="0.5,0.5">
<Polygon.Points>
<Point X="10"/>
<Point X="0" Y="5" />
<Point Y="10" X="10" />
</Polygon.Points>
<Polygon.RenderTransform>
<ScaleTransform />
</Polygon.RenderTransform>
<Polygon.Fill>
<LinearGradientBrush EndPoint="0.5,0" StartPoint="0.5,1">
<GradientStop Color="#FFA9A9A9"/>
<GradientStop Color="#FFD3D3D3" Offset="1"/>
</LinearGradientBrush>
</Polygon.Fill>
<Polygon.Stroke>
<LinearGradientBrush EndPoint="0.5,0" StartPoint="0.5,1">
<GradientStop Color="#FF696969"/>
<GradientStop Color="#FF939393" Offset="1"/>
</LinearGradientBrush>
</Polygon.Stroke>
</Polygon>
</LayoutTransformer>
<ContentPresenter
Grid.Row="1"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And code:
public class GlowingArrowButton : ButtonBase
{
public GlowingArrowButton()
{
DefaultStyleKey = typeof (GlowingArrowButton);
}
public ArrowDirection ArrowDirection
{
get { return (ArrowDirection) GetValue( ArrowDirectionProperty ); }
set { SetValue( ArrowDirectionProperty, value ); }
}
public static readonly DependencyProperty ArrowDirectionProperty =
DependencyProperty.Register( "ArrowDirection", typeof( ArrowDirection ), typeof( GlowingArrowButton ), new PropertyMetadata( default( ArrowDirection ) ) );
}
public enum ArrowDirection
{
Left,
Up,
Right,
Down
}
[Edit]
Written but untested:
public class RotationTranslator : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var arrowDirection = (ArrowDirection) value;
switch (arrowDirection)
{
case ArrowDirection.Left: return new RotateTransform{ Angle = 0 };
case ArrowDirection.Up: return new RotateTransform { Angle = 90 };
case ArrowDirection.Right: return new RotateTransform { Angle = 180 };
case ArrowDirection.Down: return new RotateTransform { Angle = -90 };
}
throw new InvalidOperationException();
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture){throw new NotSupportedException();}
}
Storyboard requires the DynamicResource markup extension and "Silverlight does not support dynamic resources." Strewth.