Как заставить listboxitem расширяться при выборе? - PullRequest
0 голосов
/ 18 января 2011

У меня есть ситуация, когда я хочу, чтобы пользователь делал выбор в определенном порядке (сначала я хочу, чтобы пользователь выбрал базу данных, затем я хочу, чтобы он сообщил мне свои учетные данные).

Для этогоЯ поставил перед собой задачу создать список, который расширяет элемент при выборе.Сделать это не сложно (что-то вроде

Visibility="{Binding Path=IsSelected
             , RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}
             , Converter={StaticResource VisibilityOfBool}
             , ConverterParameter=False}"

сделает свое дело).

Проблема в том, что переход происходит мгновенно;пользователю трудно увидеть, что произошло.То, что я хотел бы сделать, это анимированное расширение скрытой панели ...

Вот страница, чтобы продемонстрировать, что я имею в виду:

<Page 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:system="clr-namespace:System;assembly=mscorlib"
      mc:Ignorable="d" 
      d:DesignHeight="300" d:DesignWidth="300"
    Title="SlidingExpansionOnSelected">
    <!--x:Class="TorsSandBox.Pages.SlidingExpansionOnSelected"-->

    <Page.Resources>
        <DataTemplate x:Key="daItemTemplate">
            <StackPanel Margin="10">
                <StackPanel.Triggers>
                        <EventTrigger RoutedEvent="ListBoxItem.Selected">
                            <EventTrigger.Actions>
                                <BeginStoryboard>
                                    <Storyboard>
                                        <DoubleAnimation
                                        Storyboard.TargetName="daTransform"
                                        Storyboard.TargetProperty="ScaleY"
                                        To="1.0" Duration="0:0:1"/>
                                    </Storyboard>
                                </BeginStoryboard>
                            </EventTrigger.Actions>
                        </EventTrigger>
                        <EventTrigger RoutedEvent="ListBoxItem.Unselected">
                            <EventTrigger.Actions>
                                <BeginStoryboard>
                                    <Storyboard>
                                        <DoubleAnimation
                                        Storyboard.TargetName="daTransform"
                                        Storyboard.TargetProperty="ScaleY"
                                        To="0" Duration="0:0:1"/>
                                    </Storyboard>
                                </BeginStoryboard>
                            </EventTrigger.Actions>
                        </EventTrigger>
                </StackPanel.Triggers>
                <TextBlock x:Name="Header" Text="{Binding}"/>
                <Border x:Name="daBorder"
                    BorderThickness="3" BorderBrush="DarkOrange" CornerRadius="5"
                    HorizontalAlignment="Stretch"
                    Margin="20 10 10 10"
                    MinHeight="100"
                    >
                    <Border.LayoutTransform>
                        <ScaleTransform x:Name="daTransform" ScaleX="1" ScaleY="0"/>
                    </Border.LayoutTransform>
                    <TextBlock Text="Hide this until selected" 
                        HorizontalAlignment="Center" VerticalAlignment="Center" />
                </Border>
            </StackPanel>
        </DataTemplate>
    </Page.Resources>

    <ListBox
        HorizontalContentAlignment="Stretch"
        ItemTemplate="{StaticResource daItemTemplate}"
        >
        <system:String>First row</system:String>
        <system:String>Second row</system:String>
        <system:String>Third row</system:String>
        <system:String>Last row</system:String>
    </ListBox>
</Page>

Триггеры не работают, ноэто потому что я не могу заставить их стрелять ... Кто-нибудь знает, как это сделать?

С уважением, Тор Торбергсен

Ответы [ 3 ]

2 голосов
/ 18 января 2011

Это слишком сложно ...Что не так с вашим подходом, так это то, что анимация влияет только на элементы ниже в VisualTree, это означает, что контейнер, насколько я знаю, не затронут.Я говорю, что указание пути к свойствам в анимации - главная проблема.Я не смог получить доступ к границе внутри StackPanel, потому что его свойство Children не является свойством зависимости, а весь синтаксис довольно необычен.

В любом случае, вот хакерское решение, которое работает:

        <Style TargetType="ListBoxItem">
            <Style.Resources>
                <Storyboard x:Key="OnSelected1"/>
            </Style.Resources>
            <Setter Property="Tag">
                <Setter.Value>
                    <sys:Double>0</sys:Double>
                </Setter.Value>
            </Setter>
            <Setter Property="ContentTemplate">
                <Setter.Value>
                    <DataTemplate>
                        <StackPanel x:Name="stackPanel" Margin="10">
                            <TextBlock x:Name="Header" Text="{Binding}"/>
                            <Border x:Name="daBorder"
                                    BorderThickness="3" BorderBrush="DarkOrange" CornerRadius="5"
                                    HorizontalAlignment="Stretch"
                                    Margin="20 10 10 10"
                                    MinHeight="100">
                                <Border.LayoutTransform>
                                    <ScaleTransform ScaleX="1" ScaleY="{Binding RelativeSource={RelativeSource AncestorType=ListBoxItem}, Path=Tag}"/>
                                </Border.LayoutTransform>
                                <TextBlock Text="Hide this until selected"  HorizontalAlignment="Center" VerticalAlignment="Center" />
                            </Border>
                        </StackPanel>
                    </DataTemplate>
                </Setter.Value>
            </Setter>
            <Style.Triggers>
                <EventTrigger RoutedEvent="ListBoxItem.Selected">
                    <EventTrigger.Actions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation
                                    Storyboard.TargetProperty="(ListBoxItem.Tag)"
                                    Storyboard.TargetName="{x:Null}"
                                    To="1.0" Duration="0:0:1"/>
                            </Storyboard>
                        </BeginStoryboard>
                        <BeginStoryboard Storyboard="{StaticResource OnSelected1}"/>
                    </EventTrigger.Actions>
                </EventTrigger>
                <EventTrigger RoutedEvent="ListBoxItem.Unselected">
                    <EventTrigger.Actions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation
                                    Storyboard.TargetProperty="(ListBoxItem.Tag)"
                                    Storyboard.TargetName="{x:Null}"
                                    To="0" Duration="0:0:1"/>
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger.Actions>
                </EventTrigger>
            </Style.Triggers>
        </Style>

Я попытался извлечь ScaleTransform и ссылаться на него как в анимации, так и в Border, но это не сработалопо любой причине.

0 голосов
/ 06 декабря 2014

РЕДАКТИРОВАТЬ:

Хорошо, я понял это.Я создал прикрепленное свойство для этого (вместо использования тега).

public static class ListBoxHelper
{
    public static readonly DependencyProperty ScaleYAnimationProperty =
        DependencyProperty.RegisterAttached("ScaleYAnimation", typeof(double), typeof(ListBoxHelper), new FrameworkPropertyMetadata(0d));

    public static double GetScaleYAnimation(UIElement element)
    {
        return (double)element.GetValue(ScaleYAnimationProperty);
    }

    public static void SetScaleYAnimation(UIElement element, double value)
    {
        element.SetValue(ScaleYAnimationProperty, value);
    }
}

 <ListBox ItemsSource="{Binding Contacts}" HorizontalContentAlignment="Stretch">
        <ListBox.Resources>
            <Style TargetType="ListBoxItem" BasedOn="{StaticResource {x:Type ListBoxItem}}">
                <Setter Property="controls:ListBoxHelper.ScaleYAnimation" Value="0"/>
                <Setter Property="ContentTemplate">
                    <Setter.Value>
                        <DataTemplate>
                            <StackPanel>
                                <Grid>
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="40"/>
                                        <ColumnDefinition Width="*"/>
                                        <ColumnDefinition Width="Auto"/>
                                        <ColumnDefinition Width="100"/>
                                    </Grid.ColumnDefinitions>

                                    <controls:CircleContentControl Grid.Column="0" Width="40" Height="40">
                                        <Image Source="{Binding Image}"/>
                                    </controls:CircleContentControl>
                                    <TextBlock Text="{Binding FullName}" Grid.Column="1" Margin="10,0,5,0" VerticalAlignment="Center"/>
                                    <TextBlock Text="{Binding PhoneNumber}" Grid.Column="2" VerticalAlignment="Center" FontStyle="Italic">
                                        <TextBlock.LayoutTransform>
                                            <ScaleTransform ScaleX="0.7" ScaleY="0.7"/>
                                        </TextBlock.LayoutTransform>
                                    </TextBlock>
                                    <StackPanel Orientation="Horizontal" Grid.Column="3" VerticalAlignment="Center" HorizontalAlignment="Center">
                                        <Button cal:Message.Attach="Call($dataContext)" Width="30" Height="30" Style="{StaticResource ContactDialButtonStyle}">
                                            <Rectangle Width="10" Height="10" Fill="{Binding Path=Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}">
                                                <Rectangle.OpacityMask>
                                                    <VisualBrush Stretch="Fill" Visual="{DynamicResource appbar_phone}" />
                                                </Rectangle.OpacityMask>
                                            </Rectangle>
                                        </Button>
                                    </StackPanel>
                                </Grid>
                                <Border x:Name="daBorder"
                                BorderThickness="3" BorderBrush="DarkOrange" CornerRadius="5"
                                HorizontalAlignment="Stretch"
                                Margin="20 10 10 10"
                                MinHeight="100">
                                    <Border.LayoutTransform>
                                        <ScaleTransform ScaleX="1" ScaleY="{Binding RelativeSource={RelativeSource AncestorType=ListBoxItem}, Path=(controls:ListBoxHelper.ScaleYAnimation)}"/>
                                    </Border.LayoutTransform>
                                    <TextBlock Text="Hide this until selected"  HorizontalAlignment="Center" VerticalAlignment="Center" />
                                </Border>
                            </StackPanel>
                        </DataTemplate>
                    </Setter.Value>
                </Setter>
                <Style.Triggers>
                    <EventTrigger RoutedEvent="ListBoxItem.Selected">
                        <EventTrigger.Actions>
                            <BeginStoryboard>
                                <Storyboard>
                                    <DoubleAnimation
                                Storyboard.TargetProperty="(controls:ListBoxHelper.ScaleYAnimation)"
                                Storyboard.TargetName="{x:Null}"
                                To="1.0" Duration="0:0:1"/>
                                </Storyboard>
                            </BeginStoryboard>
                        </EventTrigger.Actions>
                    </EventTrigger>
                    <EventTrigger RoutedEvent="ListBoxItem.Unselected">
                        <EventTrigger.Actions>
                            <BeginStoryboard>
                                <Storyboard>
                                    <DoubleAnimation
                                Storyboard.TargetProperty="(controls:ListBoxHelper.ScaleYAnimation)"
                                Storyboard.TargetName="{x:Null}"
                                To="0.0" Duration="0:0:1"/>
                                </Storyboard>
                            </BeginStoryboard>
                        </EventTrigger.Actions>
                    </EventTrigger>
                </Style.Triggers>
            </Style>
        </ListBox.Resources>
    </ListBox> 

Я использую решение @HB.Работает при первой загрузке списка.Однако, если я разверну один элемент списка, переключусь на другую вкладку и вернусь на вкладку, где находится список, появится исключение:

System.Windows.Data Error: 23 : Cannot convert '<null>' from type '<null>' to type 'System.Double' for 'en-US' culture with default conversions; consider using Converter property of Binding. NotSupportedException:'System.NotSupportedException: DoubleConverter não pode ser convertido de (nulo).
   em System.ComponentModel.TypeConverter.GetConvertFromException(Object value)
   em System.ComponentModel.TypeConverter.ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, Object value)
   em System.ComponentModel.BaseNumberConverter.ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, Object value)
   em MS.Internal.Data.DefaultValueConverter.ConvertHelper(Object o, Type destinationType, DependencyObject targetElement, CultureInfo culture, Boolean isForward)'

System.Windows.Data Error: 6 : 'ObjectSourceConverter' converter failed to convert value '<null>' (type '<null>'); fallback value will be used, if available. BindingExpression:Path=Tag; DataItem='ListBoxItem' (Name=''); target element is 'ScaleTransform' (HashCode=48000142); target property is 'ScaleY' (type 'Double') NotSupportedException:'System.NotSupportedException: DoubleConverter não pode ser convertido de (nulo).
   em MS.Internal.Data.DefaultValueConverter.ConvertHelper(Object o, Type destinationType, DependencyObject targetElement, CultureInfo culture, Boolean isForward)
   em MS.Internal.Data.ObjectSourceConverter.Convert(Object o, Type type, Object parameter, CultureInfo culture)
   em System.Windows.Data.BindingExpression.ConvertHelper(IValueConverter converter, Object value, Type targetType, Object parameter, CultureInfo culture)'

У кого-нибудь тоже есть это?

0 голосов
/ 18 января 2011

Вам не нужен префикс ListBoxItem в ваших событиях, просто используйте «Выбрано» и «Не выбрано».

Другой альтернативный вариант - триггер свойства:

https://web.archive.org/web/20120225232943/http://en.csharp-online.net/WPF_Styles_and_Control_Templates%E2%80%94Property_Triggers

...