C# WPF数据绑定方法以及重写数据模板后数据绑定

写在前面

本文将会介绍WPF如何实现前后端数据绑定和在进行数据绑定时常用的方法和类以及对于DataGrid、ListView这样的控件重写数据模板后控件如何进行数据绑定

本文主要针对于数据绑定的基础实现进行介绍,通过此博文你将会有能力编写一个MVVM设计模式的C#、WPF项目。如果您是C#及WPF的资深开发人员本文可能对您没有太大的帮助,但如果你是一个正在学习和了解C#、WPF的开发人员来说本文可以帮助你认识MVVM设计模式和数据绑定。

 


 

一、实现前后端数据绑定:

说到前后端的数据绑定,就需要先说一下WPF的MVVM设计模式,它是由传统的MVC设计模式改进而来,不同点在于MVVM数据源更新不需要一个Controller控制器来向前台同步数据,同时前台数据更改也不需要控制器向后台同步。如果想深入详细的了解MVVM设计模式百度百科对这部分的讲解和说明我认为非常的详细和系统。也可以阅读下方的实例,相信通过代码实例更能够让你对MVVM有一个更深入的认识。

实例:

源代码地址(码云):https://gitee.com/hkb1202/csharp-wpf-data-binding-demo

实例基于.Net Core 3.1平台,为博主编写并亲测可用的,通过实例相信你可以更好的理解这部分内容。

C# WPF数据绑定方法以及重写数据模板后数据绑定

 

新建一个WPF项目,并且添加Command类和MainWindowsViewModel类

Command.cs代码:

C# WPF数据绑定方法以及重写数据模板后数据绑定

 1 using System;
 2 using System.Windows.Input;
 3 
 4 namespace WpfExample
 5 {
 6     public class Command : ICommand
 7     {
 8 
 9         /// <summary>
10         /// 检查命令是否可以执行的事件,在UI事件发生导致控件状态或数据发生变化时触发
11         /// </summary>
12         public event EventHandler CanExecuteChanged
13         {
14             add
15             {
16                 if (_canExecute != null)
17                 {
18                     CommandManager.RequerySuggested += value;
19                 }
20             }
21             remove
22             {
23                 if (_canExecute != null)
24                 {
25                     CommandManager.RequerySuggested -= value;
26                 }
27             }
28         }
29 
30         /// <summary>
31         /// 判断命令是否可以执行的方法
32         /// </summary>
33         private Func<object, bool> _canExecute;
34 
35         /// <summary>
36         /// 命令需要执行的方法
37         /// </summary>
38         private Action<object> _execute;
39 
40         /// <summary>
41         /// 创建一个命令
42         /// </summary>
43         /// <param name="execute">命令要执行的方法</param>
44         public Command(Action<object> execute) : this(execute, null)
45         {
46 
47         }
48 
49         /// <summary>
50         /// 创建一个命令
51         /// </summary>
52         /// <param name="execute">命令要执行的方法</param>
53         /// <param name="canExecute">判断命令是否能够执行的方法</param>
54         public Command(Action<object> execute, Func<object, bool> canExecute)
55         {
56             _execute = execute;
57             _canExecute = canExecute;
58         }
59 
60         /// <summary>
61         /// 判断命令是否可以执行
62         /// </summary>
63         /// <param name="parameter">命令传入的参数</param>
64         /// <returns>是否可以执行</returns>
65         public bool CanExecute(object parameter)
66         {
67             if (_canExecute == null) return true;
68             return _canExecute(parameter);
69         }
70 
71         /// <summary>
72         /// 执行命令
73         /// </summary>
74         /// <param name="parameter"></param>
75         public void Execute(object parameter)
76         {
77             if (_execute != null && CanExecute(parameter))
78             {
79                 _execute(parameter);
80             }
81         }
82     }
83 }

Command.cs

 Command类是实现ICommand接口,从而实现将前台的命令注册到后台的ViewModel中,在此不详细展开讲解,请先照抄代码,如果对这部分感兴趣可以查阅博客园中关于ICommand接口的详解。暂时不理解这里并不影响后续的编码。

MainWindowViewModel.cs代码:

C# WPF数据绑定方法以及重写数据模板后数据绑定

  1 using System.Collections.ObjectModel;
  2 using System.ComponentModel;
  3 using System.Windows;
  4 using System.Windows.Controls;
  5 
  6 namespace WpfExample
  7 {
  8     public class MainWindowViewModel : INotifyPropertyChanged
  9     {
 10         //实现接口当数据源变动通知前台UI
 11         public event PropertyChangedEventHandler? PropertyChanged;
 12 
 13         public void RaisePropertyChanged(string propName)
 14         {
 15             if (PropertyChanged != null)
 16             {
 17                 PropertyChanged(this, new PropertyChangedEventArgs(propName));
 18             }
 19         }
 20 
 21         /// <summary>
 22         /// 前台DataGrid绑定的People集合
 23         /// </summary>
 24         public ObservableCollection<Person> People { get; set; }
 25 
 26         /// <summary>
 27         /// 绑定前台DataGrid控件SelectedItem字段上,用于保存当前选中的Item所对应的数据源
 28         /// </summary>
 29         public Person SelectItem
 30         {
 31             get
 32             {
 33                 return m_SelectItem;
 34             }
 35             set
 36             {
 37                 m_SelectItem = value;
 38                 RaisePropertyChanged("SelectItem");
 39             }
 40         }
 41 
 42         /// <summary>
 43         /// DataGrid控件中删除按钮命令
 44         /// </summary>
 45         public Command DelClick
 46         {
 47             get
 48             {
 49                 if (m_DelClick == null)
 50                     m_DelClick = new Command(DeleteEvent);
 51 
 52                 return m_DelClick;
 53             }
 54         }
 55 
 56         /// <summary>
 57         /// 前台添加小刚按钮命令
 58         /// </summary>
 59         public Command AddClick
 60         {
 61             get
 62             {
 63                 if (m_AddClick == null)
 64                     m_AddClick = new Command(AdditionEvent);
 65 
 66                 return m_AddClick;
 67             }
 68         }
 69 
 70         /// <summary>
 71         /// 前台修改Text按钮命令
 72         /// </summary>
 73         public Command ReviseClick
 74         {
 75             get
 76             {
 77                 if (m_ReviseClick == null)
 78                     m_ReviseClick = new Command(ReviseEvent);
 79 
 80                 return m_ReviseClick;
 81             }
 82         }
 83 
 84         /// <summary>
 85         /// 前台TextBlock控件显示的文本
 86         /// </summary>
 87         public string TextInfo
 88         {
 89             get
 90             {
 91                 return m_TextInfo;
 92             }
 93             set
 94             {
 95                 m_TextInfo = value;
 96                 //数据源更新调用更新前台UI方法
 97                 RaisePropertyChanged("TextInfo");
 98             }
 99         }
100 
101         /// <summary>
102         /// DataGrid控件电话信息的TextBox键盘按下回车命令
103         /// </summary>
104         public Command PressEnterKey
105         {
106             get
107             {
108                 if (m_PressEnterKey == null)
109                     m_PressEnterKey = new Command(PressEnterKeyEvent);
110 
111                 return m_PressEnterKey;
112             }
113         }
114 
115         private Person m_SelectItem;
116         private Command m_DelClick;
117         private Command m_AddClick;
118         private Command m_ReviseClick;
119         private string m_TextInfo;
120         private Command m_PressEnterKey;
121 
122         /// <summary>
123         /// 构造方法
124         /// </summary>
125         public MainWindowViewModel()
126         {
127             People = new ObservableCollection<Person>();
128 
129             Person person1 = new Person() { Name = "小明", Age = 12, Sex = "", Phone = "110" };
130             Person person2 = new Person() { Name = "小红", Age = 13, Sex = "", Phone = "119" };
131             Person person3 = new Person() { Name = "小王", Age = 15, Sex = "", Phone = "120" };
132 
133             People.Add(person1);
134             People.Add(person2);
135             People.Add(person3);
136 
137             TextInfo = "点击右侧按钮这里内容将会变化!";
138         }
139 
140         /// <summary>
141         /// DataGrid控件中删除按钮事件
142         /// </summary>
143         /// <param name="obj">可传入前台控件</param>
144         private void DeleteEvent(object obj)
145         {
146             if (MessageBox.Show($"是否删除{SelectItem.Name}的数据?", "提示", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
147             {
148                 People.Remove(SelectItem);
149             }
150         }
151 
152         /// <summary>
153         /// 前台添加小刚按钮事件
154         /// </summary>
155         /// <param name="obj">可传入前台控件</param>
156         private void AdditionEvent(object obj)
157         {
158             if (MessageBox.Show("是否添加“姓名:小刚,年龄:18,性别:女,电话:123”?", "提示", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
159             {
160                 People.Add(new Person() { Name = "小刚", Age = 18, Sex = "", Phone = "123" });
161             }
162         }
163 
164         /// <summary>
165         /// 前台修改Text按钮事件
166         /// </summary>
167         /// <param name="obj">可传入前台控件</param>
168         private void ReviseEvent(object obj)
169         {
170             if (TextInfo == "点击右侧按钮这里内容将会变化!")
171             {
172                 TextInfo = "点击了右侧按钮!!!!!!!!!";
173             }
174             else
175             {
176                 TextInfo = "点击右侧按钮这里内容将会变化!";
177             }
178         }
179 
180         /// <summary>
181         /// DataGrid控件电话信息的TextBox键盘按下回车事件
182         /// </summary>
183         /// <param name="obj">可传入前台控件</param>
184         private void PressEnterKeyEvent(object obj)
185         {
186             TextBox textBox = (TextBox)obj;
187             MessageBox.Show($"点击了回车!控件内容为:{textBox.Text}");
188         }
189 
190         /// <summary>
191         /// 数据结构
192         /// </summary>
193         public class Person
194         {
195             public string Name { get; set; }
196             public int Age { get; set; }
197             public string Sex { get; set; }
198             public string Phone { get; set; }
199         }
200     }
201 }

MainWindowViewModel.cs

MainWindowsViewModel类中编写业务逻辑代码。

MainWindow.xaml代码:

C# WPF数据绑定方法以及重写数据模板后数据绑定

 1 <Window x:Class="WpfExample.MainWindow"
 2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 5         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 6         xmlns:local="clr-namespace:WpfExample"
 7         mc:Ignorable="d"
 8         Title="MainWindow" Height="450" Width="800">
 9     <Grid>
10         <DataGrid Margin="10,10,10,50" ItemsSource="{Binding People, Mode=TwoWay}" SelectedItem="{Binding SelectItem}" AutoGenerateColumns="False" CanUserAddRows="False">
11 
12             <DataGrid.Columns>
13                 <DataGridTextColumn Header="姓名" Binding="{Binding Name}" Width="*" />
14                 <DataGridTextColumn Header="年龄" Binding="{Binding Age}" Width="*" />
15                 <DataGridTextColumn Header="性别" Binding="{Binding Sex}" Width="*" />
16                 <DataGridTemplateColumn Header="电话" Width="*">
17                     <DataGridTemplateColumn.CellTemplate>
18                         <DataTemplate>
19                             <TextBox x:Name="TextBox_Phone" Text="{Binding Phone}">
20                                 <TextBox.InputBindings>
21                                     <KeyBinding Key="Return" Command="{Binding Path=DataContext.PressEnterKey, RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=DataGrid}}" CommandParameter="{Binding ElementName=TextBox_Phone}"></KeyBinding>
22                                 </TextBox.InputBindings>
23                             </TextBox>
24                         </DataTemplate>
25                     </DataGridTemplateColumn.CellTemplate>
26                 </DataGridTemplateColumn>
27                 <DataGridTemplateColumn Header="删除" Width="*">
28                     <DataGridTemplateColumn.CellTemplate>
29                         <DataTemplate>
30                             <Button Content="删除" Command="{Binding Path=DataContext.DelClick, RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=DataGrid}}" />
31                         </DataTemplate>
32                     </DataGridTemplateColumn.CellTemplate>
33                 </DataGridTemplateColumn>
34             </DataGrid.Columns>
35         </DataGrid>
36         <Button Margin="10,0,10,10" VerticalAlignment="Bottom" HorizontalAlignment="Left" Height="30" Width="100" Content="添加学生小刚" Command="{Binding AddClick}"></Button>
37         <TextBlock Margin="0,0,140,10" VerticalAlignment="Bottom" HorizontalAlignment="Right" Text="{Binding TextInfo}" FontSize="24"></TextBlock>
38         <Button Margin="0,0,10,10" VerticalAlignment="Bottom" HorizontalAlignment="Right" Height="30" Width="100" Content="修改Text内容" Command="{Binding ReviseClick}"></Button>
39     </Grid>
40 </Window>

MainWindow.xaml

MainWindow.xaml.cs

C# WPF数据绑定方法以及重写数据模板后数据绑定

 1 using System.Windows;
 2 
 3 namespace WpfExample
 4 {
 5     public partial class MainWindow : Window
 6     {
 7         public MainWindow()
 8         {
 9             InitializeComponent();
10             //绑定DataContext
11             DataContext = new MainWindowViewModel();
12         }
13     }
14 }

MainWindow.xaml.cs

实例效果:

 C# WPF数据绑定方法以及重写数据模板后数据绑定

主界面窗口,支持点击删除按钮删掉对应信息;支持修改姓名,年龄,性别,电话信息;支持修改电话信息按下回车键捕捉回车事件功能;支持点击左下角添加学生小刚按钮增加信息;支持点击右下角修改Text内容下方TextBlok控件内容变化。

 

C# WPF数据绑定方法以及重写数据模板后数据绑定

C# WPF数据绑定方法以及重写数据模板后数据绑定

点击删除按钮,弹出确认删除对话框,点击是则删除成功。

 

C# WPF数据绑定方法以及重写数据模板后数据绑定

C# WPF数据绑定方法以及重写数据模板后数据绑定

点击左下角“添加学生小刚”按钮,弹出是否确认添加小刚信息确认框,点击是则会添加小刚的信息。

 

C# WPF数据绑定方法以及重写数据模板后数据绑定

在电话信息中输入回车会显示点击了回车弹框,并且显示控件中的内容。

 

C# WPF数据绑定方法以及重写数据模板后数据绑定

点击右下角“修改Text内容按钮”下方TextBlock控件内容发生改变

 

C# WPF数据绑定方法以及重写数据模板后数据绑定

修改小明的姓名后点击删除按钮,提示信息显示小明的姓名也被更改,说明数据源同时进行了更改。

 


 

1.数据源:数据绑定是通过ViewModel作为数据源,绑定到前台xaml进行实现的。通过后台对于数据源的修改,可以将内容直接同步到前台界面上。可以详见上面数据的删除和添加以及修改Text的实例。People、SelectItem、TextInfo都是数据源。

2.命令:除了数据要进行实时更新以外,前台的操作也应该能够传输到后台,在后台逻辑做出响应。这时我们需要用到Command(命令),在本实例中展示了将按钮的点击事件和键盘的回车事件通过命令的方式传到后台,但命令的用法远不止这两种,可以在实际的开发过程中跟据不同的需求在进行学习和尝试。值得注意的是命令是可以带参数的,前台代码中的CommandParameter就是它的参数,例如按钮点击的命令可以通过参数来确定点击的是哪一个按钮,当然也可以给每一个按钮绑定一个独立的命令。DelClick、AddClick、ReviseClick、PressEnterKey都是命令。

3.数据模板的重写:在本实例中重写了DataGrid控件中的电话一列和删除一列的数据模板,我们可以看到电话一列重写为了TextBox删除一列重写为了Button,表头也可以进行数据模板的重写。在DataTemplate中你可以写几乎任意的控件,如果需要放多个控件可以使用Grid和StackPanel这类布局控件进行封装。值得注意的是当重写数据模板之后,对于命令绑定的写法需要格外注意,需要注意Path和RelativeSource属性,详见例子代码中的写法,如果按照常规Binding的写法你会发现后端无法收到你绑定的命令。

4.双向绑定:顾名思义绑定是双向的,不仅仅是后台数据更新后自动同步到前台,同时前台的数据更新也会自动同步到后台。这种双向绑定也是MVVM设计模式的一大特点,本实例中可以看到修改了小明的名字后,修改的内容在你没有进行任何操作的情况下自动同步到了后台的数据源中(值得注意的是这里需要让选中的cell失去焦点修改的内容才会同步到后台数据源),这就是双向绑定。当然在绑定的过程中你可以设置多种模式,如果不设置默认为双向绑定,设置的方法是通过Mode属性(Binding="{Binding Name ,Mode=TwoWay}")你可以设置Default、OneTime、OneWay、OneWayToSource、TwoWay。

 

以上就是本实例中涉及一些要点,这些内容是做WPF和C#开发的基本内容,希望他们能对你的学习和工作起到一些帮助,如果对于本文某些用法写法说法有任何的意见欢迎指正交流。谢谢。

 

2023.4.17下午两点五十五分

原文链接:https://www.cnblogs.com/hellohxs/archive/2023/04/17/15262161.html

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C# WPF数据绑定方法以及重写数据模板后数据绑定 - Python技术站

(0)
上一篇 2023年4月17日
下一篇 2023年4月17日

相关文章

  • C#中的DateTime是值类型还是引用类型

    C#中的DateTime是值类型还是引用类型是一个常见的问题,它的答案是:DateTime是值类型。以下是详细的解释: 在C#中,类型可以被分为值类型和引用类型两种。值类型在栈上分配内存并且存储它们的实例,它们之间没有共享数据的方式。引用类型在堆上分配内存并且存储一个指向它们的实例的引用。值类型的示例包括:int、double、bool、struct、enu…

    C# 2023年6月1日
    00
  • 利用Timer在ASP.NET中实现计划任务的方法

    利用Timer在ASP.NET中实现计划任务的方法可以分为以下几个步骤: 在ASP.NET项目中安装System.Timers包。可以通过NuGet包管理器来安装,也可以手动添加引用。 在ASP.NET项目中创建一个类,可以命名为Tasks或者TaskScheduler,该类需要继承System.Timers.Timer类,并实现定时执行的代码。具体实现可以…

    C# 2023年6月6日
    00
  • C#创建Windows服务与服务的安装、卸载

    下面将为你详细讲解“C#创建Windows服务与服务的安装、卸载”的完整攻略。 1. 创建 Windows 服务 1.1 使用 Visual Studio 创建服务项目 打开 Visual Studio,选择“文件”-“新建”-“项目”,在“新建项目”窗口中选择“Windows 服务”项目模板,点击“确定”按钮创建项目。 1.2 设计服务程序 服务程序类必须…

    C# 2023年6月3日
    00
  • SpringBoot多种场景传参模式

    对于SpringBoot中的多种场景传参模式,我们可以从以下几个方面来进行学习和演示示例: 基础数据类型传参 对象传参 Map传参 List传参 复杂数据类型传参(JSON数据) 接下来,我们将逐一讲解以上几种场景对应的传参模式及示例演示。 基础数据类型传参 在SpringBoot中,基础数据类型传参是最常见的场景,涉及到的参数类型包括int、String等…

    C# 2023年6月1日
    00
  • FtpHelper实现ftp服务器文件读写操作(C#)

    FtpHelper实现ftp服务器文件读写操作(C#) 简介 FtpHelper是一个C#编写的FTP工具,用于实现FTP服务器文件的读写操作。本文将介绍使用FtpHelper进行FTP文件读写操作的方法。 安装 使用NuGet包管理器安装FtpHelper Install-Package FtpHelper 连接FTP服务器 使用FtpHelper连接FT…

    C# 2023年6月1日
    00
  • C#多线程之线程控制详解

    C#多线程之线程控制详解 在C#中,多线程技术通常用于对计算密集型和I/O密集型任务进行并发处理,以提高程序的性能和响应时间。C#提供了一系列的线程控制相关的基础类和方法,开发者可以通过这些类和方法灵活地控制线程的创建、启动、暂停、终止等行为。本文将详细讲解C#多线程之线程控制的相关知识点,包括线程同步、线程池、任务取消等内容。 线程同步 在多线程并发场景下…

    C# 2023年6月6日
    00
  • ASP.NET 使用application与session对象写的简单聊天室程序

    ASP.NET是一种广泛使用的Web开发框架,为构建Web应用程序提供了丰富的工具和组件。其中,application对象和session对象是ASP.NET应用程序中重要的服务器端状态管理机制之一,用于在不同的用户之间和同一用户的多个请求之间共享数据。在此基础上,我们可以实现一些有趣的功能,比如简单的聊天室程序。 下面是ASP.NET使用applicati…

    C# 2023年5月31日
    00
  • C#找出字符串中第一个字母并大写的方法

    要找出字符串中第一个字母并大写,可以使用C#中的字符串处理函数和char类型的特性。下面是具体的方法: 1.使用SubString和ToUpper函数找到第一个字符并大写 可以使用SubString函数来截取第一个字符,再使用ToUpper函数将该字符大写。示例代码如下: string str = "apple"; char firstC…

    C# 2023年6月8日
    00
合作推广
合作推广
分享本页
返回顶部