鳕鱼天空

This is Mr Wang's Tech Blog.

c# datagridview加双缓中解决闪烁问题

摘要: 本文介绍了在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 Blazor的Auto渲染模式的初体验

合集 - .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支持四种渲染方式

  1. 静态渲染,这种页面只可显示,不提供交互,可用于网页内容展示
  2. 使用Blazor Server托管的通过Server交互方式
  3. 使用WebAssembly托管的在浏览器端交互方式
  4. 使用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按钮,将不再有响应事件发生。

 

iphone的safari浏览器中实现全屏浏览的方法

正常情况下,当你用手机浏览器打开网页时,导航就停留在上面,这样实际展示的屏幕就变小了。
那能不能加载后,屏幕就自动全屏呢?这就是本文要讨论的。

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方法。