winform中也可以这样做数据展示✨
1、前言
在做winform开发的过程中,经常需要做数据展示的功能,之前一直使用的是gridcontrol控件,今天想通过一个示例,跟大家介绍一下如何在winform blazor hybrid中使用ant design blazor中的table组件做数据展示。
2、效果
先来看看实现的效果:


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:

这里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中单个项的类型,但是现在这里DataSource是WeatherData[],那么单个项的类型是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接口,如下所示:

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 是委托类型。详细学习,可以查看官方文档:

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

这里也通过一个简单的例子进行说明:
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。
理解了以上之后,我们看看这部分的代码:

代码如下:
<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做数据展示。
winform中也可以这样做数据展示✨的更多相关文章
- 记录一下SparkStreaming中因为使用redis做数据验证而导致数据结果不对的问题
业务背景: 需要通过redis判断当前用户是否是新用户.当出现新用户后,会将该用户放入到redis中,以标明该用户已不是新用户啦. 出现问题: 发现入库时,并没有新用户入库,但我看了数据了,确实应该是 ...
- winform中利用反射实现泛型数据访问对象基类(2)
在1的基础上做了一点改进 参数化处理 看上去更简洁 无主键情况下 update 方法需要改进 insert delete没有问题 /// <summary> /// DAO基类 ...
- C#在winform中操作数据库,实现数据增删改查
1.前言: 运行环境:VS2013+SQL2008+Windows10 程序界面预览: 使用的主要控件:dataGridview和menuStrip等. 2.功能具体介绍: 1.首先,我们要先实现基本 ...
- winform中利用反射实现泛型数据访问对象基类(3)
继续完善了几点代码 满足没有主键的情况下使用 并且完善实体字段反射设置value时的类型转换 /// <summary> /// DAO基类 实体名必须要与数据表字段名一致 /// < ...
- winform中利用反射实现泛型数据访问对象基类(1)
考虑到软件使用在客户端,同时想简化代码的实现,就写了一个泛型的数据访问对象基类,并不是特别健全,按道理应该参数化的方式实现insert和update,暂未使用参数化,抽时间改进. /// <su ...
- vue中使用Echart将一组数据展示出三种统计图
1 <template> 2 <div class="container"> 3 <div id="myEchart" style ...
- 在DevExpress程序中使用Winform分页控件直接录入数据并保存
一般情况下,我们都倾向于使用一个组织比较好的独立界面来录入或者展示相关的数据,这样处理比较规范,也方便显示比较复杂的数据.不过在一些情况下,我们也可能需要直接在GridView表格上直接录入或者修改数 ...
- WebGIS中利用AGS JS+eChart实现一些数据展示的探索
文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/. 1.背景 eChart提供了迁徙图.热点图.夜视图等跟地图能够很好的结 ...
- Winform中如何实现父窗体传递数据到子窗体并刷新子窗体
原理:利用委托和事件,本文将以图文并茂的例子讲述,告诉我们So Easy --------------------------------------------------------------- ...
- 在DevExpress程序中使用PopupContainerEdit和PopupContainer实现数据展示
在一些数据的即时查询场景中,我们可能需要对输入信息进行模糊查询并进行选择,例如在一些文本输入场景,如输入某个站点编码或者设备编码,然后获取符合的列表供用户选择的场景,本篇随笔介绍在DevExpress ...
随机推荐
- Prompt 指北:如何写好 Prompt,让 GPT 的回答更加精准
目录 1. 得亏 GPT 脾气好 2. 玩 GPT 得注意姿势 3. 指南指北指东指西 3.1 首先你得理解 GPT 是咋工作的 3.2 "Prompt 工程"走起 3.3 奇淫技 ...
- Linux下导入MySQL数据库
导入数据库1.首先建空数据库mysql>create database abc; 2.导入数据库方法一:(1)选择数据库mysql>use abc;(2)设置数据库编码mysql>s ...
- MD5&MD5盐值加密到BCryptPasswordEncoder
MD5&MD5盐值加密 Message Digest algorithm5,信息摘要算法: 压缩性:任意长度的数据,算出的MD5值长度都是固定的 容易计算:从原数据计算出MD5值很容易 抗修改 ...
- VMware Work Station使用ubuntu20.04挂载共享文件夹写入文件时出现输入/输出错误
原因是默认的max_write为0x00020000即128k,超过此大小会报错,另外big_writes,umask等选项也要加上, sudo /usr/bin/vmhgfs-fuse .host: ...
- Go流程控制与快乐路径原则
Go流程控制与快乐路径原则 目录 Go流程控制与快乐路径原则 一.流程控制基本介绍 二.if 语句 2.1 if 语句介绍 2.2 单分支结构的 if 语句形式 2.3 Go 的 if 语句的特点 2 ...
- 累死了qwq-一些平时的思考awa
最近真的有点难受了qwq有的时候没有认可我就是会有点伤心虽然知道就算是全部的人都认可我也没有什么用...但是总归是一个动力的来源.唉有的时候真的好想就这么的放弃信奥啊,毕竟在浙江这种地方,想要那一个奖 ...
- salesforce零基础学习(一百三十三)ListView的button思考
本篇参考: salesforce零基础学习(九十五)lightning out salesforce零基础学习(一百一十)list button实现的一些有趣事情 https://help.sales ...
- PHP-FFMpeg 操作音视频
目录 安装PHP-FFMpeg 视频中提取一张图片 视频中提取多张图片 调整视频大小 视频添加水印 生成音频波形 音频转换 给音频添加元数据 拼接多个音视频 截取音视频 提取 gif 动图 裁剪视频 ...
- Java核心知识体系5:反射机制详解
Java核心知识体系1:泛型机制详解 Java核心知识体系2:注解机制详解 Java核心知识体系3:异常机制详解 Java核心知识体系4:AOP原理和切面应用 1 介绍 无论是那种语言体系,反射都是必 ...
- 如何在Excel中实现三联类模板?
本文由葡萄城技术团队原创并首发.转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 前言 在一些报表打印应用场景中,会有类似于如下图所示的排版格式: 一般情况下 ...