個人記賬系統(tǒng):MVVM與SQLite實(shí)戰(zhàn))
1. 項(xiàng)目概述個人記賬小系統(tǒng)的核心價值這個個人記賬小系統(tǒng)是我在業(yè)余時間開發(fā)的一個輕量級財務(wù)管理工具主要解決日常收支記錄的痛點(diǎn)。相比市面上復(fù)雜的記賬軟件它去除了所有冗余功能保留了最核心的記賬、統(tǒng)計和報表功能。整個系統(tǒng)采用WPF框架開發(fā)界面簡潔直觀數(shù)據(jù)存儲在本地SQLite數(shù)據(jù)庫中既保證了隱私性又免去了網(wǎng)絡(luò)依賴。提示系統(tǒng)源碼完全開放特別適合.NET開發(fā)者學(xué)習(xí)WPF數(shù)據(jù)綁定、LINQ查詢和圖表繪制的實(shí)戰(zhàn)應(yīng)用我最初開發(fā)這個系統(tǒng)的動機(jī)很簡單市面上的記賬App要么功能太臃腫要么充斥著廣告。作為一個程序員我更想要一個能完全掌控的、可以隨時自定義功能的解決方案。現(xiàn)在這個版本已經(jīng)穩(wěn)定運(yùn)行了兩年多期間根據(jù)實(shí)際使用反饋迭代了十幾個小版本。2. 系統(tǒng)架構(gòu)與技術(shù)選型2.1 前端界面設(shè)計系統(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記錄每筆交易的金額、類型、分類、時間等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庫實(shí)現(xiàn)動態(tài)圖表支持月度收支趨勢折線圖分類占比餅圖年度對比柱狀圖預(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)計報表生成報表系統(tǒng)采用策略模式支持多種統(tǒng)計維度按日/周/月/年的收支匯總分類對比分析預(yù)算執(zhí)行情況賬戶余額變動統(tǒng)計引擎的核心是LINQ查詢例如// 月度統(tǒng)計示例 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ī)制自動備份每天首次啟動時自動備份數(shù)據(jù)庫手動導(dǎo)出支持導(dǎo)出為JSON/CSV格式云同步可選通過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)鍵問題與解決方案4.1 數(shù)據(jù)綁定性能優(yōu)化初期當(dāng)交易記錄超過5000條時界面會出現(xiàn)明顯卡頓。通過以下措施優(yōu)化虛擬化容器使用VirtualizingStackPanel分頁加載每次只加載當(dāng)前月的記錄延遲渲染對圖表數(shù)據(jù)采用按需加載!-- ListView虛擬化示例 -- ListView VirtualizingStackPanel.IsVirtualizingTrue VirtualizingStackPanel.VirtualizationModeRecycling ListView.ItemTemplate.../ListView.ItemTemplate /ListView4.2 多主題切換實(shí)現(xiàn)為滿足不同用戶的視覺偏好實(shí)現(xiàn)了動態(tài)換膚功能定義資源字典存儲不同主題的顏色和樣式使用ResourceDictionary.MergedDictionaries動態(tài)切換配合MahApps.Metro等UI庫增強(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 跨平臺兼容性處理雖然主要面向Windows但通過以下方式提升了兼容性使用.NET Core 3.1/NET 5而非傳統(tǒng).NET Framework避免調(diào)用Windows特有API數(shù)據(jù)庫層使用跨平臺的SQLite5. 項(xiàng)目部署與使用指南5.1 開發(fā)環(huán)境搭建安裝Visual Studio 2019/2022社區(qū)版即可確保勾選.NET桌面開發(fā)工作負(fù)載克隆源碼倉庫git clone https://example.com/accounting-system.git還原NuGet包dotnet restore5.2 數(shù)據(jù)庫初始化系統(tǒng)首次運(yùn)行時會自動創(chuàng)建數(shù)據(jù)庫結(jié)構(gòu)如需手動初始化dotnet ef database update5.3 自定義配置通過修改appsettings.json可以調(diào)整默認(rèn)貨幣符號日期顯示格式備份保留天數(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í)自動識別交易類型賬單提醒集成系統(tǒng)通知功能投資跟蹤添加股票、基金等投資記錄移動端適配通過MAUI實(shí)現(xiàn)跨平臺對于想學(xué)習(xí)WPF的開發(fā)者這個項(xiàng)目提供了很好的起點(diǎn)。我在代碼中刻意保持了簡潔性每個核心功能模塊都控制在300行以內(nèi)方便理解。特別推薦重點(diǎn)研究MainWindowViewModel.csMVVM模式的典型實(shí)現(xiàn)TransactionRepository.csEF Core的最佳實(shí)踐ChartHelper.cs動態(tài)圖表的數(shù)據(jù)綁定技巧實(shí)際開發(fā)中最大的教訓(xùn)是不要過早優(yōu)化。初期我花了太多時間設(shè)計完美架構(gòu)后來發(fā)現(xiàn)對于個人項(xiàng)目快速迭代才是關(guān)鍵。現(xiàn)在這個版本已經(jīng)是第三次重構(gòu)后的結(jié)果每次重構(gòu)都讓代碼更簡潔、更易維護(hù)。