C# WPF數據綁定方法以及重寫數據模板後數據綁定

来源:https://www.cnblogs.com/hellohxs/archive/2023/04/17/15262161.html
-Advertisement-
Play Games

寫在前面 本文將會介紹WPF如何實現前後端數據綁定和在進行數據綁定時常用的方法和類以及對於DataGrid、ListView這樣的控制項重寫數據模板後控制項如何進行數據綁定。 本文主要針對於數據綁定的基礎實現進行介紹,通過此博文你將會有能力編寫一個MVVM設計模式的C#、WPF項目。如果您是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平臺,為博主編寫並親測可用的,通過實例相信你可以更好的理解這部分內容。

 

新建一個WPF項目,並且添加Command類和MainWindowsViewModel類

Command.cs代碼:

 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代碼:

  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代碼:

 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

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 原文鏈接:https://www.zhoubotong.site/post/94.html 說下背景吧,大家在開發中可能在不同的目錄(package)下定義了相同的struct(屬性參數完全一樣如名字、個數和類型),在方法調用傳參數的時候,可能是用到了其中某一個struct的引用。 那麼這裡就牽扯到 ...
  • Java的反射機制允許程式員在執行期藉助於Reflection API取得任何類的內部信息,並能操作對象的屬性和方法,在各類框架中應用非常廣泛。這一期是關於反射內容的筆記,包含Class類、Field類、Method類、Constructor類及相關方法。 ...
  • Gin 環境:https://goproxy.cn,driect github.com/gin-gonic/gin 介紹 Gin 是一個用 Go (Golang) 編寫的 Web 框架。 它具有類似 martini 的 API,性能要好得多,多虧了 httprouter,速度提高了 40 倍。 如果 ...
  • 前言 Disruptor的高性能,是多種技術結合以及本身架構的結果。本文主要講源碼,涉及到的相關知識點需要讀者自行去瞭解,以下列出: 鎖和CAS 偽共用和緩存行 volatile和記憶體屏障 原理 此節結合demo來看更容易理解:傳送門 下圖來自官方文檔 官方原圖有點亂,我翻譯一下 在講原理前,先瞭解 ...
  • 作者:馬佩 鏈接:https://juejin.cn/post/7146016771936354312 場景 當我們業務資料庫表中的數據越來越多,如果你也和我遇到了以下類似場景,那讓我們一起來解決這個問題 數據的插入,查詢時長較長 後續業務需求的擴展 在表中新增欄位 影響較大 表中的數據並不是所有的 ...
  • 大家好,我是陶朱公Boy。(一個認真生活總想超越自己的程式員) 一線互聯網Java技術專家,有超過8年+後端開發、架構經驗。公眾號:「陶朱公Boy」歡迎大家關註! 星球簡介 一個幫你學編程、做項目、找工作少走彎路的交流圈,進步從此開始! 加入後你可以: 1.獲取陶朱公原創編程學習路線、原創編程知識庫 ...
  • 1. 示例 首先,定義一個介面: public interface Staff { void work(); } 然後,新增一個類並實現上面的介面: public class Coder implements Staff { @Override public void work() { System ...
  • 隨著技術的發展,ASP.NET Core MVC也推出了好長時間,經過不斷的版本更新迭代,已經越來越完善,本系列文章主要講解ASP.NET Core MVC開發B/S系統過程中所涉及到的相關內容,適用於初學者,在校畢業生,或其他想從事ASP.NET Core MVC 系統開發的人員。 經過前幾篇文章... ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...