gpt4 book ai didi

WPF:在带有效果的 ItemsControl 中显示和隐藏项目

转载 作者:行者123 更新时间:2023-12-04 11:29:37 25 4
gpt4 key购买 nike

我一直在使用this great article作为显示和隐藏具有过渡效果的元素的基础。它工作得非常巧妙,因为它可以让你绑定(bind) Visibility属性正常,然后定义可见性变化时发生的情况(例如,为其不透明度设置动画或触发 Storyboard )。当你隐藏一个元素时,它使用值强制来保持它可见,直到转换完成。

我正在寻找与 ItemsControl 一起使用的类似解决方案和 ObservableCollection .换句话说,我想绑定(bind) ItemsSourceObservableCollection正常,但控制添加和删除项目并触发动画时发生的情况。我不认为在这里使用值强制会起作用,但显然,项目仍然需要保留在列表中,直到它们的转换完成。有谁知道任何现有的解决方案可以使这变得容易?

我希望任何解决方案都相当通用且易于应用于任何类型的项目列表。理想情况下,样式和动画行为是分开的,将其应用于特定列表将是一项简单的任务,例如为其赋予附加属性。

最佳答案

淡入很容易,但是对于淡出,项目需要保留在源列表中,直到动画完成(如您所说)。

如果我们仍然希望能够使用源 ObservableCollection通常(添加/删除等)然后我们必须创建一个镜像集合,它与源集合不断同步,并延迟删除直到动画完成。这可以通过 CollectionChanged 来完成。事件。

这是我使用附加行为实现的。可用于ItemsControl , ListBox , DataGrid或源自 ItemsControl 的任何其他内容.

而不是绑定(bind)ItemsSource ,绑定(bind)附加属性ItemsSourceBehavior.ItemsSource .它将创建一个镜像 ObservableCollection使用反射,将镜子用作ItemsSource而是处理 FadeIn/FadeOut动画。
请注意,我尚未对此进行广泛测试,并且可能存在错误和可以进行的一些改进,但它在我的场景中效果很好。

示例使用

<ListBox behaviors:ItemsSourceBehavior.ItemsSource="{Binding MyCollection}">
<behaviors:ItemsSourceBehavior.FadeInAnimation>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity"
From="0.0"
To="1.0"
Duration="0:0:3"/>
</Storyboard>
</behaviors:ItemsSourceBehavior.FadeInAnimation>
<behaviors:ItemsSourceBehavior.FadeOutAnimation>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity"
To="0.0"
Duration="0:0:1"/>
</Storyboard>
</behaviors:ItemsSourceBehavior.FadeOutAnimation>
<!--...-->
</ListBox>

项目来源行为
public class ItemsSourceBehavior
{
public static readonly DependencyProperty ItemsSourceProperty =
DependencyProperty.RegisterAttached("ItemsSource",
typeof(IList),
typeof(ItemsSourceBehavior),
new UIPropertyMetadata(null, ItemsSourcePropertyChanged));
public static void SetItemsSource(DependencyObject element, IList value)
{
element.SetValue(ItemsSourceProperty, value);
}
public static IList GetItemsSource(DependencyObject element)
{
return (IList)element.GetValue(ItemsSourceProperty);
}

private static void ItemsSourcePropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
{
ItemsControl itemsControl = source as ItemsControl;
IList itemsSource = e.NewValue as IList;
if (itemsControl == null)
{
return;
}
if (itemsSource == null)
{
itemsControl.ItemsSource = null;
return;
}

Type itemsSourceType = itemsSource.GetType();
Type listType = typeof(ObservableCollection<>).MakeGenericType(itemsSourceType.GetGenericArguments()[0]);
IList mirrorItemsSource = (IList)Activator.CreateInstance(listType);
itemsControl.SetBinding(ItemsControl.ItemsSourceProperty, new Binding{ Source = mirrorItemsSource });

foreach (object item in itemsSource)
{
mirrorItemsSource.Add(item);
}
FadeInContainers(itemsControl, itemsSource);

(itemsSource as INotifyCollectionChanged).CollectionChanged +=
(object sender, NotifyCollectionChangedEventArgs ne) =>
{
if (ne.Action == NotifyCollectionChangedAction.Add)
{
foreach (object newItem in ne.NewItems)
{
mirrorItemsSource.Add(newItem);
}
FadeInContainers(itemsControl, ne.NewItems);
}
else if (ne.Action == NotifyCollectionChangedAction.Remove)
{
foreach (object oldItem in ne.OldItems)
{
UIElement container = itemsControl.ItemContainerGenerator.ContainerFromItem(oldItem) as UIElement;
Storyboard fadeOutAnimation = GetFadeOutAnimation(itemsControl);
if (container != null && fadeOutAnimation != null)
{
Storyboard.SetTarget(fadeOutAnimation, container);

EventHandler onAnimationCompleted = null;
onAnimationCompleted = ((sender2, e2) =>
{
fadeOutAnimation.Completed -= onAnimationCompleted;
mirrorItemsSource.Remove(oldItem);
});

fadeOutAnimation.Completed += onAnimationCompleted;
fadeOutAnimation.Begin();
}
else
{
mirrorItemsSource.Remove(oldItem);
}
}
}
};
}

private static void FadeInContainers(ItemsControl itemsControl, IList newItems)
{
EventHandler statusChanged = null;
statusChanged = new EventHandler(delegate
{
if (itemsControl.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated)
{
itemsControl.ItemContainerGenerator.StatusChanged -= statusChanged;
foreach (object newItem in newItems)
{
UIElement container = itemsControl.ItemContainerGenerator.ContainerFromItem(newItem) as UIElement;
Storyboard fadeInAnimation = GetFadeInAnimation(itemsControl);
if (container != null && fadeInAnimation != null)
{
Storyboard.SetTarget(fadeInAnimation, container);
fadeInAnimation.Begin();
}
}
}
});
itemsControl.ItemContainerGenerator.StatusChanged += statusChanged;
}

public static readonly DependencyProperty FadeInAnimationProperty =
DependencyProperty.RegisterAttached("FadeInAnimation",
typeof(Storyboard),
typeof(ItemsSourceBehavior),
new UIPropertyMetadata(null));
public static void SetFadeInAnimation(DependencyObject element, Storyboard value)
{
element.SetValue(FadeInAnimationProperty, value);
}
public static Storyboard GetFadeInAnimation(DependencyObject element)
{
return (Storyboard)element.GetValue(FadeInAnimationProperty);
}

public static readonly DependencyProperty FadeOutAnimationProperty =
DependencyProperty.RegisterAttached("FadeOutAnimation",
typeof(Storyboard),
typeof(ItemsSourceBehavior),
new UIPropertyMetadata(null));
public static void SetFadeOutAnimation(DependencyObject element, Storyboard value)
{
element.SetValue(FadeOutAnimationProperty, value);
}
public static Storyboard GetFadeOutAnimation(DependencyObject element)
{
return (Storyboard)element.GetValue(FadeOutAnimationProperty);
}
}

关于WPF:在带有效果的 ItemsControl 中显示和隐藏项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6747491/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com