WPF:使用效果显示和隐藏 ItemsControl 中的项目

2023-11-26

我一直在使用这篇很棒的文章作为显示和隐藏具有过渡效果的元素的基础。它工作得非常巧妙,因为它可以让你绑定Visibility属性就像平常一样,然后定义当可见性发生变化时会发生什么(例如,设置其不透明度的动画或触发故事板)。当您隐藏某个元素时,它会使用值强制使其保持可见,直到转换完成。

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

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


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

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

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

代替绑定ItemsSource, 绑定附加属性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);
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

WPF:使用效果显示和隐藏 ItemsControl 中的项目 的相关文章

  • 按下按钮并在java中的新窗口中打开文件

    我创建了一个 JFrame 并放置了一个文本字段和按钮 在文本字段中我放置了从文本文件读取的名称 我知道我想单击按钮并打开一个已知窗口 我想在其中放置名称 其他信息来自同一个文件 这是我的代码 这是我的主框架 package Fronten
  • 带有图层列表的自定义背景以显示对角线?

    我只想创建一个自定义背景 但我不知道如何使用 xml 而不是图像来做到这一点 这是 XML
  • Relay/ICommand 与 DelegateCommand——差异

    据我所知 下面的代码可以从 Relay ICommand 命令更改为 Delegate 命令 并且仍然以相同的方式绑定命令 如果我错了 它们的区别和用途是什么 private DelegateCommand something public
  • 在简单注入器中解析具有自定义参数的类

    我正在使用以下命令创建 WPF MVVM 应用程序简易注射器作为 DI 容器 现在 当我尝试从简单注入器解析视图时遇到一些问题 因为我需要在构造时将参数传递到构造函数中 而不是在将视图注册到容器时 因此这不是适用的 简单注入器将值传递到构造
  • 我的 Powershell GUI 界面在打开网格视图时不断调整大小

    我目前正在构建一个复制到剪贴板工具 其中显示存储在文件夹中的 txt 文件列表 并且我使用 out gridview 来允许用户更好地选择和过滤列表 我已附上图片以供参考 单击加载 out gridview 的按钮后如何停止调整大小 Too
  • 在Linux上编译C# + WPF以便在Windows上运行

    我有一个 C 应用程序 其中某些部分是使用 WPF 编写的 Mono 不支持 可以在 Linux 上编译这个应用程序吗 最终 该应用程序将在 Windows 上运行 但它是更大框架的一部分 并且我们的整个构建过程在 Linux 上运行 因此
  • R 错误:无法更改锁定绑定的值

    我试图估计无限数字流的平均值和标准差 当我运行代码时 出现错误消息 无法更改锁定绑定的值 我做了一些研究 发现这个错误与我使用全局变量有关 但我无法弄清楚 任何帮助将非常感激 在此先感谢您的帮助 define global variable
  • 将多个实时视频流拉入 WPF

    我想创建一个应用程序 将由同轴电缆 hdmi 或其他标准提供的多个实时视频源拉入 WPF 中进行操作 即应用一些转换或像素着色器 然后将其输出到监视器 开始使用这个应用程序时我会考虑什么 有没有任何硬件可以让事情变得更容易 如果您通过同轴电
  • WPF DataGrid - 在每行末尾添加按钮

    我想在数据网格的每一行的末尾添加一个按钮 我找到了以下 xaml 但它将按钮添加到开头 有人知道如何在所有数据绑定列之后添加它吗 这会将按钮添加到开头而不是末尾
  • 删除 JFX 中选项卡后面的灰色背景

    So is there any way to remove the gray area behind the tab s 我尝试过用 CSS 来做到这一点 但没有找到方法 要设置 tabpane 标题的背景颜色 请在 CSS 文件中写入 t
  • 如何将 WPF UIElement 从可视化树移动到固定页面?

    我的 MVVM 应用程序使用屏幕上的视觉对象将屏幕内容渲染到打印文档 我的视图有一个ContentControl使用DataTemplate资源来确定要显示的内容 但是当我尝试将该内容添加到FixedPage对象 我得到一个Argument
  • 增加 WPF 弹出动画的持续时间

    我有一个 WPF PopUp 控件 用于显示菜单叠加层 并且使用默认的淡入淡出动画 不过我想让动画需要更长的时间才能完成 我可以在 XAML 中做到这一点吗 你能在这里发布相关的xaml代码吗 否则 您可以查看这些链接以开始使用 xaml
  • 如何将 WPF 窗口置于前面?

    我创建了一个单实例应用程序 并且希望在用户多次启动该应用程序时激活已打开的窗口 这工作正常 但我有一个问题 如果已经打开的窗口超出了另一个应用程序窗口 我必须将其放在前面 我尝试过 window Focus 和 window Show 但它
  • .NET UI 元素线程限制的原因

    我们知道 除了实例化元素的线程之外 不可能从任何线程执行操作任何 UI 元素属性的代码 我的问题是 为什么 我记得当我们使用 COM 用户界面元素时 在 COM Visual Basic 6 0 时代 所有 UI 元素都是使用 COM 类和
  • 跨项目/dll 访问 Xaml 中的资源

    是否可以从另一个项目引用存储在 ResourceDictionary 构建操作 资源 中的 Xaml 资源 我想将资产合并到主项目的资源字典中或单独访问它们 例如 项目 MyResources 包含一个名为 Assets 的文件夹 其中有一
  • 如何创建向后兼容 Windows 7 的缩放和尺寸更改每显示器 DPI 感知应用程序?

    我是 WPF 和 DPI 感知 API 的新手 正在编写一个在 Windows 7 8 1 和 10 中运行的应用程序 我使用具有不同每个显示器 DPI 设置的多个显示器 并且有兴趣将我的应用程序制作为跨桌面配置尽可能兼容 我已经知道可以将
  • 在 WPF 中将 png 图像合并为单个图像

    我正在寻找一种将一些 PNG 平铺图像合并为大图像的方法 所以我搜索并找到了一些链接 This https stackoverflow com questions 6325057 c sharp combine lots of images
  • 如何解决 Laravel 8 UI 分页问题?

    我在尝试最近发布的 laravel 8 时遇到了问题 我试图找出变化是什么以及它是如何工作的 当我这样做时 我遇到了分页 laravel 8 UI 变得混乱的问题 不知何故它发生了 有人可以帮助我吗 或者经历过同样的事情 像这样我在 lar
  • 如何在 wpf 应用程序的代码隐藏中创建集合视图源

    我有以下代码 public partial class MainWindow Window public MainWindow InitializeComponent var entities new DemoEntities var de
  • 如何在MVVM中管理多个窗口

    我知道有几个与此类似的问题 但我还没有找到明确的答案 我正在尝试深入研究 MVVM 并尽可能保持纯粹 但不确定如何在坚持模式的同时启动 关闭窗口 我最初的想法是向 ViewModel 发送数据绑定命令 触发代码来启动一个新视图 然后通过 X

随机推荐

  • Django/mod_wsgi OSError: [Errno 13] 权限被拒绝: 当 DEBUG = OFF 时为“静态”

    我在 Centos 6 2 服务器 运行 apache mysql php 上有一个 Django 1 4 应用程序 使用 mod wsgi 并将我的项目部署在虚拟环境中 该应用程序本身是我在托管服务上使用多年的应用程序 现在我正在自己的机
  • next.js getStaticPaths 列出每个路径还是仅列出附近的路径?

    使用 Next js 导出静态页面 我在动态路由中得到了这样的结果pages id js我放入的任何路径getStaticPaths将创建部分 凉爽的 列出每一页是否更好 getStaticPaths return some functio
  • 将 Powerpoint 演示嵌入到 C# 应用程序中

    我希望能够将 powerpoint 演示文稿嵌入到 C 表单 WinForms 中 基本上我们有一台 52 英寸的显示器 其想法是在一个角落循环播放 PPT 然后其他 3 个角落将显示程序本身的信息 我原以为这会很简单 但看来我错了 有人建
  • Windows 文件路径路径中的空格

    我正在使用 python 进行文件操作 我的文件路径为 filepath E ABC SEM 2 testfiles all txt 当我使用 python 打开文件时 它说 IOError No such file 但是 该文件存在于驱动
  • 如何在重定向到外部页面之前在 jquery 中预加载(缓存)该页面?

    我正在做一个phonegap应用程序 我有一个 index html 页面 其中有一个重定向到网站应用程序的登录按钮 当点击登录按钮时 我想要一个加载 gif 来显示页面 正在被缓存 预加载并在完成后重定向到页面 我希望有一个示例脚本代码
  • 改变material-ui按钮的字体大小,并让按钮缩放?

    我似乎在更改 Material UI 用于 React RaishedButton 上的字体大小以及让按钮本身与其正确缩放时遇到问题
  • Visual Studio 中的静态和动态链接

    我理解静态和动态链接的概念 据了解 在Windows平台上 dll是动态库和 lib是静态库 我的困惑 我做了一个必须使用 OpenCV 库的项目 基本上 我必须使用以下 5 个 OpenCV 库 lopencv core lopencv
  • jQuery $.post 和 json_encode 返回一个带有引号的字符串

    我正在使用 jQuery 的 post 调用 它返回一个带有引号的字符串 引号是由 json encode 行添加的 如何阻止添加引号 我在 post 通话中遗漏了什么吗 post getSale php function data con
  • 检查表是否存在[重复]

    这个问题在这里已经有答案了 我有一个桌面应用程序 其中嵌入了数据库 当我执行程序时 我需要检查特定的表是否存在 如果不存在则创建它 给定我的数据库的名为 conn 的 Connection 对象 我如何检查它 DatabaseMetaDat
  • JavaScript 执行连接到 mongoHQ shell 失败

    尝试直接访问 MongoHQ gt mongo mongodb heroku email protected 10046 myapp MongoDB shell version 2 4 3 connecting to mongodb her
  • 是否可以通过编程方式清除控制台历史记录?

    使用控制台应用程序时 在某个位置输入的所有内容的历史记录Console ReadLine 被储存了 当控制台提示输入某些内容时 按向上 向下光标将滚动浏览此历史记录 并且可以通过按 F7 查看整个历史记录 使用 C 是否有办法禁用此行为或清
  • 从 YouTube 网址获取持续时间

    我正在寻找一个函数 可以从 url 中提取视频的 YouTube 持续时间 我读了一些教程但不明白 我使用网址在我的网站上嵌入视频 并且我有一个提取缩略图的功能 我只想要类似的东西来获取持续时间 这是我如何获得拇指 function get
  • iOS:应用程序内购买管理多个自动续订订阅,具有升级和降级选项

    我们正在为 iPhone 开发一款 iOS 应用程序 该应用程序将具有免费功能 并且该应用程序将具有高级功能 其中有 4 个应用程序内购买自动续订订阅选项 如下所示 单月订阅 单年订阅 家庭包月 家庭每年订阅 我们将在应用程序内有一个商店屏
  • Flask 下载文件

    我正在尝试使用 Flask 创建一个网络应用程序 让用户上传文件并将其提供给另一个用户 现在 我可以将文件上传到上传文件夹正确 但我似乎找不到一种方法让用户下载回来 我将文件名存储到数据库中 我有一个为数据库对象提供服务的视图 我也可以删除
  • 在 Jenkins 从节点上运行的 Jenkinsfile 中执行 docker build 命令的最简单方法?

    我希望 Jenkinsfile 执行的操作的基本示例 node sh docker build t foo bar 看来我需要将 docker 安装到正在执行 Jenkinsfile 的 Jenkins 从属映像上 有一个简单的方法可以做到
  • 关闭来自服务器的 akka-http websocket 连接

    在我的场景中 客户端发送 再见 websocket 消息 我需要关闭之前在服务器端建立的连接 来自 akka httpdocs 通过从服务器逻辑取消传入连接 Flow 可以关闭连接 例如 通过将其下游连接到 Sink cancelled 将
  • contenteditable 无法在 IE 10 中工作

    我正在尝试创建客户端可编辑表 这是我的代码 它适用于 Chrome Firefox 但不适用于 IE 还有什么与 IE 脚本有关的吗
  • 如何使用java压缩文件夹本身

    假设我有以下目录结构 D reports january 假设一月份有两个 Excel 文件 分别为 A xls 和 B xls 有很多地方都写过如何使用压缩文件java util zip 但我想将 january 文件夹本身压缩到 rep
  • Base64 背景图像多行?

    是否可以放base64背景图像是多行而不是一长行 如果是这样 怎么办 我当前的主体 CSS 是 body background color FFFFFF background image url data image png base64
  • WPF:使用效果显示和隐藏 ItemsControl 中的项目

    我一直在使用这篇很棒的文章作为显示和隐藏具有过渡效果的元素的基础 它工作得非常巧妙 因为它可以让你绑定Visibility属性就像平常一样 然后定义当可见性发生变化时会发生什么 例如 设置其不透明度的动画或触发故事板 当您隐藏某个元素时 它