为了触发动画,我创建了附加的依赖属性 AddNewItem(布尔值):
public class MyDependencyClass : DependencyObject
{
public static readonly DependencyProperty AddNewItemProperty;
public static void SetAddNewItem(DependencyObject DepObject, bool value)
{
DepObject.SetValue(AddNewItemProperty, value);
}
public static bool GetAddNewItem(DependencyObject DepObject)
{
return (bool)DepObject.GetValue(AddNewItemProperty);
}
static MyDependencyClass()
{
PropertyMetadata MyPropertyMetadata = new PropertyMetadata(false);
AddNewItemProperty = DependencyProperty.RegisterAttached("AddNewItem",
typeof(bool),
typeof(MyDependencyClass),
MyPropertyMetadata);
}
}
然后创建我们的依赖属性的边框(警告添加一个新项目):
<Border x:Name="WarningBorder" Style="{StaticResource HideBorderStyle}" local:MyDependencyClass.AddNewItem="False" Height="33" Background="#44515B" BorderThickness="0" Margin="65,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Opacity="0">
<TextBlock x:Name="WarningText" FontFamily="./#Segoe UI" TextAlignment="Center" Margin="0,5,0,0" FontSize="18" Foreground="Gainsboro" Text="You add new item" />
</Border>
样式 HideBorderStyle 包含在属性AddNewItem =True 时触发的 DataTrigger。HideBorderStyle 列表:
<Style x:Key="HideBorderStyle" TargetType="{x:Type Border}">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=WarningBorder, Path=(local:MyDependencyClass.AddNewItem), Mode=OneWay}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Width" BeginTime="0:0:0" From="0.0" To="427.0" Duration="0:0:0.5" />
<DoubleAnimation Storyboard.TargetProperty="Opacity" BeginTime="0:0:0" From="0.0" To="1.0" Duration="0:0:1.0" />
<DoubleAnimation Storyboard.TargetProperty="Opacity" BeginTime="0:0:5" From="1.0" To="0.0" Duration="0:0:1.0" />
<DoubleAnimation Storyboard.TargetProperty="Width" BeginTime="0:0:5" From="427.0" To="0.0" Duration="0:0:1.0" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
假设我们有一个 SampleListBox 和 AddButton:
<Grid>
<ListBox x:Name="SampleListBox" Width="400" Height="200" BorderThickness="1" BorderBrush="Black" DisplayMemberPath="Name" Background="AliceBlue" Loaded="SampleListBox_Loaded" />
<Button Content="Add" Width="50" Height="30" VerticalAlignment="Bottom" Click="AddButton_Click" />
</Grid>
AddButton_Click 列表:
private void AddButton_Click(object sender, RoutedEventArgs e)
{
PersonListBox.Add(new Person()
{
Name = "NewItem",
});
SampleListBox.ItemsSource = PersonListBox;
}
在 SampleListBox_Loaded 中,我初始化 SampleListBox 的数据并分配一个处理程序NotifyCollectionChangedEventHandler,该处理程序在集合更改时调用。SampleListBox_Loaded 事件列表:
private void SampleListBox_Loaded(object sender, RoutedEventArgs e)
{
PersonListBox.Add(new Person()
{
Name = "Peter Orange",
Age = 32,
Sample = "Sample",
});
SampleListBox.ItemsSource = PersonListBox;
PersonListBox.CollectionChanged += new NotifyCollectionChangedEventHandler(PersonListBox_CollectionChanged);
}
在 PersonListBox_CollectionChanged 中,我为依赖属性 AddNewItem 设置了值True。PersonListBox_CollectionChanged 列表:
private void PersonListBox_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Add)
{
MyDependencyClass.SetAddNewItem(WarningBorder, true);
}
}
现在,当将项目添加到集合中时会触发动画。如果添加另一个元素动画不会触发。所以她工作了,你需要为未来的显示动画折叠值:
private void ResetButton_Click(object sender, RoutedEventArgs e)
{
MyDependencyClass.SetAddNewItem(WarningBorder, false);
}
在这种情况下,您需要决定何时重置动画的值。
编辑:
为了使添加的项目动画化,我基于我之前的示例。但是现在将为ListBoxItem分配带有DataTrigger的样式:
<ListBox x:Name="SampleListBox" local:MyDependencyClass.AddNewItem="False" local:MyDependencyClass.InitCountOfList="0" Width="400" Height="200" BorderThickness="1" BorderBrush="Black" DisplayMemberPath="Name" Background="AliceBlue" Loaded="SampleListBox_Loaded">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding ElementName=SampleListBox, Path=(local:MyDependencyClass.AddNewItem), Mode=OneWay}" Value="True" />
<Condition Binding="{Binding ElementName=SampleListBox, Converter={StaticResource BoolToInitItemsConverter}}" Value="True" />
</MultiDataTrigger.Conditions>
<MultiDataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" BeginTime="0:0:0" From="0.0" To="1.0" Duration="0:0:1.0" />
</Storyboard>
</BeginStoryboard>
</MultiDataTrigger.EnterActions>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
为了正确工作,动画(尤其是在程序开始时)是根据另一个属性创建的 - InitCountOfList (Int):
public class MyDependencyClass : DependencyObject
{
public static readonly DependencyProperty AddNewItemProperty, InitCountOfListProperty;
#region AddNewItem
public static void SetAddNewItem(DependencyObject DepObject, bool value)
{
DepObject.SetValue(AddNewItemProperty, value);
}
public static bool GetAddNewItem(DependencyObject DepObject)
{
return (bool)DepObject.GetValue(AddNewItemProperty);
}
#endregion
#region InitCountOfList
public static void SetInitCountOfList(DependencyObject DepObject, int value)
{
DepObject.SetValue(InitCountOfListProperty, value);
}
public static int GetInitCountOfList(DependencyObject DepObject)
{
return (int)DepObject.GetValue(InitCountOfListProperty);
}
#endregion
#region Constructor of DependencyProperty
static MyDependencyClass()
{
PropertyMetadata BoolPropertyMetadata = new PropertyMetadata(false);
PropertyMetadata IntPropertyMetadata = new PropertyMetadata(0);
AddNewItemProperty = DependencyProperty.RegisterAttached("AddNewItem",
typeof(bool),
typeof(MyDependencyClass),
BoolPropertyMetadata);
InitCountOfListProperty = DependencyProperty.RegisterAttached("InitCountOfList",
typeof(int),
typeof(MyDependencyClass),
IntPropertyMetadata);
}
#endregion
}
数据在 Window_ContentRendered 事件中初始化:
private void Window_ContentRendered(object sender, EventArgs e)
{
PersonListBox.Add(new Person()
{
Name = "Peter Orange",
});
SampleListBox.ItemsSource = PersonListBox;
// Set the initial number of collection
MyDependencyClass.SetInitCountOfList(SampleListBox, SampleListBox.Items.Count);
}
处理程序 NotifyCollectionChangedEventHandler在 SampleListBox_Loaded 事件中分配:
private void SampleListBox_Loaded(object sender, RoutedEventArgs e)
{
PersonListBox.CollectionChanged += new NotifyCollectionChangedEventHandler(PersonListBox_CollectionChanged);
}
Handler 和 AddButton_Click 保持不变:
private void PersonListBox_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Add)
{
MyDependencyClass.SetAddNewItem(SampleListBox, true);
}
}
private void AddButton_Click(object sender, RoutedEventArgs e)
{
PersonListBox.Add(new Person()
{
Name = "NewItem",
});
}
Converter BoolToInitItemsConverter,如果在开始期间没有添加元素,则返回 true:
/// <summary>
/// Return true, if count of collection > initial
/// </summary>
public class BoolToInitItemsConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
ListBox MyListBox = value as ListBox;
int InitCountOfList = MyDependencyClass.GetInitCountOfList(MyListBox);
if (MyListBox.Items.Count > InitCountOfList)
{
// Added a new element
return true;
}
// First run and we do not want
// to run the animation
return false;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return DependencyProperty.UnsetValue as object;
}
}
现在动画工作仅适用于添加的项目。