WinUI3入门2:DataGrid动态更新 添加删除和修改字段

发布于:2025-06-19 ⋅ 阅读:(14) ⋅ 点赞:(0)

初级代码游戏的专栏介绍与文章目录-CSDN博客

我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。

这些代码大部分以Linux为目标但部分代码是纯C++的,可以在任何平台上使用。

源码指引:github源码指引_初级代码游戏的博客-CSDN博客

C#是我多年以来的业余爱好,新搞的东西能用C#的就用C#了。


        承接上一篇:WinUI3入门1:使用DataGrid控件显示表格-CSDN博客

        上一篇我们已经显示了表格,但是只显示一般是不够的,我们还要考虑动态修改。本篇我们解决对数据源的修改如何反映到DataGrid控件的问题。

        说起来“修改”是一个问题,但是分解开是两个完全不同的问题:

  • 添加和删除如何反应到界面
  • 修改字段如何反映到界面

        因为容器的“修改”是添加和删除,而字段的修改属于容器里的每个对象,技术上是完全不同的。

一、添加和删除如何反映到界面

        DataGrid通过ItemSource绑定到数据源,数据源要求是个IEnumerable,通常用List<>,然而,List<>并没有变化通知的功能,因此我们之前用List<>无论如何都不能实现数据源添加修改反映到界面。

        为了让DataGrid能够得到数据源变化通知,需要使用另一个模板:ObservableCollection<>。简单替换之后数据源的增加和删除就能立即反映到界面上了。

        通过点击按钮给数据源增加数据:

			Data tmp = new Data("aa", "", "", "");
			datas.Add(tmp);
			datas[0].Dir = datas.Count.ToString();注意此句尚不会更新到界面

            datas[0].File = datas.Count.ToString();注意此句尚不会更新到界面

        效果如下: 

        注意,修改字段是不会反映上去的,即使隐藏控件然后再显示也不行。但是如果数据很多发生了滚动,一条数据重新出现时会显示为更新后的数据。(注:上图是已经添加了字段变化通知的效果,第一行第一列第二列已经被修改)

二、修改界面如何反应到字段

2.1 INotifyPropertyChanged

        能够通知字段变化的数据类型必须支持INotifyPropertyChanged接口。该接口包含一个事件:

event PropertyChangedEventHandler PropertyChanged;

        此事件在属性更改时发生。实现此接口的数据类型需要在每个属性更改是触发此事件。 

2.2 实现INotifyPropertyChanged

        实现过程相当繁琐,C#在引入无数令人困惑的语法甜点之后,为什么不给加个关键字指示一下呢?

        以下是新的Data类的代码:

		public class Data : INotifyPropertyChanged
		{
			String _dir;
			String _file;
			public String Dir { get { return _dir; } set { _dir = value; OnPropertyChanged(); } }
			public String File { get { return _file; } set { _file = value; OnPropertyChanged(); } }
			public String Ext { get; set; } = "";
			public String Type { get; set; } = "";
			public String Encode { get; set; } = "";
			public String BOM { get; set; } = "";
			public int CR { get; set; } = 0;
			public int CRLF { get; set; } = 0;
			public int LF { get; set; } = 0;
			public String State { get; set; } = "";

			public event PropertyChangedEventHandler PropertyChanged = delegate { };
			public void OnPropertyChanged([CallerMemberName] string propertyName="")
			{
				// Raise the PropertyChanged event, passing the name of the property whose value has changed.
				PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
			}
			public Data(String str, String n,
				String str2, String b)
			{
				this.Dir = str;
				this.Ext = n;
				this.File = str2;
				this.State = b;
			}

			public static ObservableCollection<Data> Datas()
			{
				return new ObservableCollection<Data>(new Data[4] {
			new Data("a", "1",
				"aaa",
				"false"),
			new Data("b","2",
				"bbb",
				"false"),
			new Data("c", "3",
				"ccc",
				"true"),
			new Data("d", "4",
				"ddd",
				"true")
		});
			}
		}

        定义INotifyPropertyChanged要求的事件:

			public event PropertyChangedEventHandler PropertyChanged = delegate { };

        实现辅助的触发时间函数,以简化每个属性的代码:

			public void OnPropertyChanged([CallerMemberName] string propertyName="")
			{
				// Raise the PropertyChanged event, passing the name of the property whose value has changed.
				PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
			}

        一个属性的实现:

			String _dir;
			public String Dir { get { return _dir; } set { _dir = value; OnPropertyChanged(); } }

        我们还记得原来的写法很简单:

public String Dir { get; set; } = "";

         为什么复杂了这么多?

  • 因为要调用函数触发事件,set必须写出来
  • 因为set必须写出来,就必须先给自己赋值
  • 在set里给自己赋值会触发set,无限递归
  • 所以不能使用简化属性语法,必须额外定义一个实际变量
  • 因此get也必须写出来

        对每一个需要实时更新界面的属性都要这样写。

三、xaml设置和代码设置

        xaml可以设置Mode为单项或双向,代码设置ItemSource时没有设置的地方,目前看至少是OneWay方式,是否支持双向,我们以后再研究。


(这里是文档结束)


网站公告

今日签到

点亮在社区的每一天
去签到