WPF DataGrid 如何将被选中行带到视野中

WPF DataGrid 如何将被选中行带到视野中

目录

前言

准备工作

方法一

方法二

总结

独立观察员 2021 年 12 月 11 日

前言

在 WPF 开发中,显示表格一般使用 DataGrid 控件,而且我们一般会依据用户的选中行的操作来执行一些逻辑,这种情况,选中了哪一行,用户是心知肚明的。而还有一种情况,我们可能在业务逻辑中,由程序自己选中了某一行,如果这一行当前不在用户界面的可视区(换句话说也就是滚动条没有滚到那个位置),那么我们如何将其带到用户的视野中呢?

准备工作

今天准备介绍两个方法。正所谓,工欲善其事必先利其器,所以在开始之前,我们先来构建一个可以模拟后台选中行的功能。

使用的还是之前用过的 DataGrid 的 Demo 程序(在《WPF DataGrid 通过自定义表头模拟首行固定》和《WPF 触屏事件后触发鼠标事件的问题及 DataGrid 误触问题》中用过),加了一个可以填写要选中的行号的文本框,以及一个执行选中操作的按钮:

7cb9f46fd4e619ef98f659effa5f21a7.png

下面来演示一下没有自动将选中行带到视野中的情况。我们先将数据添加到 10 条,然后缩小程序的窗口,这样有些数据就在滚动区外面了,也就是不在视野中。然后我们通过程序来选中行,可以看到选中功能是正常的,但是对于视野外的数据,用户看不到其是否选中,需要手动滚动来寻找,如下图(动图):

dcd035b4ce0ec2f9293bf8271ea76356.gif

好,那接下来就介绍怎么解决吧。

方法一

这个方法是参考《【翻译】WPF 中附加行为的介绍 Introduction to Attached Behaviors in WPF》文章中的将 TreeViewItem(树状列表项)带到视野中的方法,我稍微改造了一下,使其同时支持 DataGridRow 和 TreeViewItem,并且之后如果有其它受支持的类型也可以方便地扩展。BringIntoViewBehavior 类提供了一个 IsBroughtIntoViewWhenSelected 附加属性,给每个列表项的 Selected 事件指定了处理方法,处理方法中调用 BringIntoView () 方法,完整代码如下:

using System.Windows;
using System.Windows.Controls;
/** 源码已托管:https://gitee.com/dlgcy/WPFTemplateLib*/
namespace WPFTemplateLib.WpfHelpers
{/// <summary>/// 功能:列表项被选中时带到视野中/// 参考:http://dlgcy.com/introduction-to-attached-behaviors-in-wpf//// 说明:用于 DataGrid 时需要设置 EnableRowVirtualization="False"/// </summary>/// <example>/// <code>/// Setter Property="wpfHelpers:BringIntoViewBehavior.IsBroughtIntoViewWhenSelected" Value="True"/>/// </code>/// </example>public class BringIntoViewBehavior{#region IsBroughtIntoViewWhenSelectedpublic static bool GetIsBroughtIntoViewWhenSelected(FrameworkElement item){return (bool)item.GetValue(IsBroughtIntoViewWhenSelectedProperty);}public static void SetIsBroughtIntoViewWhenSelected(FrameworkElement item, bool value){item.SetValue(IsBroughtIntoViewWhenSelectedProperty, value);}/// <summary>/// 是否在选中时带到视野中/// </summary>public static readonly DependencyProperty IsBroughtIntoViewWhenSelectedProperty =DependencyProperty.RegisterAttached("IsBroughtIntoViewWhenSelected",typeof(bool),typeof(BringIntoViewBehavior),new UIPropertyMetadata(false, OnIsBroughtIntoViewWhenSelectedChanged));static void OnIsBroughtIntoViewWhenSelectedChanged(DependencyObject depObj, DependencyPropertyChangedEventArgs e){FrameworkElement item = depObj as FrameworkElement;if (item == null)return;if (e.NewValue is bool == false)return;switch (depObj){case DataGridRow row:{if ((bool)e.NewValue)row.Selected += OnItemSelected;elserow.Selected -= OnItemSelected;break;}case TreeViewItem treeViewItem:{if ((bool)e.NewValue)treeViewItem.Selected += OnItemSelected;elsetreeViewItem.Selected -= OnItemSelected;break;}default:break;}}static void OnItemSelected(object sender, RoutedEventArgs e){// 忽略所有只是报告子孙的 Selected 被触发的祖先。if (!ReferenceEquals(sender, e.OriginalSource))return;if (e.OriginalSource is FrameworkElement item)item.BringIntoView();}#endregion}
}

此方法用于 DataGrid 时需要设置 EnableRowVirtualization="False"(默认为 true):

723e03d85a75789e4c44c70d850830e5.png

91bc4fb2a5764ba1c7b578e8381fddd4.png

使用时只要在行样式中应用这个附加属性即可:

95bc5426272aa8397261a3c74402f83f.png

注意引入命名空间:

0d41e2f529eac9f9a941b74f55ed1715.png

效果如下(动图):

4b7b3fc63344e071d13dab8cd26d05fa.gif

方法二

如果开了行虚拟化(EnableRowVirtualization="True"),离可视区较远的行的 Selected 事件就不会被触发,以上方法就不行了。

类似于这个帖子的情况《WPF 开启行虚拟化的时候,行选择功能不正常,求解决方案》(https://bbs.csdn.net/topics/392666509):

a9824064587f611a38b2a273a2700dcc.png

所以如果因为数据量比较大必须开启行虚拟化时,可以使用下面的方法。

先给 DataGrid 命个名(如 x:Name="Dg" )方便后台使用,然后在 ViewModel 中添加一个选中项改变事件 SelectedItemChanged,并在选中项改变时调用(参数为选中行的索引):

/// <summary>
/// 选中项改变事件
/// </summary>
public event Action<int> SelectedItemChanged;private User _SelectedItem;
/// <summary>
/// 选中项
/// </summary>
public User SelectedItem
{get => _SelectedItem;set{SetProperty(ref _SelectedItem, value);SelectedItemChanged?.Invoke(Datas.IndexOf(_SelectedItem));}
}

接着在后台事件中注册事件处理方法,处理方法中调用了 DataGrid 的 ScrollIntoView 方法,代码如下:

_vm.SelectedItemChanged += OnSelectedItemChanged;/// <summary>
/// 选中项改变事件执行方法
/// </summary>
/// <param name="index">选中行索引</param>
private void OnSelectedItemChanged(int index)
{Dg.ScrollIntoView(Dg.Items.GetItemAt(index));
}

效果和方法一的一样,就不再赘述了。

总结

关于将 DataGrid 选中行带到视野中的需求,本文介绍了两种方法。方法一提供了一个附加属性,可以方便地实现该需求,不过要求不能开启行虚拟化。方法二则是需要在 ViewModel 和页面后台编写代码,通过事件来触发相关操作,不过可以支持行虚拟化。大家可以依据实际情况选择使用,如果有更好的方法,欢迎交流。 

源代码地址:https://gitee.com/dlgcy/DLGCY_WPFPractice/tree/Blog20211211 

WPF

WPF 触屏事件后触发鼠标事件的问题及 DataGrid 误触问题

WPF DataGrid 通过自定义表头模拟首行固定

WPF ComboBox 使用 ResourceBinding 动态绑定资源键并支持语言切换

【翻译】WPF 中附加行为的介绍 Introduction to Attached Behaviors in WPF

WPF 使用 Expression Design 画图导出及使用 Path 画图

WPF MVVM 弹框之等待框

解决 WPF 绑定集合后数据变动界面却不更新的问题(使用 ObservableCollection)

WPF 消息框 TextBox 绑定新数据时让光标和滚动条跳到最下面

真・WPF 按钮拖动和调整大小

WPF MVVM 模式下的弹窗

WPF 让一组 Button 实现 RadioButton 的当前样式效果

WPF 原生绑定和命令功能使用指南

WPF 用户控件的自定义依赖属性在 MVVM 模式下的使用备忘

在WPF的MVVM模式中使用OCX组件

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python 基础语法_Python脚本文件结构

前言 Python基础语法这一章&#xff0c;主要记录了Python的文件结构、逻辑运算符、算术操作符、控制流语句、输入和输出语句、函数、对象、类等方面的内容。在了解了Python的数据类型之后&#xff0c;结合之前的要点来一起继续学习。 软件环境 系统 UbuntuKylin 14.04软件 Pyth…

Andriod之import android.support.v4或者import android.support.v7提示导入错误解决办法

问题所在原因&#xff1a;少了v4.jar包 解决办法&#xff1a;给项目添加v4.jar包就行 在使用Eclipse开发andriod程序时&#xff0c;程序中提示import android.support.v4.XXX或者import android.support.v7.XXX出错&#xff0c;具体的提示信息是&#xff1a; The import andro…

e2200网卡驱动 linux,Linux驱动修炼之道-驱动中一些常见的宏

Linux驱动修炼之道-驱动中一些常见的宏努力成为linux kernel hacker的人李万鹏原创作品&#xff0c;为梦而战。转载请标明出处http://doc.xuehai.net/woshixingaaa/archive/2011/06/02/6462065.aspx本文档讲解一下驱动中常用的宏&#xff0c;下边一个一个来说&#xff0c;先声明…

一对经典的时间获取客户/服务器程序

前言 本文通过一对经典的时间获取客户/服务器程序&#xff0c;展现了Linux网络编程的大体框架&#xff0c;为以后更深入的学习打下基础。 客户服务器模式网络编程的大体框架 客户端代码 1 #include <stdio.h>2 // 下头文件包含socket(), bind()等套接字通信必须的函数。3…

SkyWalking8.1.0 部署和使用

一、简介1、官方文档https://github.com/apache/skywalking/tree/master/docs2、功能SkyWalking是一个可观测性分析平台和应用性能管理系统&#xff0c;提供分布式跟踪、服务网格遥测分析、度量聚合和可视化一体化解决方案&#xff0c;并支持多种开发语言。专为微服务、云原生架…

CGI编程学习

一&#xff0e;基本原理 CGI&#xff1a;通用网关接口&#xff08;Common Gateway Interface&#xff09;是一个Web服务器主机提供信息服务的标准接口。通过CGI接口&#xff0c;Web服务器就能够获取客户端提交的信息&#xff0c;转交给服务器端的CGI程序进行处理&#xff0c;最…

博古通今的孩子是怎么养成的?答案就在这本影响了无数中国人思想的奇书里……

▲ 点击查看“三十六计走为上计”这句话&#xff0c;相信是大家从小听到大的俗语了。除此之外&#xff0c;还有“抛砖引玉”、“顺手牵羊”、“借刀杀人”、“擒贼先擒王”等都出自经典兵书《三十六计》。《三十六计》是中国古代最伟大的兵法谋略书之一&#xff0c;集智慧韬略、…

jmeter(2)录制脚本

Jmeter脚本是以JMX格式为主 Jmeter也是支持录制的&#xff0c;支持第三方录制方式和代理录制方式。 1、第三方录制主要是通过badboy来录制&#xff0c;录制后另存为jmx格式即可。 2、Jmeter也有自己的代理&#xff0c;录制脚本前&#xff0c;我们只要启动好代理&#xff0c;手动…

Android之Installation error: INSTALL_FAILED_UPDATE_INCOMPATIBLE问题解决

Installation error: INSTALL_FAILED_UPDATE_INCOMPATIBLE 晚上在测一个widget,前面测的好好的,后面再安装的时候发现如下错误: [2009-06-07 02:39:35 - battery] Performing sync [2009-06-07 02:39:35 - battery] Automatic Target Mode: using device HT843GZ03305 [2009…

linux硬盘转windows7,记——第一次上手UEFI电脑,将mbr硬盘的Windows7和Linux转为gpt+uefi启动...

这是篇日记&#xff0c;前面有大量的个人情绪&#xff0c;要看方法的请直接看后面。--------------------------------------------------------------------------------------------我终于上手新电脑了虽然还是用别人的旧电脑但是总算能够用上近代一点的硬件了&#xff0c;可…

20 个 .NET 6 新增的 API

DateOnly & TimeOnly.NET 6 引入了两种期待已久的类型 - DateOnly 和 TimeOnly, 它们分别代表DateTime的日期和时间部分。DateOnly dateOnly new(2021, 9, 25);Console.WriteLine(dateOnly);TimeOnly timeOnly new(19, 0, 0);Console.WriteLine(timeOnly); DateOnly date…

中国学生的最大噩梦,都来源于这个男人

全世界只有3.14 % 的人关注了爆炸吧知识会通中西经世致用说到中国古代的“全才”&#xff0c;一般人都会脱口而出沈括、张衡、祖冲之....而在明朝&#xff0c;有这么一位少有人知的“全才”式科学家&#xff0c;他的研究领域包括天文、历法、数学、军事、农业、水利....和上述的…

BASE64 编码和解码

依赖jar: import org.apache.commons.codec.binary.Base64; BASE64和其他相似的编码算法通常用于转换二进制数据为文本数据&#xff0c;其目的是为了简化存储或传输。更具体地说&#xff0c;BASE64算法主要用于转换二进 制数据为ASCII字符串格式。Java语言提供了一个非常好的BA…

类和类之间的关系解析-1

一、泛化关系 泛化关系也称继承关系&#xff0c;指的是一个类&#xff08;称为子类、子接口&#xff09;继承另外的一个类&#xff08;称为父类、父接口&#xff09;的功能&#xff0c;并可以增加它自己的新功能的能力。在Java中继承关系通过关键字extends明确标识&#xf…

转:智能卡测试操作系统技术

具有稳定、可靠的卡内操作系统是智能卡正常工作的基础&#xff0c;智能卡操作系统控制外界与智能卡之间的通信&#xff0c;管理卡片的存储空间&#xff0c;并且在卡内对于各种命令进行处理&#xff0c;所以在COS 开发过程中有必要对COS 进行充分且全面的测试。COS 的主要特点: …

Android之添加快捷方式(Shortcut)到手机桌面

在两个手机上测试,发现小米手机上添加了快捷方式后不能移除,三星手机可以。权限 要在手机桌面上添加快捷方式,首先需要在manifest中添加权限。 <!-- 添加快捷方式 --><uses-permission android:name="com.android.launcher.permission.INSTALL_SHORTCUT"…

C# 使用阿里云发送短信

最近有个项目&#xff0c;短信服务使用的是阿里云的&#xff0c;想要使用阿里云平台的短信服务&#xff0c;首先要注册一个阿里云账号&#xff0c;由于发送短信消息需要用到短信签名、短信模板ID&#xff08;已添加并通过审核&#xff09;1、注册阿里云账号&#xff08;地址&am…

如果太阳系毁灭,这种神秘粒子就是真凶!

185年12月7日这一天&#xff0c;东汉中平二年乙丑&#xff0c;一位天文学家观测到天空出现了一颗极其明亮的星体&#xff0c;他并不知道这意味着什么。这颗突然出现于苍穹之中的星星在夜空中照耀了八个月后&#xff0c;又忽然消逝了。《后汉书天文志》中留下了这段记载&#xf…

Centos7 安装gitlab 8.7.5

简介&#xff1a;GitLab 是一个用于仓库管理系统的开源项目。使用Git作为代码管理工具&#xff0c;并在此基础上搭建起来的web服务。1. Web框架使用Ruby on Rails。2. 基于MIT代码发布协议。3. 需要gitolite协同工作。安装要求&#xff1a;ruby 1.9.3MySQLgitgitoliteredis如果…