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# String.Contains()方法: 返回一个值,该值指示指定的字符串是否出现在此字符串中

    C#中的 String.Contains() 方法 String.Contains() 方法用于判断字符串是否包含指定的字符或子字符串,返回值为布尔类型,即如果包含则返回 true,否则返回 false。以下是该方法的语法: public bool Contains (string value); 其中,value 参数为需查找的字符串。 使用方法 使用该方…

    C# 2023年4月19日
    00
  • C#实现截图工具小项目

    下面是详细的C#实现截图工具小项目攻略。 一、项目背景 截图工具是一款在电脑操作中十分常用的小工具,通过对电脑屏幕进行截图来方便用户进行操作、记录等。而使用C#进行开发,同样可以实现一个简单易用的截图工具,因此本篇攻略主要讲解如何使用C#实现截图工具。 二、开发准备 开发工具:Visual Studio或Visual Studio Code(推荐使用Visu…

    C# 2023年6月1日
    00
  • C#10的13个特性

    下面是关于C#10的13个特性的详细讲解: 新特性列表 以下是C#10中的全部13个特性: 全局 修饰符 元组投影初始值设定项 第一级模式 物化值参数 元素增强 特殊的 GetEnums() 统一处理的命名参数 异步流的增加 数组分配表达式 const 局部变量 用于对象初始化函数的 With 操作符 使用, When, And <合成> 记法来…

    C# 2023年6月1日
    00
  • c#动态调用Webservice的两种方法实例

    下面是关于”c#动态调用Webservice的两种方法实例”的完整攻略。 一、使用Visual Studio生成Web服务引用 1. 根据WebService的URL生成引用 在Visual Studio中,右键选择项目 -> 添加服务引用(Add Service Reference),在弹出的窗口中输入WebService的URL地址,然后单击“Go…

    C# 2023年6月6日
    00
  • java中的JSONP使用实例详解

    Java中的JSONP使用实例详解 JSONP(JSON with Padding)是一种跨域数据交互的技术,它允许在不同域之间进行数据交互。在Java中,可以使用JSONP来实现跨域数据交互。以下是JSONP的使用实例详解: 1. JSONP的基本原理 JSONP的基本原理是利用标签的跨域特性,将JSON数据作为参数传递给一个回调函数,然后在客户端中调用该…

    C# 2023年5月15日
    00
  • C#延迟执行方法函数实例讲解

    C#延迟执行方法函数实例讲解 什么是延迟执行 延迟执行是指在需要的时候才会进行真正的计算或执行,它可以提高程序的执行效率,在一些需要消耗大量资源或时间的情况下尤为重要。 C#中的延迟执行 C#中延迟执行可以通过Lambda表达式、Func和Action委托等方式实现。 Lambda表达式实现延迟执行 Lambda表达式是一种简单、紧凑的语法形式,可以在需要的…

    C# 2023年6月1日
    00
  • 使用DateTime的ParseExact方法实现特殊日期时间的方法详解

    让我来详细讲解下如何使用 C# 中的 DateTime.ParseExact 方法来解析特殊格式的日期时间字符串。 什么是 DateTime.ParseExact 方法? DateTime.ParseExact 是 C# 中用来将一个字符串转换成特定格式的日期时间类型的方法。这个方法的使用方式与 DateTime.Parse 很类似,但是它需要一个额外的参数…

    C# 2023年5月15日
    00
  • C#如何给PDF文件添加水印

    下面是C#如何给PDF文件添加水印的完整攻略: 1. 使用 iTextSharp 添加水印到 PDF 文件中 步骤如下: 引用 iTextSharp 的 dll 文件。 C# using iTextSharp.text; using iTextSharp.text.pdf; 读取 PDF 文件并创建 PdfStamper 对象。 C# PdfReader r…

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