使用XAML在LongListSelector上添加选定的效果

时间:2014-10-10 09:12:28

标签: xaml windows-phone-8 expression-blend

我有LongListSelector和GroupHeaderTemplate以及ItemTemplate。

我想添加' Selected'对组中所选项目的影响。例如,名为RightArrow的元素可以变为灰色(现在它是蓝色的)。

我试图用Expression Blend做到这一点,但效果并不适用于所选项目,但适用于每个项目。

Preview

<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>

1 个答案:

答案 0 :(得分:1)

从我看到的问题是,您将故事板应用于整个LongListSelector控件而不是单个项目。您的VisualStateManager应放入ItemTemplateDataTemplate)。

不幸的是,框中似乎没有提供挂钩,因此您必须使用VisualStateManager.GoToState方法手动管理您的项目状态。

首先,您应该删除分配给Selected LongListSelector状态的情节提要,因为此部分会影响整个列表。

然后你应该用两种视觉状态创建简单的控件:NormalSelected

<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>

然后将此控件添加到DataTemplate,如下所示:

<phone:LongListSelector x:Name="ListSelector" SelectionChanged="HandleSelectionChanged">
    <phone:LongListSelector.ItemTemplate>
        <DataTemplate>
            <phoneApp2:CustomLongListSelectorItem/>
        </DataTemplate>
    </phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>

最后,您必须在页面的代码隐藏中添加一些代码,以管理自定义控件的状态。 基本上你需要实现HandleSelectionChanged方法和GetItemsRecursive作为一个小帮手来轻松控制孩子。

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

上面提供的代码主要来自此示例Highlight a selected item in the LongListSelector on WP8。它可能与示例略有不同,因为我想确保它能正常工作。