如何使listboxitem扩展选择?

时间:2011-01-18 10:28:46

标签: wpf animation listbox wpf-controls transition

我有一种情况,我希望用户按特定顺序做出选择(首先我希望用户选择数据库,然后我希望他告诉我他的凭据)。

为了做到这一点,我挑战自己的任务是在选择中创建扩展项目的列表框。 使其扩展并不困难(类似

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>

触发器不起作用,但那是因为我不能让它们发火......有人知道如何实现这一点吗?

此致 Tor Thorbergsen

3 个答案:

答案 0 :(得分:2)

这个东西太复杂了...... 你的方法有什么问题,动画只会影响VisualTree中较低的元素,这意味着就我所知,容器不受影响。
我说,在动画中指定属性路径是一个主要的痛苦。我无法访问StackPanel内的边框,因为它的Children属性不是依赖属性,整个语法相当不寻常。

无论如何,这是一个hacky解决方案,有效:

        <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并在动画和边框中引用它,但是由于某种原因它不起作用。

答案 1 :(得分:0)

您不应该在事件上使用ListBoxItem前缀,只需使用“Selected”和“Unselected”。

尝试的另一种选择是属性触发器:

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

答案 2 :(得分:0)

修改

好的,我已经弄清楚了。我为此创建了一个附加属性(而不是使用Tag)。

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> 

我正在使用@ H.B解决方案。它在第一次加载列表时有效。但是,如果我展开一个listboxitem,切换到另一个选项卡并返回到listbox所在的选项卡,则会抛出异常:

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

任何人都有这个吗?