個(gè)人記賬系統(tǒng):MVVM與SQLite實(shí)戰(zhàn))
1. 項(xiàng)目概述個(gè)人記賬小系統(tǒng)的核心價(jià)值這個(gè)個(gè)人記賬小系統(tǒng)是我在業(yè)余時(shí)間開發(fā)的一個(gè)輕量級(jí)財(cái)務(wù)管理工具主要解決日常收支記錄的痛點(diǎn)。相比市面上復(fù)雜的記賬軟件它去除了所有冗余功能保留了最核心的記賬、統(tǒng)計(jì)和報(bào)表功能。整個(gè)系統(tǒng)采用WPF框架開發(fā)界面簡(jiǎn)潔直觀數(shù)據(jù)存儲(chǔ)在本地SQLite數(shù)據(jù)庫(kù)中既保證了隱私性又免去了網(wǎng)絡(luò)依賴。提示系統(tǒng)源碼完全開放特別適合.NET開發(fā)者學(xué)習(xí)WPF數(shù)據(jù)綁定、LINQ查詢和圖表繪制的實(shí)戰(zhàn)應(yīng)用我最初開發(fā)這個(gè)系統(tǒng)的動(dòng)機(jī)很簡(jiǎn)單市面上的記賬App要么功能太臃腫要么充斥著廣告。作為一個(gè)程序員我更想要一個(gè)能完全掌控的、可以隨時(shí)自定義功能的解決方案?,F(xiàn)在這個(gè)版本已經(jīng)穩(wěn)定運(yùn)行了兩年多期間根據(jù)實(shí)際使用反饋迭代了十幾個(gè)小版本。2. 系統(tǒng)架構(gòu)與技術(shù)選型2.1 前端界面設(shè)計(jì)系統(tǒng)采用WPF的MVVM模式開發(fā)主要使用了以下布局控件DockPanel主窗口的基礎(chǔ)布局Grid數(shù)據(jù)表格的精確排版StackPanel工具欄的垂直/水平排列TabControl不同功能模塊的切換!-- 典型布局示例 -- DockPanel Menu DockPanel.DockTop.../Menu StatusBar DockPanel.DockBottom.../StatusBar TabControl TabItem Header記賬 Grid Grid.RowDefinitions.../Grid.RowDefinitions StackPanel OrientationHorizontal.../StackPanel /Grid /TabItem /TabControl /DockPanel2.2 后端數(shù)據(jù)處理數(shù)據(jù)層采用Entity Framework Core操作SQLite主要實(shí)體包括Transaction記錄每筆交易的金額、類型、分類、時(shí)間等Category收支分類體系可自定義Budget預(yù)算設(shè)置Account多賬戶管理// 典型數(shù)據(jù)模型 public class Transaction { public int Id { get; set; } public decimal Amount { get; set; } public DateTime Date { get; set; } public string Description { get; set; } public TransactionType Type { get; set; } public int CategoryId { get; set; } public Category Category { get; set; } }2.3 圖表可視化使用LiveCharts庫(kù)實(shí)現(xiàn)動(dòng)態(tài)圖表支持月度收支趨勢(shì)折線圖分類占比餅圖年度對(duì)比柱狀圖預(yù)算完成度儀表盤3. 核心功能實(shí)現(xiàn)詳解3.1 交易記錄的CRUD操作記賬系統(tǒng)的核心是交易記錄的增刪改查。我采用了Repository模式進(jìn)行封裝主要技術(shù)點(diǎn)包括異步數(shù)據(jù)加載使用async/await避免UI卡頓數(shù)據(jù)驗(yàn)證在ViewModel層實(shí)現(xiàn)IDataErrorInfo批量操作支持CSV導(dǎo)入導(dǎo)出// 典型ViewModel代碼 public class TransactionViewModel : INotifyPropertyChanged, IDataErrorInfo { private readonly ITransactionRepository _repository; public async Task LoadDataAsync() { Transactions new ObservableCollectionTransaction( await _repository.GetByDateRangeAsync(StartDate, EndDate)); } public string Error null; public string this[string columnName] { get { if (columnName nameof(Amount) Amount 0) return 金額必須大于0; return null; } } }3.2 統(tǒng)計(jì)報(bào)表生成報(bào)表系統(tǒng)采用策略模式支持多種統(tǒng)計(jì)維度按日/周/月/年的收支匯總分類對(duì)比分析預(yù)算執(zhí)行情況賬戶余額變動(dòng)統(tǒng)計(jì)引擎的核心是LINQ查詢例如// 月度統(tǒng)計(jì)示例 var monthlyStats transactions .GroupBy(t new { t.Date.Year, t.Date.Month }) .Select(g new { Year g.Key.Year, Month g.Key.Month, Income g.Where(t t.Type TransactionType.Income).Sum(t t.Amount), Expense g.Where(t t.Type TransactionType.Expense).Sum(t t.Amount) }) .OrderBy(x x.Year) .ThenBy(x x.Month);3.3 數(shù)據(jù)備份與恢復(fù)考慮到數(shù)據(jù)安全性實(shí)現(xiàn)了以下機(jī)制自動(dòng)備份每天首次啟動(dòng)時(shí)自動(dòng)備份數(shù)據(jù)庫(kù)手動(dòng)導(dǎo)出支持導(dǎo)出為JSON/CSV格式云同步可選通過(guò)Web API與自建服務(wù)器同步備份核心代碼public async Task BackupDatabaseAsync(string backupPath) { var dbPath GetDatabasePath(); using (var source File.OpenRead(dbPath)) using (var dest File.Create(backupPath)) { await source.CopyToAsync(dest); } }4. 開發(fā)中的關(guān)鍵問(wèn)題與解決方案4.1 數(shù)據(jù)綁定性能優(yōu)化初期當(dāng)交易記錄超過(guò)5000條時(shí)界面會(huì)出現(xiàn)明顯卡頓。通過(guò)以下措施優(yōu)化虛擬化容器使用VirtualizingStackPanel分頁(yè)加載每次只加載當(dāng)前月的記錄延遲渲染對(duì)圖表數(shù)據(jù)采用按需加載!-- ListView虛擬化示例 -- ListView VirtualizingStackPanel.IsVirtualizingTrue VirtualizingStackPanel.VirtualizationModeRecycling ListView.ItemTemplate.../ListView.ItemTemplate /ListView4.2 多主題切換實(shí)現(xiàn)為滿足不同用戶的視覺(jué)偏好實(shí)現(xiàn)了動(dòng)態(tài)換膚功能定義資源字典存儲(chǔ)不同主題的顏色和樣式使用ResourceDictionary.MergedDictionaries動(dòng)態(tài)切換配合MahApps.Metro等UI庫(kù)增強(qiáng)效果public void ApplyTheme(string themeName) { var themeDict new ResourceDictionary { Source new Uri($Themes/{themeName}.xaml, UriKind.Relative) }; Application.Current.Resources.MergedDictionaries[0] themeDict; }4.3 跨平臺(tái)兼容性處理雖然主要面向Windows但通過(guò)以下方式提升了兼容性使用.NET Core 3.1/NET 5而非傳統(tǒng).NET Framework避免調(diào)用Windows特有API數(shù)據(jù)庫(kù)層使用跨平臺(tái)的SQLite5. 項(xiàng)目部署與使用指南5.1 開發(fā)環(huán)境搭建安裝Visual Studio 2019/2022社區(qū)版即可確保勾選.NET桌面開發(fā)工作負(fù)載克隆源碼倉(cāng)庫(kù)git clone https://example.com/accounting-system.git還原NuGet包dotnet restore5.2 數(shù)據(jù)庫(kù)初始化系統(tǒng)首次運(yùn)行時(shí)會(huì)自動(dòng)創(chuàng)建數(shù)據(jù)庫(kù)結(jié)構(gòu)如需手動(dòng)初始化dotnet ef database update5.3 自定義配置通過(guò)修改appsettings.json可以調(diào)整默認(rèn)貨幣符號(hào)日期顯示格式備份保留天數(shù)主題顏色{ AppSettings: { CurrencySymbol: ¥, DateFormat: yyyy-MM-dd, BackupRetentionDays: 7, DefaultTheme: Light } }6. 擴(kuò)展開發(fā)建議基于現(xiàn)有系統(tǒng)可以進(jìn)一步擴(kuò)展多用戶支持添加登錄系統(tǒng)和數(shù)據(jù)隔離智能分類利用機(jī)器學(xué)習(xí)自動(dòng)識(shí)別交易類型賬單提醒集成系統(tǒng)通知功能投資跟蹤添加股票、基金等投資記錄移動(dòng)端適配通過(guò)MAUI實(shí)現(xiàn)跨平臺(tái)對(duì)于想學(xué)習(xí)WPF的開發(fā)者這個(gè)項(xiàng)目提供了很好的起點(diǎn)。我在代碼中刻意保持了簡(jiǎn)潔性每個(gè)核心功能模塊都控制在300行以內(nèi)方便理解。特別推薦重點(diǎn)研究MainWindowViewModel.csMVVM模式的典型實(shí)現(xiàn)TransactionRepository.csEF Core的最佳實(shí)踐ChartHelper.cs動(dòng)態(tài)圖表的數(shù)據(jù)綁定技巧實(shí)際開發(fā)中最大的教訓(xùn)是不要過(guò)早優(yōu)化。初期我花了太多時(shí)間設(shè)計(jì)完美架構(gòu)后來(lái)發(fā)現(xiàn)對(duì)于個(gè)人項(xiàng)目快速迭代才是關(guān)鍵?,F(xiàn)在這個(gè)版本已經(jīng)是第三次重構(gòu)后的結(jié)果每次重構(gòu)都讓代碼更簡(jiǎn)潔、更易維護(hù)。