当前位置: 首页 > news >正文

WPF——动态排名图表实现

开发环境

VS2022

.NET 8.0

MVVM Toolkit 8.2.2

需求

开发中需要实现按照成绩动态指名,以展示当前的竞赛成绩的一个实时情况及变化。

即如下效果:

需求分析

按照接收到的信息,就是要将获取到的集合排序,并且要将排序前后的变化,要能在UI上动态的表示出来,以直观的显示排名的变化效果。

UI上的排名上升与下降的实现,本质就是当前显示控件位置的变化,最方便的方式肯定是在Canvas上设置它的Top位置了,然后再有一个从原位置到新位置过度动画,那么就好了。

按上述思路,首先想到的就是自定义控件,完全自定义控件有点麻烦,最后决定使用常用的集合控件 ItemsControl(其子控件也行,但仅用ListView尝试过)来进行实现。

代码实现

VM及Model:

    internal partial class MainWindowViewModel : ObservableRecipient{[ObservableProperty]ObservableCollection<Person> persons =[new Person() { Id = 1, Name = "张三", Age = 18, Gender = "男", Address = "北京", Grade = "一年级" ,Y=50,OldY=50,Score=40},new Person() { Id = 2, Name = "李四", Age = 19, Gender = "女", Address = "上海", Grade ="二年级",Y=100,OldY=100,Score=60},new Person() { Id = 3, Name = "王五", Age = 20, Gender = "男", Address = "广州", Grade = "三年级" ,Y=150,OldY=150,Score=90},];Timer timer;public MainWindowViewModel(){timer = new Timer(OnTimer, null, 0,1000);}private void OnTimer(object? state){Dispatcher.CurrentDispatcher.Invoke(() =>{Random random = new();var index = random.Next(0, 3);Persons[index].Score = random.Next(0, 100);var sorts = Persons.OrderBy(p => p.Score);int i = 0;foreach (var item in sorts){item.Id = ++i;item.Y = i * 50;}});}}public partial class Person : ObservableObject{[ObservableProperty]private int id;[ObservableProperty]private string name;[ObservableProperty]private int age;[ObservableProperty]private string gender;[ObservableProperty]private string address;[ObservableProperty]private string grade;private int y;public int Y{get => y;set{if (y != value){OldY = y; //记录旧值SetProperty(ref y, value);}}}[ObservableProperty]private int oldY;[ObservableProperty]private int score;}

Xaml中绑定如下,注意下述代码中的ZContentPresenter为自定义控件:

 <ItemsControlx:Name="myItemsControl"Margin="10"ItemsSource="{Binding Persons}"><ItemsControl.ItemsPanel><ItemsPanelTemplate><Canvas /></ItemsPanelTemplate></ItemsControl.ItemsPanel><ItemsControl.ItemTemplate><DataTemplate><control:ZContentPresenterx:Name="presenter"Content="{Binding}"Top="{Binding Y}"><ContentPresenter.ContentTemplate><DataTemplate><StackPanel Orientation="Horizontal"><TextBox Text="{Binding Id}" /><TextBox Text="{Binding Name}" /><TextBox Text="{Binding Age}" /><TextBox Text="{Binding Y}" /></StackPanel></DataTemplate></ContentPresenter.ContentTemplate></control:ZContentPresenter></DataTemplate></ItemsControl.ItemTemplate></ItemsControl>

对于 UI中的ZContentPresenter为自定义控件,其代码如下:

    public class ZContentPresenter : ContentPresenter{public ZContentPresenter(){}public int Top{get { return (int)GetValue(TopProperty); }set { SetValue(TopProperty, value); }}public static readonly DependencyProperty TopProperty =DependencyProperty.Register("Top", typeof(int), typeof(ZContentPresenter), new PropertyMetadata(0, TopChanged));private static void TopChanged(DependencyObject d, DependencyPropertyChangedEventArgs e){if (d is ZContentPresenter control){var oldValue = (int)e.OldValue;var newValue = (int)e.NewValue;var parent=(ContentPresenter)control.VisualParent;StartAnimation((double)(oldValue), (double)(newValue), parent);}}private static void StartAnimation(double from, double to, FrameworkElement element){Storyboard storyboard = new();DoubleAnimation animation = new(){From = from,To = to,Duration = TimeSpan.FromSeconds(0.5),AutoReverse = false,RepeatBehavior = new RepeatBehavior(1)};Storyboard.SetTarget(animation, element);Storyboard.SetTargetProperty(animation, new PropertyPath(Canvas.TopProperty));//Storyboard.SetTargetProperty(animation, new PropertyPath("(Canvas.Top)"));storyboard.Children.Add(animation);storyboard.Begin();
/*            storyboard.Completed += (sender, e) =>{storyboard.Stop();};*/}}

那为什么不直接在ItemContainerStyle中直接使用样式与Trigger中设置动画来实现呢?

这涉及到Trigger不能侦听Y值的实时变化,另外还有一个问题就是在Animation中不能绑定From与To值,若From或To采用绑定,会导致出现报错:无法冻结此 Storyboard 时间线树供跨线程使用。

注意事项

1. 自定义控件中的

 Storyboard.SetTargetProperty(animation, new PropertyPath("(Canvas.Top)"));

这种写法与

Storyboard.SetTargetProperty(animation, new PropertyPath(Canvas.TopProperty));

是等价的,并且不能将括号去掉。

2. 另外就是一定要绑定Top属性为你指定的离Canvas顶部的距离,本例中以Y值进行绑定

3. 虽然已经将ItemsControl中的DataTemplate的ContentPresneter改用了ZContentPresneter(即使将ContentPresenter.ContentTemplate也改为了ZContentPresneter.ContentTemplate,也没有效果),但若要改写ItemsControl的ItemContainerStyle,它的TargetType仍还是只能为ContentPresenter,它的默认容器就是ContentPresenter,暂未发现如何将默认的容器改为ZContentPresneter。也就是说目前还只能如下设置:

            <ItemsControl.ItemContainerStyle><Style TargetType="ContentPresenter"><Setter Property="Canvas.Left" Value="0" /><Setter Property="Canvas.Top" Value="{Binding OldY}" /><Style.Triggers><DataTrigger Binding="{Binding Y, UpdateSourceTrigger=PropertyChanged}" Value="50"><DataTrigger.EnterActions><BeginStoryboard><Storyboard><DoubleAnimationAutoReverse="false"RepeatBehavior="1"Storyboard.TargetProperty="(Canvas.Top)"From="5"To="20"Duration="0:0:1" /></Storyboard></BeginStoryboard></DataTrigger.EnterActions></DataTrigger></Style.Triggers></Style></ItemsControl.ItemContainerStyle>

相关文章:

WPF——动态排名图表实现

开发环境 VS2022 .NET 8.0 MVVM Toolkit 8.2.2 需求 开发中需要实现按照成绩动态指名&#xff0c;以展示当前的竞赛成绩的一个实时情况及变化。 即如下效果&#xff1a; 需求分析 按照接收到的信息&#xff0c;就是要将获取到的集合排序&#xff0c;并且要将排序前后的变…...

reactive() 的局限性

reactive() API 有一些局限性&#xff1a; 有限的值类型&#xff1a;它只能用于对象类型 (对象、数组和如 Map、Set 这样的集合类型)。它不能持有如 string、number 或 boolean 这样的原始类型。 不能替换整个对象&#xff1a;由于 Vue 的响应式跟踪是通过属性访问实现的&…...

stm32f407vet6驱动3.2寸lcd(9341 FSMC hal)

最近在钻研一些显示屏&#xff0c;研究到了lcd显示屏&#xff0c;然后入手了一块f407的开发板,但是店家给的资料有点怪&#xff0c;是keil4的工程,我一打开显示缺少f407vexxx&#xff0c;keil现在还巨慢&#xff0c;然后我到处找资料&#xff0c;发现网上大多是vgt6,又去各家ve…...

替换后的最长重复字符(LeetCode)

题目 给你一个字符串 s 和一个整数 k 。你可以选择字符串中的任一字符&#xff0c;并将其更改为任何其他大写英文字符。该操作最多可执行 k 次。 在执行上述操作后&#xff0c;返回 包含相同字母的最长子字符串的长度。 解题 def characterReplacement(s, k):count {}max_len…...

[sqlserver][sql]sqlserver查询表信息和字段信息

--查询一个表中的所有字段 SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAMEzsyh_AccInfo --查询一个库下的所有表 select * from sysobjects where xtypeU --查询一个数据库下的所有字段 SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME in(select nam…...

easypoi模板导出word并且合并行

导出流程 引入依赖制作模板合并导出 引入依赖 <dependency><groupId>cn.afterturn</groupId><artifactId>easypoi-base</artifactId><version>4.1.2</version> </dependency>制作模板 合并行是备注那一列&#xff0c;这一列…...

雨云美国二区E5v2服务器测评(非广告)

注&#xff1a;本文非广告&#xff0c;非推广 本文长期更新地址&#xff1a; 雨云美国二区E5v2服务器测评&#xff08;非广告&#xff09;-星零岁的博客https://blog.0xwl.com/13594.html 今天来测评一下雨云美国二区v2服务器。我测试的这台配置是4-8&#xff0c; 35 M上传&a…...

前端form表单post请求

前端请求post&#xff0c;以表单的形式&#xff0c;后端传来的str,就是url携带的参数 const form document.createElement(form); form.style.display none; form.setAttribute(target, _blank); form.setAttribute(method, post); form.setAttribute(action,url); var vars …...

oracle共享池(shared pool):一、工作原理、组成部分 二、软硬解析过程

文章目录 oracle整体结构图共享池&#xff08;shared pool&#xff09;shared pool的作用shared pool的组成查询 shared pool 各组成部分大小硬解析和软解析 oracle整体结构图 共享池&#xff08;shared pool&#xff09; shared pool的作用 1、 将 sql 语句解析成执行计划 …...

设计模式六大原则中的里氏替换原则

设计模式六大原则中的里氏替换原则&#xff08;Liskov Substitution Principle, LSP&#xff09;是面向对象设计中一个至关重要的原则&#xff0c;它定义了继承的基本原则和约束&#xff0c;确保子类能够透明地替换父类&#xff0c;而不会破坏系统的正确性和稳定性。以下是对里…...

安装Cellpose

Cellpose是目前运用范围最广、效果最好的细胞分割模型&#xff0c;以下是安装方法。 3.1 安装cellpose 3.1.1 创建cellpose 打开Anaconda Navigator,如下图所示&#xff1a; 图3.1.1.1 Anaconda Navigator 依次点击 Environments、Create&#xff0c;在弹出的窗中&#xff0…...

图卷积神经网络算法

图神经网络 图卷积神经网络 GNN GCN 算法 咨询 图卷积神经网络&#xff08;GCN&#xff09; python D码&#xff0c;应用于节点分类。元学习&#xff0c;自监督学&#xff0c;transformer&#xff0c;lstm&#xff0c;cnn&#xff0c;bert&#xff0c;GAN&#xff0c;交通预测 …...

【C#】System.Text.Json

文章目录 主要特点使用场景基本用法序列化反序列化 自定义序列化与反序列化注意事项 System.Text.Json 是 .NET Core 3.0 及更高版本中引入的一个高性能的、低内存的 JSON 序列化与反序列化库。它是 .NET Core 和 .NET 5/6/7 等新版本中推荐的 JSON 处理方式&#xff0c;因为它…...

经典游戏,用java实现的坦克大战小游戏

今天给大家分享一个使用java编写的坦克大战小游戏&#xff0c;整体还是挺好玩的&#xff0c;通过对这款游戏的简单实现&#xff0c;加深对java基础的深刻理解。 一、设计思路 1.坦克大战小游戏通过java实现&#xff0c;其第一步需要先绘制每一关对应的地图&#xff0c;地图包括…...

linux开通端口命令

这块需要开通8088 8083 端口限制 查看已开放端口&#xff1a;sudo firewall-cmd --list-ports 开放8083端口&#xff1a;sudo firewall-cmd --add-port8088/tcp --permanent 开放8088端口&#xff1a;sudo firewall-cmd --add-port8083/tcp --permanent 移除端…...

5、并发锁机制之synchronized

并发锁机制之synchronized i/i--引起的线程安全问题分析原因分析i的JVM字节码指令i--的JVM 字节码指令结论 解决方案 synchronized的使用加锁方式使用synchronized解决之前的共享问题方式一方式二 synchronized底层实现原理分析查看synchronized的字节码指令序列重量级锁实现之…...

职场那些事:应对施暴者的智慧

在职场中&#xff0c;有些人用各种手段让你感到难受&#xff0c;让你屈服&#xff0c;甚至适应他们的变态心理。面对这种人&#xff0c;最重要的就是保持低调。&#x1f910; 很多同事选择倾诉&#xff0c;然而这其实是个大错特错。正如鲁迅所说&#xff0c;“同事间的悲欢并不…...

精细化管理和智慧化运营的智慧油站开源了。

AI视频监控平台简介 AI视频监控平台是一款功能强大且简单易用的实时算法视频监控系统。它的愿景是最底层打通各大芯片厂商相互间的壁垒&#xff0c;省去繁琐重复的适配流程&#xff0c;实现芯片、算法、应用的全流程组合&#xff0c;从而大大减少企业级应用约95%的开发成本。用…...

vue项目配置基础路由vue-router

1、运行以下命令安装vue-router yarn add vue-router 2、在src目录下的components中新建两个vue页面 3、在src目录下新建router文件夹&#xff0c;在router文件夹下面新建index.js文件 4、配置main.js文件 //引入Vue import Vue from "vue"; //引入App import App…...

2024年入职/转行网络安全,该如何规划?_网络安全职业规划

前言 前段时间&#xff0c;知名机构麦可思研究院发布了 《2022年中国本科生就业报告》&#xff0c;其中详细列出近五年的本科绿牌专业&#xff0c;其中&#xff0c;信息安全位列第一。 网络安全前景 对于网络安全的发展与就业前景&#xff0c;想必无需我多言&#xff0c;作为…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器

一.自适应梯度算法Adagrad概述 Adagrad&#xff08;Adaptive Gradient Algorithm&#xff09;是一种自适应学习率的优化算法&#xff0c;由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率&#xff0c;适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

从WWDC看苹果产品发展的规律

WWDC 是苹果公司一年一度面向全球开发者的盛会&#xff0c;其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具&#xff0c;对过去十年 WWDC 主题演讲内容进行了系统化分析&#xff0c;形成了这份…...

Spring数据访问模块设计

前面我们已经完成了IoC和web模块的设计&#xff0c;聪明的码友立马就知道了&#xff0c;该到数据访问模块了&#xff0c;要不就这俩玩个6啊&#xff0c;查库势在必行&#xff0c;至此&#xff0c;它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据&#xff08;数据库、No…...

蓝桥杯3498 01串的熵

问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798&#xff0c; 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...

RSS 2025|从说明书学习复杂机器人操作任务:NUS邵林团队提出全新机器人装配技能学习框架Manual2Skill

视觉语言模型&#xff08;Vision-Language Models, VLMs&#xff09;&#xff0c;为真实环境中的机器人操作任务提供了极具潜力的解决方案。 尽管 VLMs 取得了显著进展&#xff0c;机器人仍难以胜任复杂的长时程任务&#xff08;如家具装配&#xff09;&#xff0c;主要受限于人…...

mac 安装homebrew (nvm 及git)

mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用&#xff1a; 方法一&#xff1a;使用 Homebrew 安装 Git&#xff08;推荐&#xff09; 步骤如下&#xff1a;打开终端&#xff08;Terminal.app&#xff09; 1.安装 Homebrew…...

Web后端基础(基础知识)

BS架构&#xff1a;Browser/Server&#xff0c;浏览器/服务器架构模式。客户端只需要浏览器&#xff0c;应用程序的逻辑和数据都存储在服务端。 优点&#xff1a;维护方便缺点&#xff1a;体验一般 CS架构&#xff1a;Client/Server&#xff0c;客户端/服务器架构模式。需要单独…...

前端高频面试题2:浏览器/计算机网络

本专栏相关链接 前端高频面试题1&#xff1a;HTML/CSS 前端高频面试题2&#xff1a;浏览器/计算机网络 前端高频面试题3&#xff1a;JavaScript 1.什么是强缓存、协商缓存&#xff1f; 强缓存&#xff1a; 当浏览器请求资源时&#xff0c;首先检查本地缓存是否命中。如果命…...

何谓AI编程【02】AI编程官网以优雅草星云智控为例建设实践-完善顶部-建立各项子页-调整排版-优雅草卓伊凡

何谓AI编程【02】AI编程官网以优雅草星云智控为例建设实践-完善顶部-建立各项子页-调整排版-优雅草卓伊凡 背景 我们以建设星云智控官网来做AI编程实践&#xff0c;很多人以为AI已经强大到不需要程序员了&#xff0c;其实不是&#xff0c;AI更加需要程序员&#xff0c;普通人…...

深度解析:etcd 在 Milvus 向量数据库中的关键作用

目录 &#x1f680; 深度解析&#xff1a;etcd 在 Milvus 向量数据库中的关键作用 &#x1f4a1; 什么是 etcd&#xff1f; &#x1f9e0; Milvus 架构简介 &#x1f4e6; etcd 在 Milvus 中的核心作用 &#x1f527; 实际工作流程示意 ⚠️ 如果 etcd 出现问题会怎样&am…...