winform中也可以这样做数据展示✨

1、前言

在做winform开发的过程中,经常需要做数据展示的功能,之前一直使用的是gridcontrol控件,今天想通过一个示例,跟大家介绍一下如何在winform blazor hybrid中使用ant design blazor中的table组件做数据展示。

2、效果

先来看看实现的效果:

数据展现效果

image-20231215110015929

3、具体实现

怎么在winform blazor hybrid项目中使用Ant Design Blazor可以看我上篇文章。

引入Ant Design Blazor的Table组件:

 <Table TItem="IData" DataSource="@datas" 
     OnRowClick="OnRowClick" @ref="antTableRef" >
     <PropertyColumn Property="c=>c.StationName">            
     </PropertyColumn>
     <PropertyColumn Property="c=>c.Weather">
     </PropertyColumn>
     <PropertyColumn Property="c=>c.Tem_Low">            
     </PropertyColumn>
     <PropertyColumn Property="c=>c.Tem_High">           
     </PropertyColumn>
     <PropertyColumn Property="c=>c.Wind">
     </PropertyColumn>
     <PropertyColumn Property="c=>c.Visibility_Low">
     </PropertyColumn>
     <PropertyColumn Property="c=>c.Visibility_High">
     </PropertyColumn>
     <PropertyColumn Property="c=>c.Fog">
     </PropertyColumn>
     <PropertyColumn Property="c=>c.Haze">
     </PropertyColumn>
     <PropertyColumn Property="c=>c.Date">
     </PropertyColumn>
 </Table>

其中:

TItem表示DataSource中单个项的类型,从 0.16.0 开始,Table 已支持普通类、record、接口和抽象类作为 DataSource 的类型。

这里我的TItem设置为一个叫做IData的接口,它的定义如下:

public interface IData
{
    [DisplayName("站名")]
    public string? StationName { get; set; }
    [DisplayName("天气")]
    public string? Weather { get; set; }
    [DisplayName("最低温度/℃")]
    public string? Tem_Low { get; set; }
    [DisplayName("最高温度/℃")]
    public string? Tem_High { get; set; }
    [DisplayName("风力风向")]
    public string? Wind { get; set; }
    [DisplayName("最低可见度/km")]
    public string? Visibility_Low { get; set; }
    [DisplayName("最高可见度/km")]
    public string? Visibility_High { get; set; }
    [DisplayName("雾")]
    public string? Fog { get; set; }
    [DisplayName("霾")]
    public string? Haze { get; set; }
    [DisplayName("日期")]
    public DateTime? Date { get; set; }
}

其中的[DisplayName("站名")]是一个属性或成员的元数据注解,用于提供一个更友好的显示名称。Ant Design Blazor会自动使用这个来显示名称。

DataSource表示表格的数据源,类型为IEnumerable

image-20231215151309395

这里DataSource="@datas" 表示我将一个名为 datas 的数据源分配给Table组件的 DataSource 属性。

datas的定义如下:

 WeatherData[] datas = Array.Empty<WeatherData>();

WeatherData是自定义类,实现了IData接口:

    public class WeatherData : IData
    {
        [SugarColumn(IsPrimaryKey = true, IsIdentity = true)]
        public int Id { get; set; }     
        public string? StationName { get; set; }
        public string? Weather { get; set; }
        public string? Tem_Low { get; set; }
        public string? Tem_High { get; set; }
        public string? Wind { get; set; }
        public string? Visibility_Low { get; set; }
        public string? Visibility_High { get; set; }
        public string? Fog { get; set; }
        public string? Haze { get; set; }
        public DateTime? Date { get; set; }
    }
}

看到这里大家可能会有个疑问,那就是刚刚的TItem表示DataSource中单个项的类型,但是现在这里DataSourceWeatherData[],那么单个项的类型是WeatherData而不是刚刚设置的IData,这样可以吗?

通过以下这个简单的例子,可能你就会解开疑惑:

public interface IFlyable
{
    void Fly();
}
public class Bird : IFlyable
{
    public void Fly()
    {
        Console.WriteLine("The bird is flying.");
    }

}
class Program
{
    // 主方法
    static void Main()
    {
       Bird myBird = new Bird();
       IFlyable flyableObject = myBird; // 类型转换

        // 调用接口方法
        flyableObject.Fly();
    }
}

定义了一个IFlyable接口、一个Bird类,该类实现了IFlyable接口,在Main函数中,实例化了一个Bird类,然后该对象隐式转换为接口类型,再通过接口调用实现类的方法,输出结果为:

The bird is flying.

这说明C# 中当一个类实现了一个接口时,该类的实例可以被隐式转换为该接口类型。这里就是WeatherData会被隐式转化为了IData

DataSource也是一样,虽然官方文档上写的类型是IEnumerable,但是我们这里确是WeatherData[]这样也可以,也是因为Array实现了IEnumerable接口,如下所示:

image-20231215155107743

OnRowClick表示行点击事件,类型为EventCallback<RowData>,本例中实际上没有用到。

在Blazor中,@ref 是一个用于在Blazor组件中引用HTML元素或组件实例的指令。通过使用 @ref,你可以在Blazor组件中获取对DOM元素或子组件的引用,然后在代码中进行操作或访问其属性和方法。

这里我在Table组件上添加了@ref=“antTableRef”,在代码区域添加了:

 Table<IData>? antTableRef;

就成功引用了Table组件实例。

<PropertyColumn>表示属性列,也就是要展示的列。它的Property属性指定要绑定的属性,类型为Expression<Func<TItem, TProp>>

这里大家可能会有疑问,Expression<Func<TItem, TProp>>到底是啥呀?

Expression<Func<TItem, TProp>> 是C#中的一个表达式树,用于表示一个参数为 TItem 类型且返回值为 TProp 类型的lambda表达式。

拆开来看,Expression<T> 是一个表示lambda表达式的树状结构的类,其中 T 是委托类型。详细学习,可以查看官方文档:

image-20231215160753817

Func<TItem, TProp> 是一个泛型委托类型,表示一个带有一个输入参数和一个输出参数的方法,详细学习,也可以查看官方文档:

image-20231215160924173

这里也通过一个简单的例子进行说明:

Expression<Func<Person, string>> getNameExpression = person => person.Name;

getNameExpression表示一个Lambda表达式,一个什么样的Lambda表达式呢?一个输入参数类型为Person对应这里的person、输出类型为string对应这里的person.Name的一个Lambda表达式。

所以代码:

<PropertyColumn Property="c=>c.StationName">            
</PropertyColumn>

就可以理解了,Property的类型是一个输入参数类型为TItem这里TItem的类型就是IData、输出类型为TProp这里TProp类型就是string的一个Lamda表达式c=>c.StationName

理解了以上之后,我们看看这部分的代码:

image-20231215162534740

代码如下:

<GridRow>
      <Space>
            <SpaceItem>
                <Text Strong>开始日期:</Text>
            </SpaceItem>
            <SpaceItem>
                <DatePicker TValue="DateTime?" Format="yyyy/MM/dd" 
                Mask="yyyy/dd/MM" Placeholder="@("yyyy/dd/MM")"
                @bind-Value = "Date1"/>
            </SpaceItem>
            <SpaceItem>
                <Text Strong>结束日期:</Text>
            </SpaceItem>
            <SpaceItem>
                <DatePicker TValue="DateTime?" Format="yyyy/MM/dd" 
                Mask="yyyy/dd/MM" Placeholder="@("yyyy/dd/MM")"
                @bind-Value = "Date2"/>
            </SpaceItem>
        <SpaceItem>
            <Text Strong>站名:</Text>
        </SpaceItem>
        <SpaceItem>
            <AutoComplete @bind-Value="@value"
                          Options="@options"
                          OnSelectionChange="OnSelectionChange"
                          OnActiveChange="OnActiveChange"
                          Placeholder="input here" 
                          Style="width:150px"/>
        </SpaceItem>
        <SpaceItem>
            <Button Type="@ButtonType.Primary" OnClick="QueryButton_Clicked">查询</Button>
        </SpaceItem>
        </Space>
</GridRow>

站名自动填充:

  <AutoComplete @bind-Value="@value"
                          Options="@options"
                          OnSelectionChange="OnSelectionChange"
                          OnActiveChange="OnActiveChange"
                          Placeholder="input here" 
                          Style="width:150px"/>

这个的实现,在上篇文章中已经介绍了,这里就不再重复讲了。

两个日期选择组件都使用了数据绑定:

 <SpaceItem>
     <DatePicker TValue="DateTime?" Format="yyyy/MM/dd" 
                 Mask="yyyy/dd/MM" Placeholder="@("yyyy/dd/MM")"
                @bind-Value = "Date1"/>
</SpaceItem>
     
 <SpaceItem>
      <DatePicker TValue="DateTime?" Format="yyyy/MM/dd" 
                Mask="yyyy/dd/MM" Placeholder="@("yyyy/dd/MM")"
                @bind-Value = "Date2"/>
 </SpaceItem>

其中:

TValue表示值的类型,这里设置为DateTime?

@bind-Value进行数据绑定,将日期选择组件的值与Date1和Date2绑定起来:

 DateTime? Date1;
 DateTime? Date2;

查询按钮:

<Button Type="@ButtonType.Primary" OnClick="QueryButton_Clicked">查询</Button>

点击事件代码:

async void QueryButton_Clicked()
{
    if (Date1 != null && Date2 != null && value != null)
    {
        var cofig = new MessageConfig()
            {
                Content = "正在更新中...",
                Duration = 0
            };
        var task = _message.Loading(cofig);
        var condition = new Condition();
        condition.StartDate = (DateTime)Date1;
        condition.EndDate = (DateTime)Date2;
        condition.StationName = value;
        datas = weatherServer.GetDataByCondition(condition).ToArray();
        StateHasChanged();  
        task.Start();
    }
    else
    {
        await _message.Error("请查看开始日期、结束日期与站名是否都已选择!!!");
    }
}

当条件成立时,创建Condition类型,写入开始日期、结束日期和站名,Condition类的定义如下:

 public class Condition
 {
     public DateTime StartDate{ get; set; }
     public DateTime EndDate { get; set; }
     public string? StationName { get; set; }     
 }

然后调用业务逻辑层的weatherServer中的GetDataByCondition方法:

 datas = weatherServer.GetDataByCondition(condition).ToArray();

weatherServer中的GetDataByCondition方法如下:

 public List<WeatherData> GetDataByCondition(Condition condition)
 {
     return dataService.GetDataByCondition(condition);
 }

因为涉及到数据库的读写,因此调用了数据库访问层中的dataService的GetDataByCondition方法。

数据库访问层中的dataService的GetDataByCondition方法如下:

  public List<WeatherData> GetDataByCondition(Condition condition)
  {
      return db.Queryable<WeatherData>()
               .Where(x => x.Date >= condition.StartDate &&
                           x.Date < condition.EndDate.AddDays(1) &&
                           x.StationName == condition.StationName).ToList();
  }

当重新查询时:

 StateHasChanged();  

调用这个方法组件会进行更新。在Blazor中,StateHasChanged 是一个方法,用于通知Blazor框架重新渲染组件及其子组件。Blazor组件的UI渲染是基于组件的状态(state)的,当组件的状态发生变化时,需要调用 StateHasChanged 方法来通知框架进行重新渲染。

 var cofig = new MessageConfig()
            {
                Content = "正在更新中...",
                Duration = 0
            };
 var task = _message.Loading(cofig);
 task.Start();

是给用户信息提示。

4、总结

以上通过一个完整的例子,说明了在winform中除了可以用girdcontrol做数据展示外也可以使用Ant Design Blazor中的Table做数据展示。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/248177.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MYSQL练题笔记-子查询-换座位

一、题目相关内容 1&#xff09;相关的表和题目 2&#xff09;帮助理解题目的示例&#xff0c;提供返回结果的格式 二、自己初步的理解 没啥思路&#xff0c;我还没做过交换的这种题&#xff0c;所以我觉得这类交换的题以后值得做一个合集&#xff0c;是有点灵活度在里面的&a…

computed 和 watch 的奇妙世界:让数据驱动你的 Vue 应用(上)

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

海思平台isp之ccm标定

文章目录 1、raw图采集2、ccm标定2.1、标定参数配置2.2、标定效果优化2.2.1、优化方式一2.2.2、优化方式二2.2.3、优化方式三1、raw图采集 raw图采集步骤及标准,请参考文章 《海思平台isp之ccm标定》。2、ccm标定 2.1、标定参数配置 (1)图像基本参数 (2)黑电平设置 (…

VR播控系统深耕VR教学领域,助力开启未来新课堂

作为提升教育质量的技术之一&#xff0c;VR技术已经逐渐成为培养新一代人才、提升教学质量的重要方式&#xff0c;相比于传统教育&#xff0c;VR技术在教学方面的应用&#xff0c;所带来的变化和效果提升都是非常明显的&#xff0c;尤其是VR播控系统的上线&#xff0c;作为VR教…

CDH6.3.2安装

文章目录 [toc]一、CM简介1、ClouderaManager的概念2、ClouderaManager的功能3、ClouderaManager的架构 二、准备清单1、部署步骤2、集群规划3、软件环境准备 三、安装清单1、操作系统iso包2、JDK包3、MySQL包4、CM和CDH包5、部署ansible 四、基础环境准备1、配置网络2、配置ho…

Doris学习笔记

目录 简介 特点 MPP数据库 PB和EB都是用来衡量数据存储量的单位。 秒级响应 Google Mesa Apache Impala 支持标准sql且兼容mysql协议 ROLAP OLAP&#xff08;On-Line Analytical Processing&#xff0c;联机分析处理&#xff09; ROLAP&#xff08;Relational On-Line An…

理解Mysql索引原理及特性

作为开发人员&#xff0c;碰到了执行时间较长的sql时&#xff0c;基本上大家都会说”加个索引吧”。但是索引是什么东西&#xff0c;索引有哪些特性&#xff0c;下面和大家简单讨论一下。 1 索引如何工作&#xff0c;是如何加快查询速度 索引就好比书本的目录&#xff0c;提高数…

智能优化算法应用:基于差分进化算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于差分进化算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于差分进化算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.差分进化算法4.实验参数设定5.算法结果6.…

FTP、U盘等传统数据安全摆渡方法的6个弊端

数据安全摆渡&#xff0c;即数据在不同的网络之间&#xff0c;进行安全流转。做网间隔离的初衷&#xff0c;就是为了保护数据安全&#xff0c;但是在数据摆渡时&#xff0c;除了安全&#xff0c;企业还是需要考虑其他的要素&#xff0c;比如可靠性、易用性、兼容性等等。而传统…

linux 防火墙systemctl (个人笔记)

查看 systemctl status firewalld 开启 systemctl start firewalld 关闭 systemctl stop firewalld.service 查看所有 firewall-cmd --zonepublic --list-ports 开放端口&#xff1a;// --permanent 永久生效,没有此参数重启后失效 firewall-cmd --zonepublic --add-port9527/…

c语言 词法分析器《编译原理》课程设计 文本形式保存

词法分析器的功能输入源程序&#xff0c;按照构词规则分解成一系列单词符号。单词是语言中具有独立意义的最小单位&#xff0c;包括关键字、标识符、运算符、界符和常量等。 (1) 关键字&#xff1a;是由程序语言定义的具有固定意义的标识符。例如begin&#xff0c;end&#xf…

SpringBoot中日志的使用log4j2

SpringBoot中日志的使用log4j2 1、log4j2介绍 Apache Log4j2 是对 Log4j 的升级&#xff0c;它比其前身 Log4j 1.x 提供了重大改进&#xff0c;并提供了 Logback 中可用的许多改 进&#xff0c;同时修复了 Logback 架构中的一些问题&#xff0c;主要有&#xff1a; 异常处理…

GPDB - 高可用特性 - 同步复制与异步复制

GPDB - 高可用特性 - 同步复制与异步复制 GreenPlum是基于PostgreSQL的分布式数据库&#xff0c;master用于接收用户请求并生成执行计划与分发&#xff0c;当然也可以参与计算&#xff1b;而segment则用于存储数据&#xff0c;将计算的结果传递给master。Segment本身具有高可用…

5.4 Linux KickStart 无人值守安装

1、概念介绍 搭建无人执行安装服务器需要从装网络引导安装操作系统&#xff0c;这样我们就可以不必走到机器那里插入CD&#xff0d;ROM光盘或者U盘手动一台一台安装操作系统&#xff0c;使用网络引导批量部署服务器操作系统。 服务架构&#xff1a;PXE DHCP TFTP Kickstar…

dockerfite创建镜像---INMP+wordpress

目录 搭建dockerfile---lnmp 创建nginx镜像 运行 创建数据库镜像 运行 ​编辑 创建php镜像 运行 搭建dockerfile---lnmp 在192.168.10.201 服务IP地址nginx 172.111.0.10 dockernginxmysql172.111.0.20dockermysqlphp172.111.0.30dockerphp 创建nginx镜像 路径 vim /…

python基本数据类型(一)-字符串

1.字符串 字符串就是一系列字符&#xff0c;在Python中&#xff0c;用引号括起的都是字符串&#xff0c;其中的引号可以是单引号&#xff0c;也可以是双引号&#xff0c;如下所示&#xff1a; "This is a string." This is also a string.这种灵活性让你能够在字符…

【产品经理】产品增效项目落地,项目反哺产品成长

产品和项目是相辅相成的关系&#xff0c;产品的规范、成熟&#xff0c;为项目的快速落地提供支撑&#xff0c;项目的落地反哺产品&#xff0c;促进产品的成长成熟。 软件工程的初期是&#xff0c;我们需要什么&#xff0c;就立项项目&#xff0c;通过项目实现需要。 随着项目的…

用实例域代替序数

在Java中&#xff0c;枚举类型的ordinal()方法返回枚举常量的序数&#xff08;即其在枚举声明中的位置&#xff09;。在某些情况下&#xff0c;使用实例域&#xff08;instance field&#xff09;代替序数可能更加安全和易读。以下是一个示例&#xff0c;演示如何使用实例域代替…

低代码开发如何快速构建AI应用

随着人工智能&#xff08;AI&#xff09;的快速发展&#xff0c;越来越多的企业和开发者开始意识到AI在业务和应用中的重要性。然而&#xff0c;AI应用的开发通常被认为是复杂和耗时的过程&#xff0c;需要大量的编码和数据科学知识。为了解决这个问题&#xff0c;低代码开发平…

图片转HTML-screenshot-to-code

Github地址 https://github.com/abi/screenshot-to-code 在线站 Screenshot to Code 简介 这是一个基于GPT4开发的一个工具站&#xff0c;它可以基于截图生成站点代码&#xff0c;生成速度快且准确。