首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

C# ComboBox 繫結 SQL Server 日期欄位不重複年份:完整實作範例

     編輯:MySQL 資料庫相關知識

C# ComboBox 繫結 SQL Server 日期欄位不重複年份:完整實作範例


WinForms / WPF 常見需求:從資料庫日期欄位提取不重複年份繫結至 ComboBox,供使用者篩選年度報表。本文提供完整資料存取封裝、SQL 查詢、繫結屬性設定、預設選項邏輯。


資料存取封裝類(簡化版)

public class MyDBase : IDisposable
{
    private readonly SqlConnection _conn;
    public MyDBase(string server, string db, string user, string pwd)
    {
        var cs = $"Server={server};Database={db};User Id={user};Password={pwd};";
        _conn = new SqlConnection(cs);
        _conn.Open();
    }
    public DataSet GetRecordset(string sql)
    {
        var ds = new DataSet();
        using (var da = new SqlDataAdapter(sql, _conn))
            da.Fill(ds);
        return ds;
    }
    public bool ErrorCode() => false; // 簡化:實際應檢查 _conn.State / 執行例外
    public string ErrMessage() => "";
    public void DBClose() => _conn?.Close();
    public void Dispose() => DBClose();
}

Form 載入事件完整程式碼

private void Education_Training_Load(object sender, EventArgs e)
{
    using (var db = new MyDBase(DBUser.sserver, DBUser.DBName, DBUser.suser, DBUser.spasswd))
    {
        // 1. 查詢不重複年份,降序排列(最新在前)
        const string sql = "SELECT DISTINCT YEAR([date]) AS [Year] FROM education_train ORDER BY [Year] DESC";
        DataSet ds = db.GetRecordset(sql);

        if (ds.Tables[0].Rows.Count == 0) return; // 無資料直接返回

        // 2. 繫結 ComboBox
        comboBox_Year.DataSource = ds.Tables[0];
        comboBox_Year.DisplayMember = "Year";   // 顯示給使用者看的欄位
        comboBox_Year.ValueMember   = "Year";   // 實際取得的值

        // 3. 預設選中最新年份(索引 0,因 SQL 已 DESC)
        comboBox_Year.SelectedIndex = 0;

        // 4. 同步顯示於 DataGridView(示範)
        dataGridView1.DataSource = ds.Tables[0];
    } // using 確保連線關閉
}

關鍵點解析

屬性/方法作用注意事項
SELECT DISTINCT YEAR(date)提取日期欄位年份並去重SQL Server YEAR() 函數回傳 INT
ORDER BY [Year] DESC最新年份在前配合 SelectedIndex=0 直接預設最新
DisplayMember / ValueMember同欄位雙重指定若需顯示「2024 年」格式,可在 SQL 用 CONCAT(YEAR(date),' 年')
SelectedIndex = 0預設選第一項避免 -1 導致無選項
using 區塊自動釋放連線防止連線洩漏,生產碼必加

進階:參數化查詢防注入(若年份來源於使用者輸入)

string sql = "SELECT DISTINCT YEAR([date]) AS [Year] FROM education_train WHERE [date] >= @start ORDER BY [Year] DESC";
using (var cmd = new SqlCommand(sql, _conn))
{
    cmd.Parameters.AddWithValue("@start", startDate);
    using (var da = new SqlDataAdapter(cmd))
        da.Fill(ds);
}

WPF 對應寫法(XAML + MVVM 友善)

<ComboBox x:Name="comboBox_Year" 
          DisplayMemberPath="Year" 
          SelectedValuePath="Year" 
          ItemsSource="{Binding Years}" />
// ViewModel
public ObservableCollection Years { get; } = new();
public async Task LoadYearsAsync()
{
    using (var conn = new SqlConnection(cs))
    using (var cmd = new SqlCommand("SELECT DISTINCT YEAR([date]) FROM education_train ORDER BY 1 DESC", conn))
    {
        await conn.OpenAsync();
        using (var rdr = await cmd.ExecuteReaderAsync())
            while (await rdr.ReadAsync()) Years.Add(rdr.GetInt32(0));
    }
    // 預設選最新
    SelectedYear = Years.FirstOrDefault();
}

常見坑點提醒

  • 日期欄位為 NULL:YEAR(NULL) 回傳 NULL,DISTINCT 會保留一個 NULL 年份 → 繫結時出現空白項。解決:WHERE [date] IS NOT NULL。
  • 資料型別不匹配:ValueMember 為 INT,取值時用 (int)comboBox_Year.SelectedValue,勿用 ToString() 再轉型。
  • 大量年份效能:年份最多幾十個,**極小結果集**,無需分頁/虛擬化。

掌握 DISTINCT YEAR() + DataSource 繫結模式,即可快速實作年度篩選下拉選單,代碼簡潔且易維護。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved