摘要: 本文介绍了在C#Winform中,当DataGridView和ListView加载大量数据时遇到卡顿和闪烁问题的解决方案。方法一是重写CreateParams属性启用双缓冲,方法二是通过反射设置控件的DoubleBuffered属性。两种方法都能提高控件的绘制性能并减少闪烁。
先说原因,经过测试发现,当datagridview中加载大量数据时,拖拽进行放大缩小时,会有明显卡顿的感觉
解决办法1:
/// <summary>
/// 重写CreateParams属性的get访问器,目的是为了设置控件的窗口样式,以启用双缓冲功能,解决闪烁问题
/// </summary>
protected override CreateParams CreateParams
{
get
{
//首先获取基类的CreateParams属性,保存到变量cp中。这些参数包含了控件的基本创建信息
CreateParams cp = base.CreateParams;
//对cp的扩展样式进行位或操作(|=),将0x02000000这个标志添加到现有样式中。
//这个特定的十六进制值对应于WS_EX_COMPOSITED窗口样式,
//它可以强制控件及其所有子控件进行全部重新绘制,实现双缓冲效果,进而提升控件的绘制性能,减少闪烁。
cp.ExStyle |= 0x02000000;
return cp;
}
}
解决办法2:
创建一个类,在方法内部设置控件的双缓冲属性
public static class DoubleBufferedDataGridView
{
/// <summary>
/// 通过双缓冲技术,解决DataGridView或ListView的闪烁问题
/// </summary>
public static void DoubleBufferedDataGirdView(this DataGridView dgv, bool flag)
{
//获取传入的DataGridView对象的类型。
Type dgvType = dgv.GetType();
//使用反射技术查找DataGridView类型中的一个非公共实例属性
PropertyInfo pi = dgvType.GetProperty("DoubleBuffered", BindingFlags.Instance | BindingFlags.NonPublic)!;
//调用PropertyInfo对象的SetValue方法来设置DataGridView控件的DoubleBuffered属性值
pi.SetValue(dgv, flag, null);
}
}
然后在构造方法中调用该方法即可
public Form1()
{
InitializeComponent();
//设置双缓冲,解决闪烁
dataGridView1.DoubleBufferedDataGirdView(true);
}
参考链接:两种方法使用双缓冲解决C# 中DataGridView和ListView 实时刷新数据时出现闪烁的问题
使用双缓冲技术解决winform窗体控件卡顿(dataGridView加载数据缓慢)
原文链接:https://blog.csdn.net/weixin_49297068/article/details/137453565
合集 - .NET8(6)
1..NET8依赖注入新特性Keyed services2.C#12中的Primary Constructors(主构造函数)
2.C#12中的Primary Constructors(主构造函数)
3..NET8 Blazor的Auto渲染模式的初体验
4..NET8 Blazor新特性 流式渲染5.C#12中的Collection expressions(集合表达式语法糖)6.将 .NET Aspire 部署到 Kubernetes 集群
5.C#12中的Collection expressions(集合表达式语法糖)6.将 .NET Aspire 部署到 Kubernetes 集群
6.将 .NET Aspire 部署到 Kubernetes 集群
.NET8发布后,Blazor支持四种渲染方式
- 静态渲染,这种页面只可显示,不提供交互,可用于网页内容展示
- 使用Blazor Server托管的通过Server交互方式
- 使用WebAssembly托管的在浏览器端交互方式
- 使用Auto自动交互方式,最初使用 Blazor Server,并在随后访问时使用 WebAssembly 自动进行交互式客户端呈现。 自动呈现通常会提供最快的应用启动体验。
体验
通过VS创建Blazor应用时,选择Blazor Web App这个新模板。过程中可以看到有四种模板可供选择。我们可以选择Auto来体验。
新建Auto后,可以看到项目模板为我们创建了两个项目:BlazorApp与BlazorApp.Client
其中BlazorApp为启动项目,BlazorApp.Client为一个组件库
接着可以看看启动项目中的Program,一个明显的变化是,.NET8中的blazor通过添加插件方式开启了Blazor Server与WebAssembly两种交互方式。不加的话其实就是静态模式。
builder.Services.AddRazorComponents()
.AddInteractiveServerComponents()
.AddInteractiveWebAssemblyComponents();
...
app.MapRazorComponents<App>()
.AddInteractiveServerRenderMode()
.AddInteractiveWebAssemblyRenderMode()
.AddAdditionalAssemblies(typeof(Counter).Assembly);
交互模式的设置可以在Blazor.App.Client项目中的Counter中看到,使用了一个指令来设置渲染方式@rendermode InteractiveAuto
运行
我们可以尝试将项目运行起来,切换到counter路由并查看他如何自动切换交互方式。
首先,请将devtools中Application Tab页中的Cache Storage清空,防止已缓存的wasm文件影响测试效果。
然后,可以通过devtools中的request blocking功能先将wasm全部block。
我们可以发现虽然wasm都请求失败,但是Auto模式采用Blazor Server的方式通信,在点击按钮后,交互仍然生效
然后我们可以去掉对wasm的block,重新刷新页面,并点击Counter按钮后,wasm交互也生效
结论
因此验证Auto模式下,在wasm下载未完成或失败的情况下,使用Blazor Server方式交互。在wasm下载完成后使用WebAssembly方式在浏览器端交互,提高用户的体验。
另外,如果想体验静态交互,可以将Counter组件中的渲染方式@rendermode InteractiveAuto
去掉,即可体验静态交互的方式,静态交互的方式中点击Counter按钮,将不再有响应事件发生。
正常情况下,当你用手机浏览器打开网页时,导航就停留在上面,这样实际展示的屏幕就变小了。
那能不能加载后,屏幕就自动全屏呢?这就是本文要讨论的。
Add to Home Screen
说到全屏不得不谈iPhone下的safari有一个特别且重要的功能就是“Add to Home Screen”。(就在Safari浏览器最下方,最中间的那个位置,点击选择即可)
这个功能类似于把网页地址作为一个超链接的方式放到手机桌面,并且可以直接访问。不过要注意的是每个链接都需要js进行一次特殊处理,那就是监听页面点击事件,如果是链接,则使用window.location = this.href;,这样页面就不会从当前的本地窗口跳到浏览器了。
那我们看看具体代码是怎么处理的。
其实只需要在HEAD代码里增加一些必要数据:
正常情况下,当你用手机浏览器打开网页时,导航就停留在上面,这样实际展示的屏幕就变小了。
那能不能加载后,屏幕就自动全屏呢?这就是本文要讨论的。
Add to Home Screen
说到全屏不得不谈iPhone下的safari有一个特别且重要的功能就是“Add to Home Screen”。(就在Safari浏览器最下方,最中间的那个位置,点击选择即可)
这个功能类似于把网页地址作为一个超链接的方式放到手机桌面,并且可以直接访问。不过要注意的是每个链接都需要js进行一次特殊处理,那就是监听页面点击事件,如果是链接,则使用window.location = this.href;,这样页面就不会从当前的本地窗口跳到浏览器了。
那我们看看具体代码是怎么处理的。
其实只需要在HEAD代码里增加一些必要数据:
复制代码代码如下:
<meta name="apple-mobile-web-app-capable" content="yes" /><!-- home screen app 全屏 -->
<meta name="apple-mobile-web-app-status-bar-style" content="black" /><!-- 状态栏 -->
<!-- 还需要额外设置不同尺寸的启动图,默认不设置的话会自动去寻找根目录下的apple-touch-icon-precomposed.png -->
<!-- home screen app iPhone icon -->
<link rel="apple-touch-icon-precomposed" sizes="57x57" href="startup/apple-touch-icon-57x57-precomposed.png" />
<!-- home screen app iPad icon -->
<link rel="apple-touch-icon-precomposed" sizes="72x72" href="startup/apple-touch-icon-72x72-precomposed.png" />
<!-- home screen app iPhone Retinas icon -->
<link rel="apple-touch-icon-precomposed" sizes="114x114" href="startup/apple-touch-icon-114x114-precomposed.png" />
<!-- home screen app iPad Retinas icon -->
<link rel="apple-touch-icon-precomposed" sizes="144x144" href="startup/apple-touch-icon-144x144-precomposed.png" />
<!-- iPhone5启动图 -->
<link rel="apple-touch-startup-image" href="startup/startup5.png" media="(device-height:568px)">
<!-- iPhone4启动图 -->
<link rel="apple-touch-startup-image" size="640x920" href="startup/startup.png" media="(device-height:480px)">
还想了解具体的设置可以参考苹果的官网说明:Configuring Web Applications
当然,对启动图,我推荐的做法是只使用一张114*114的图片即可。即:
复制代码代码如下:
<link rel="apple-touch-icon-precomposed" href="startup/apple-touch-icon-114x114-precomposed.png" />
全屏js代码
复制代码代码如下:
window.addEventListener('DOMContentLoaded', function() {
var page = document.getElementById('page'),
nav = window.navigator,
ua = nav.userAgent,
isFullScreen = nav.standalone;
if (ua.indexOf('Android') !== -1) {
// 56对应的是Android Browser导航栏的高度
page.style.height = window.innerHeight + 56 + 'px';
} else if (/iPhone|iPod|iPad/.test(ua)) {
// 60对应的是Safari导航栏的高度
page.style.height = window.innerHeight + (isFullScreen ? 0 : 60) + 'px'
}
setTimeout(scrollTo, 0, 0, 1);
}, false);
这段代码本质上就是当前窗口的高度 + 导航栏的高度 获取到真实的屏幕高度。最后再调用scrollTo方法。
还想了解具体的设置可以参考苹果的官网说明:Configuring Web Applications
当然,对启动图,我推荐的做法是只使用一张114*114的图片即可。即:
复制代码代码如下:
<link rel="apple-touch-icon-precomposed" href="startup/apple-touch-icon-114x114-precomposed.png" />
全屏js代码
复制代码代码如下:
window.addEventListener('DOMContentLoaded', function() {
var page = document.getElementById('page'),
nav = window.navigator,
ua = nav.userAgent,
isFullScreen = nav.standalone;
if (ua.indexOf('Android') !== -1) {
// 56对应的是Android Browser导航栏的高度
page.style.height = window.innerHeight + 56 + 'px';
} else if (/iPhone|iPod|iPad/.test(ua)) {
// 60对应的是Safari导航栏的高度
page.style.height = window.innerHeight + (isFullScreen ? 0 : 60) + 'px'
}
setTimeout(scrollTo, 0, 0, 1);
}, false);
这段代码本质上就是当前窗口的高度 + 导航栏的高度 获取到真实的屏幕高度。最后再调用scrollTo方法。