首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

WPF Toolkit DataGrid 實戰完全指南:從零開始打造企業級資料網格

     編輯:關於.NET

為什麼選擇 WPF Toolkit DataGrid?

WPF 核心庫未內建資料網格,早期開發者只能組合 ListView + GridView 或第三方控件。微軟於 CodePlex 發布 WPF Toolkit,提供功能完整、原生支援虛擬化、排序、分頁、編輯、樣式化的 Microsoft.Windows.Controls.DataGrid,並隨後整合入 .NET Framework 4.0 核心庫(System.Windows.Controls.DataGrid)。本文以 Toolkit 版本為例,API 兩者相容。

三分鐘建立第一個可排序分頁 DataGrid

<Window xmlns:dg="clr-namespace:Microsoft.Windows.Controls;assembly=WpfToolkit"
        Loaded="Window_Loaded">
  <dg:DataGrid x:Name="grid" AutoGenerateColumns="True"/>
</Window>
void Window_Loaded(object sender, RoutedEventArgs e) {
    using (var dc = new NorthwindDataContext())
        grid.ItemsSource = dc.Customers.ToList();  // IEnumerable 即可
}

自動產生欄位、支援點擊欄標排序、預設分頁(設定 PageSize 需配合 PagedCollectionView),零程式碼即擁有基礎 CRUD 體驗。

進階欄位定義:TemplateColumn、ComboBoxColumn、HyperlinkColumn

<dg:DataGrid x:Name="grid" AutoGenerateColumns="False">
  <dg:DataGrid.Columns>
    <dg:DataGridTextColumn Header="客戶編號" Binding="{Binding CustomerID}" IsReadOnly="True"/>
    <dg:DataGridComboBoxColumn Header="城市" SelectedItemBinding="{Binding City}"
        ItemsSource="{Binding Source={StaticResource CityList}}"/>
    <dg:DataGridTemplateColumn Header="操作">
      <dg:DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
          <Button Content="詳情" Click="Detail_Click" Tag="{Binding CustomerID}"/>
        </DataTemplate>
      </dg:DataGridTemplateColumn.CellTemplate>
    </dg:DataGridTemplateColumn>
  </dg:DataGrid.Columns>
</dg:DataGrid>
  • DataGridComboBoxColumn 直接指定 ItemsSource(靜態資源或繫結集合),編輯時自動呈現下拉選單。
  • DataGridTemplateColumn 區分 CellTemplate(檢視模式)與 CellEditingTemplate(編輯模式),支援任意複雜 UI。

自訂欄位樣式:依賴屬性 + DataTrigger 動態高亮主鍵欄

繼承 DataGridTextColumn 加入 IsPrimaryKey 依賴屬性:

public class CustomColumn : DataGridTextColumn {
    public static readonly DependencyProperty IsPrimaryKeyProperty =
        DependencyProperty.Register("IsPrimaryKey", typeof(bool), typeof(CustomColumn), new PropertyMetadata(false));
    public bool IsPrimaryKey { get => (bool)GetValue(IsPrimaryKeyProperty); set => SetValue(IsPrimaryKeyProperty, value); }
}

在 AutoGeneratingColumn 事件中依據 LINQ to SQL 中繼資料判斷主鍵並替換欄位實例:

void grid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e) {
    var metaTable = dc.Mapping.GetTable(typeof(Customer));
    var isPK = metaTable.RowType.IdentityMembers.Any(m => m.MappedName == e.Column.Header.ToString());
    if (isPK) {
        var col = new CustomColumn { Header = e.Column.Header, Binding = (e.Column as DataGridBoundColumn).Binding };
        col.IsPrimaryKey = true;
        e.Column = col;
    }
}

CellStyle 使用 DataTrigger 綁定欄位屬性:

<Style x:Key="cellStyle" TargetType="dg:DataGridCell">
  <Style.Triggers>
    <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Column.(local:CustomColumn.IsPrimaryKey)}" Value="True">
      <Setter Property="Background" Value="Tan"/>
      <Setter Property="Foreground" Value="Red"/>
    </DataTrigger>
    <Trigger Property="IsEditing" Value="True">
      <Setter Property="Foreground" Value="Blue"/>
      <Setter Property="FontWeight" Value="Bold"/>
    </Trigger>
  </Style.Triggers>
</Style>

RowStyle 同理高亮編輯中列:

<Style x:Key="rowStyle" TargetType="dg:DataGridRow">
  <Style.Triggers>
    <Trigger Property="IsEditing" Value="True">
      <Setter Property="BorderBrush" Value="Red"/>
      <Setter Property="BorderThickness" Value="2"/>
    </Trigger>
  </Style.Triggers>
</Style>

使用者互動控制:雙向繫結暴露 DataGrid 行為屬性

將 DataGrid 所有行為屬性(CanUserAddRows、CanUserDeleteRows、CanUserSortColumns、GridLinesVisibility、ColumnHeaderHeight 等)透過 CheckBox/ComboBox 雙向繫結暴露給使用者,零程式碼實現「使用者自訂網格外觀」:

<CheckBox Content="允許新增" IsChecked="{Binding ElementName=grid, Path=CanUserAddRows, Mode=TwoWay}"/>
<ComboBox SelectedItem="{Binding ElementName=grid, Path=GridLinesVisibility}">
  <dg:DataGridGridLinesVisibility>All</dg:DataGridGridLinesVisibility>
  <dg:DataGridGridLinesVisibility>Horizontal</dg:DataGridGridLinesVisibility>
  <dg:DataGridGridLinesVisibility>Vertical</dg:DataGridGridLinesVisibility>
  <dg:DataGridGridLinesVisibility>None</dg:DataGridGridLinesVisibility>
</ComboBox>

分頁支援:PagedCollectionView 與 PagableRepeater

  • DataGrid 內建分頁:需包裝 PagedCollectionView 並設定 PageSize,DataGrid 自動顯示分頁導航(需 Template 定制)。
  • PagableRepeater:Toolkit 附贈繼承 Repeater 並擴充 PageIndex/PageSize 的輕量控件,配合 NBearDataSource 或 SqlDataSource 實現伺服器端分頁,適合非表格式清單呈現。

效能優化關鍵清單

  1. 啟用虛擬化:VirtualizingStackPanel.IsVirtualizing="True"(預設開啟),大量資料僅實例化可視列。
  2. 固定行高:RowHeight="28" 避免測量開銷。
  3. 凍結欄位:FrozenColumnCount="2" 鎖定左側欄位水平捲動時不動。
  4. 避免 AutoGenerateColumns:明確定義 Columns 減少反射與型別檢查。
  5. 非同步資料載入:ItemsSource 繫結 Task<List<T>> 或使用 BackgroundWorker,UI 執行緒不阻塞。

常見坑點與解法

現象原因解法
編輯後資料不回寫實體未實作 INotifyPropertyChanged 或 Binding Mode 錯誤實體繼承 ObservableObject;Binding 加 Mode=TwoWay
ComboBoxColumn 下拉無資料ItemsSource 繫結上下文錯誤(預設為 DataGrid DataContext)使用 StaticResource 或 RelativeSource 找正確來源
排序無效ItemsSource 非 ICollectionView 或未支援排序包裝 ListCollectionView 或 DomainDataSource
記憶體隨捲動增長CellTemplate 含未釋放事件訂閱或大型圖片使用 WeakEventPattern;圖片設定 DecodePixelWidth
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved