iT邦幫忙

2025 iThome 鐵人賽

DAY 21
0

昨天我們學會了如何從 UI 呼叫 API,把股票清單顯示在 DataGrid 上。
今天要解決一個新問題:離線狀態要怎麼用?

解法是:下載的資料存進 LiteDB,下次啟動時就能先讀取本地資料。


1) 為什麼要加 LiteDB

  • 避免重複呼叫 API → 減少網路消耗
  • 離線可用 → 沒網路也能查詢資料
  • 快取加速 → 開啟程式時可直接讀取本地資料

LiteDB 是一個輕量的 NoSQL 本地資料庫,只會生成一個 .db 檔案,非常適合桌面應用程式。


2) 定義 Repository 介面

為了保持彈性,我們先定義一個資料存取介面 IStockRepository,負責存股票清單。

// Repositories/IStockRepository.cs
using System.Collections.Generic;

public interface IStockRepository
{
    void SaveStocks(IEnumerable<StockProfile> stocks);
    IEnumerable<StockProfile> LoadStocks();
}

3) LiteDB 實作

// Repositories/LiteDbStockRepository.cs
using LiteDB;
using System;
using System.Collections.Generic;

public class LiteDbStockRepository : IStockRepository
{
    private readonly string _dbPath;

    public LiteDbStockRepository(string dbPath = "StockData.db")
    {
        _dbPath = dbPath;
    }

    public void SaveStocks(IEnumerable<StockProfile> stocks)
    {
        using var db = new LiteDatabase(_dbPath);
        var col = db.GetCollection<StockProfile>("stocks");

        col.DeleteAll();            // 先清空,避免重複
        col.InsertBulk(stocks);     // 批次寫入
    }

    public IEnumerable<StockProfile> LoadStocks()
    {
        using var db = new LiteDatabase(_dbPath);
        var col = db.GetCollection<StockProfile>("stocks");
        return col.FindAll();
    }
}

4) ViewModel:整合 API + Repository

  • LoadStocksCommand:呼叫 API → 存 LiteDB → 更新 UI
  • LoadFromLocalCommand:從本地 LiteDB 載入
// ViewModels/StockListViewModel.cs
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Threading.Tasks;
using System.Windows.Input;

public class StockListViewModel : INotifyPropertyChanged
{
    private readonly IStockApiService _api;
    private readonly IStockRepository _repo;

    public ObservableCollection<StockProfile> Stocks { get; } = new ObservableCollection<StockProfile>();

    public ICommand LoadStocksCommand { get; }
    public ICommand LoadFromLocalCommand { get; }

    public StockListViewModel(IStockApiService api, IStockRepository repo)
    {
        _api = api;
        _repo = repo;

        LoadStocksCommand = new AsyncCommand(LoadStocksAsync);
        LoadFromLocalCommand = new RelayCommand(_ => LoadFromLocal());
    }

    private async Task LoadStocksAsync()
    {
        var list = await _api.GetStocksAsync();

        Stocks.Clear();
        foreach (var s in list) Stocks.Add(s);

        _repo.SaveStocks(list); // 存入本地資料庫
    }

    private void LoadFromLocal()
    {
        var list = _repo.LoadStocks();

        Stocks.Clear();
        foreach (var s in list) Stocks.Add(s);
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string name) =>
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}

5) View:新增「載入本地資料」按鈕

<StackPanel Orientation="Horizontal" Margin="8" Spacing="8">
    <Button Content="下載股票 (API)"
            Command="{Binding LoadStocksCommand}" Width="150"/>
    <Button Content="載入本地資料"
            Command="{Binding LoadFromLocalCommand}" Width="150"/>
</StackPanel>

<DataGrid ItemsSource="{Binding Stocks}" AutoGenerateColumns="False" Margin="8">
    <DataGrid.Columns>
        <DataGridTextColumn Header="代號" Binding="{Binding Code}" Width="100"/>
        <DataGridTextColumn Header="名稱" Binding="{Binding Name}" Width="200"/>
        <DataGridTextColumn Header="產業" Binding="{Binding Industry}" Width="*"/>
    </DataGrid.Columns>
</DataGrid>

6) 啟動時的 DataContext 設定

// MainWindow.xaml.cs
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        var http = new HttpClient();
        var api = new TwseStockApiService(http);
        var repo = new LiteDbStockRepository("StockData.db");

        this.DataContext = new StockListViewModel(api, repo);
    }
}

執行效果

  1. 按「下載股票 (API)」→ 呼叫 API,存到 LiteDB,同時更新 DataGrid
  2. 下次啟動或無網路時,按「載入本地資料」→ 從 StockData.db 載入股票清單

小結

今天我們學會了:

  • 使用 LiteDB 儲存股票清單
  • Repository 模式解耦存取邏輯
  • WPF + API + LiteDB 的整合
  • 離線可用的選股工具


上一篇
Day 20 - 整合 API 與 WPF
系列文
30天快速上手製作WPF選股工具 — 從C#基礎到LiteDB與Web API整合21
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言