LongListSelector empty style - xaml

I want to show a TextBlock when the LongListSelector has no items. I can do it to every list in my app but that is not sane. So I am trying to edit the list style and do it to every list.
How can I bind to the LongListSelector ItemsSouce count inside its style?
Here is where I am now.
<Style 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}">
<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="NotScrolling" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid Margin="{TemplateBinding Padding}">
<i:Interaction.Triggers>
<!-- HERE I CANT BIND TO COUNT -->
<ec:DataTrigger Binding="{TemplateBinding ItemsSource}" Comparison="Equal" Value="0">
<ec:ChangePropertyAction TargetObject="{Binding ElementName=EmptyListText}" PropertyName="Visibility" Value="Visible" />
</ec:DataTrigger>
</i:Interaction.Triggers>
<ViewportControl x:Name="ViewportControl" HorizontalContentAlignment="Stretch" VerticalAlignment="Top" />
<ScrollBar x:Name="VerticalScrollBar" Opacity="0" Background="{StaticResource ThemeBackground}" HorizontalAlignment="Right" Orientation="Vertical" />
<TextBlock x:Name="EmptyListText" Visibility="Collapsed" Text="{Binding Source={StaticResource Literals}, Path=Literals.noResults}" />
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

It's a DataBinding issue.
Try attaching it to the TemplateParent (which is the LongListSelector) like so:
<ec:DataTrigger
Binding="{Binding RelativeSource={RelativeSource Mode=TemplateParent}, Path=ItemsSource.Count}"
Comparison="Equal" Value="0">
</ec:DataTrigger>
That should set you straight if you want to use your triggers.
I like using Converters. It is a little simpler to understand so here's the full solution using a Converter.
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows.Data;
public class MyConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value == null)
return Visibility.Collapsed;
else
{
if (value is System.Collections.IList)
{
System.Collections.IList list = (System.Collections.IList)value;
if (list.Count == 0)
return Visibility.Collapsed;
else
return Visibility.Visible;
}
else
return Visibility.Collapsed;
}
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return null;
}
}
So the LongListSelector Style is:
<TextBlock Visibility="{Binding ItemsSource, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource MyConverter}}"></TextBlock>

Create a custom composite control based on the long list selector which does what is required and has the smarts to show a specific message per a dependency property.

Related

Add Selected effect on LongListSelector with XAML

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.

How to Change the SelectedItem Foreground Text of ListBox Item

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";
}

How to reuse Storyboard with VisualStateManager In Silverlight 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.

How to change background color of Windows Phone Listpicker in FullScreen Mode

This question has been asked before but the answers provided have not worked for myself and others. The style for the listpicker is provided by I haven't been able to get the background of the Listpicker to change color (in this case yellow) despite trying every property I can think of to get it to change. What is wrong with the code?
<Style TargetType="toolkit:ListPicker" x:Key="ListPickerStyle1">
<!--<Setter Property="Background" Value="{StaticResource PhoneTextBoxBrush}"/>-->
<!--<Setter Property="Background" Value="YellowGreen"/>-->
<Setter Property="Foreground" Value="{StaticResource PhoneTextBoxForegroundBrush}"/>
<Setter Property="FontSize" Value="{StaticResource PhoneFontSizeMediumLarge}"/>
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="Margin" Value="{StaticResource PhoneTouchTargetOverhang}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="toolkit:ListPicker">
<StackPanel>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="PickerStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="Expanded">
<Storyboard>
<!--<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Border" Storyboard.TargetProperty="Background" Duration="0"> <DiscreteObjectKeyFrame Value="{StaticResource PhoneTextBoxEditBackgroundColor}" KeyTime="0"/> </ObjectAnimationUsingKeyFrames>-->
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Border" Storyboard.TargetProperty="BorderBrush" Duration="0">
<DiscreteObjectKeyFrame Value="Yellow" KeyTime="0"/>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Border" Storyboard.TargetProperty="BorderThickness" Duration="0">
<DiscreteObjectKeyFrame Value="200" KeyTime="0"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentControl Content="{TemplateBinding Header}" ContentTemplate="{TemplateBinding HeaderTemplate}"
Foreground="{StaticResource PhoneSubtleBrush}" FontSize="{StaticResource PhoneFontSizeNormal}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="0 0 0 8"/>
<Grid>
<!--<Border x:Name="Border" Background="Yellow" BorderBrush="{TemplateBinding Background}" BorderThickness="2">-->
<Border x:Name="Border" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding Background}" BorderThickness="2">
<Canvas x:Name="ItemsPresenterHost" MinHeight="46">
<ItemsPresenter x:Name="ItemsPresenter">
<ItemsPresenter.RenderTransform>
<TranslateTransform x:Name="ItemsPresenterTranslateTransform"/>
</ItemsPresenter.RenderTransform>
</ItemsPresenter>
</Canvas>
</Border>
<Popup x:Name="FullModePopup">
<!--<Border Background="{StaticResource PhoneChromeBrush}">-->
<Border Background="Yellow" BorderThickness="200">
<!-- Popup.Child should always be a Border -->
<Grid Background="Yellow">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<ContentControl Grid.Row="0" Content="{TemplateBinding FullModeHeader}" Background="Yellow"
Foreground="{StaticResource PhoneForegroundBrush}"
FontFamily="{StaticResource PhoneFontFamilySemiBold}" FontSize="{StaticResource PhoneFontSizeMedium}"
HorizontalAlignment="Left" Margin="24 12 0 0"/>
<ListBox x:Name="FullModeSelector" Grid.Row="1" ItemTemplate="{TemplateBinding ActualFullModeItemTemplate}"
FontSize="{TemplateBinding FontSize}" Margin="{StaticResource PhoneMargin}" Background="Yellow">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Background="Yellow"/>
<!-- Ensures all containers will be available during the Loaded event -->
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
</Grid>
</Border>
</Popup>
</Grid>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I did this by creating an interface to represent ListPickerPage, and changing any code references in the Toolkit to use the interface (IListPickerPage) instead.
Then, I just created a new PhoneApplicationPage, and copied & slightly modified the source (xaml & xaml.cs), (I made it implement IListPickerPage)
using System.Collections;
using System.Windows;
using System.Windows.Controls;
namespace Microsoft.Phone.Controls
{
public interface IListPickerPage
{
string HeaderText { get; set; }
IList Items { get; }
SelectionMode SelectionMode { get; set; }
object SelectedItem { get; set; }
IList SelectedItems { get; }
DataTemplate FullModeItemTemplate { get; set; }
bool IsOpen { get; set; }
}
}
and then, when you want to use it, you just specify your own page instead, by setting the PickerPageUri
<toolkit:ListPicker x:Name="lpStr"
Grid.RowSpan="2"
Width="1"
Height="1"
CacheMode="BitmapCache"
ExpansionMode="FullScreenOnly"
Foreground="Black"
FullModeItemTemplate="{StaticResource ListPickerStringLargeTemplate}"
IsHitTestVisible="False"
Opacity="0"
PickerPageUri="/Views/Globals/ToolkitPages/MyListPickerPage.xaml" />
</Grid>
The rest is simply customizing your own ListPickerPage xaml file to fit your requirements.

LongListSelector control strectching events are not firing

I've been trying to attach code to the StretchingBottom event of a LongListSelector with no success. This is the definition in XAML
<toolkit:LongListSelector x:Name="NewList"
IsFlatList="True"
IsBouncy="True"
Background="Transparent"
ShowListFooter="False"
ShowListHeader="{Binding ProgressBar}"
Margin="0,0,12,0"
ListHeaderTemplate="{StaticResource progressbarListHeader}"
ItemsSource="{Binding Items}"
ItemTemplate="{StaticResource Item}"
SelectionChanged="List_SelectionChanged"
StretchingBottom="List_StretchingBottom"/>
This is the method List_SelectionChanged:
private void List_StretchingBottom(object sender, EventArgs e)
{
var listbox = (LongListSelector)sender;
var viewModel = (ItemsViewModel)listbox.DataContext;
viewModel.LoadDataAfter();
}
When I put a breakpoint on the first line of the method it never gets hit even if I stretch all the way or wait. I've tried StretchingTop and StretchingComplete with no success.
Anyone can help?
I just got this working with much help from a MSDN blog and Codeplex
The examples there are for the ScrollViewer but the LongListSelector is using the ScrollViewer...
1st: add a Template to App.XAML inside the Application.Resources
:
<Style TargetType="ScrollViewer">
<Setter Property="VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="HorizontalScrollBarVisibility" Value="Auto"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ScrollViewer">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="ScrollStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="00:00:00.5"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="Scrolling">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="VerticalScrollBar"
Storyboard.TargetProperty="Opacity" To="1" Duration="0"/>
<DoubleAnimation Storyboard.TargetName="HorizontalScrollBar"
Storyboard.TargetProperty="Opacity" To="1" Duration="0"/>
</Storyboard>
</VisualState>
<VisualState x:Name="NotScrolling">
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="VerticalCompression">
<VisualState x:Name="NoVerticalCompression"/>
<VisualState x:Name="CompressionTop"/>
<VisualState x:Name="CompressionBottom"/>
<VisualState x:Name="StretchingTop"/>
<VisualState x:Name="StretchingBottom"/>
</VisualStateGroup>
<VisualStateGroup x:Name="HorizontalCompression">
<VisualState x:Name="NoHorizontalCompression"/>
<VisualState x:Name="CompressionLeft"/>
<VisualState x:Name="CompressionRight"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid Margin="{TemplateBinding Padding}">
<ScrollContentPresenter x:Name="ScrollContentPresenter" Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"/>
<ScrollBar x:Name="VerticalScrollBar" IsHitTestVisible="False" Height="Auto" Width="5"
HorizontalAlignment="Right" VerticalAlignment="Stretch" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"
IsTabStop="False" Maximum="{TemplateBinding ScrollableHeight}" Minimum="0" Value="{TemplateBinding VerticalOffset}"
Orientation="Vertical" ViewportSize="{TemplateBinding ViewportHeight}" />
<ScrollBar x:Name="HorizontalScrollBar" IsHitTestVisible="False" Width="Auto" Height="5"
HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"
IsTabStop="False" Maximum="{TemplateBinding ScrollableWidth}" Minimum="0" Value="{TemplateBinding HorizontalOffset}"
Orientation="Horizontal" ViewportSize="{TemplateBinding ViewportWidth}" />
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
This enables the visual state groups for Compression, so you can detect the Compression that appeares if the list is scrolled to an end. You want CompressionBottom as this happenes when the List is scrolled to the bottom.
Now I attach a handler to the LongListSelector.Loaded event and inside attach a handler to the ScrollViewer.State
private void LongListSelector_Loaded(object sender, RoutedEventArgs e)
{
//get TemplatedListBox inside LongListSelector
FrameworkElement tlb = VisualTreeHelper.GetChild(EventsDisplayList, 0) as FrameworkElement;
//get ScrollViewer inside TemplatedListBox
FrameworkElement sv = VisualTreeHelper.GetChild(tlb, 0) as FrameworkElement;
//MS says VisualGroups are inside first Child of ScrollViewer
FrameworkElement here = VisualTreeHelper.GetChild(sv, 0) as FrameworkElement;
var groups = VisualStateManager.GetVisualStateGroups(here);
VisualStateGroup vc = null;
foreach (VisualStateGroup g in groups)
{
if (g.Name == "VerticalCompression")
{
vc = g;
break;
}
}
vc.CurrentStateChanged +=new EventHandler<VisualStateChangedEventArgs>(LongListSelector_Compression);
}
private void LongListSelector_Compression(object sender, VisualStateChangedEventArgs e)
{
if (e.NewState.Name == "CompressionBottom")
{
//put your code for loading new items here
}
}
As you can see I don't use the LongListSelector.StretchingBottom event at all.
But it works :)