Wpf 如何使listboxitem在选择时展开?

Wpf 如何使listboxitem在选择时展开?,wpf,animation,listbox,wpf-controls,transition,Wpf,Animation,Listbox,Wpf Controls,Transition,我希望用户按照特定顺序进行选择(首先我希望用户选择数据库,然后我希望他告诉我他的凭据) 为了做到这一点,我向自己提出了一个挑战:制作一个列表框,在选择时扩展项目。 要让它扩展并不困难(比如 Visibility="{Binding Path=IsSelected , RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}} , Converte

我希望用户按照特定顺序进行选择(首先我希望用户选择数据库,然后我希望他告诉我他的凭据)

为了做到这一点,我向自己提出了一个挑战:制作一个列表框,在选择时扩展项目。 要让它扩展并不困难(比如

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

事件不需要ListBoxItem前缀,只需使用“已选择”和“未选择”

另一种尝试方法是属性触发器:


这东西太复杂了……
您的方法的错误在于,动画只影响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>

0
我试图提取ScaleTransform并在动画和边框中引用它,但无论出于何种原因,都没有成功。

编辑:

好的,我已经弄明白了。我已经为此创建了一个附加属性(而不是使用标记)

公共静态类ListBoxHelper
{
公共静态只读从属属性ScaleYAnimationProperty=
DependencyProperty.RegisterAttached(“ScaleYAnimation”、typeof(double)、typeof(ListBoxHelper)、new FrameworkPropertyMetadata(0d));
公共静态双GetScaleYAnimation(UIElement元素)
{
return(double)element.GetValue(ScaleYAnimationProperty);
}
公共静态void SetScaleYAnimation(UIElement元素,双值)
{
SetValue(ScaleYAnimationProperty,value);
}
}
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> 
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)'