WPF DataGrid进阶实战 | 20+个实用技巧让你的数据表格更强大!
·

大家好!在之前中我们学习了DataGrid的基础生成,今天来深入探讨DataGrid的各种高级功能和实用技巧,让你的数据展示更加专业和强大!
一、数据绑定和更新技巧
// 使用ObservableCollection实现自动更新public ObservableCollection<Employee> Employees { get; } = new ObservableCollection<Employee>();private void LoadData(){ Employees.Clear(); foreach (var emp in GetEmployeesFromDatabase()) { Employees.Add(emp); }}private void AddNewEmployee(Employee employee){ Employees.Add(employee); // 界面自动更新!}private void UpdateEmployee(int index, Employee updatedEmployee){ Employees[index] = updatedEmployee; // 自动更新!}
2. 数据源切换
// 动态切换不同的数据源public void SwitchDataSource(List<Employee> newData){ dataGrid.ItemsSource = null; // 先清空 dataGrid.ItemsSource = newData; // 设置新数据源}// 使用CollectionViewSource进行高级数据操作public void SetupCollectionView(){ ICollectionView view = CollectionViewSource.GetDefaultView(Employees); view.Filter = item => FilterEmployee(item as Employee); view.SortDescriptions.Add(new SortDescription("Name", ListSortDirection.Ascending));}
二、列功能增强
1. 动态列管理
// 动态添加列private void AddDynamicColumn(string header, string bindingPath){ DataGridTextColumn column = new DataGridTextColumn { Header = header, Binding = new Binding(bindingPath), Width = new DataGridLength(1, DataGridLengthUnitType.Star) };
dataGrid.Columns.Add(column);}// 动态移除列private void RemoveColumn(string header){ var column = dataGrid.Columns.FirstOrDefault(c => c.Header.ToString() == header); if (column != null) { dataGrid.Columns.Remove(column); }}// 显示/隐藏列private void ToggleColumnVisibility(string header, bool isVisible){ var column = dataGrid.Columns.FirstOrDefault(c => c.Header.ToString() == header); if (column != null) { column.Visibility = isVisible ? Visibility.Visible : Visibility.Collapsed; }}
2. 高级列类型
private DataGridTemplateColumn CreateProgressColumn(){ DataGridTemplateColumn column = new DataGridTemplateColumn(); column.Header = "完成进度";
// 单元格模板 FrameworkElementFactory progressFactory = new FrameworkElementFactory(typeof(ProgressBar)); progressFactory.SetValue(ProgressBar.ValueProperty, new Binding("Progress")); progressFactory.SetValue(ProgressBar.MinimumProperty, 0); progressFactory.SetValue(ProgressBar.MaximumProperty, 100); progressFactory.SetValue(ProgressBar.HeightProperty, 20.0);
DataTemplate cellTemplate = new DataTemplate(); cellTemplate.VisualTree = progressFactory; column.CellTemplate = cellTemplate;
return column;}private DataGridTemplateColumn CreateRatingColumn(){ DataGridTemplateColumn column = new DataGridTemplateColumn(); column.Header = "评分";
// 使用ItemsControl创建星级显示 FrameworkElementFactory stackFactory = new FrameworkElementFactory(typeof(StackPanel)); stackFactory.SetValue(StackPanel.OrientationProperty, Orientation.Horizontal);
FrameworkElementFactory itemsFactory = new FrameworkElementFactory(typeof(ItemsControl)); itemsFactory.SetBinding(ItemsControl.ItemsSourceProperty, new Binding("RatingStars"));
DataTemplate starTemplate = new DataTemplate(); FrameworkElementFactory starFactory = new FrameworkElementFactory(typeof(TextBlock)); starFactory.SetValue(TextBlock.TextProperty, "★"); starFactory.SetValue(TextBlock.ForegroundProperty, Brushes.Gold); starTemplate.VisualTree = starFactory;
itemsFactory.SetValue(ItemsControl.ItemTemplateProperty, starTemplate); stackFactory.AppendChild(itemsFactory);
DataTemplate cellTemplate = new DataTemplate(); cellTemplate.VisualTree = stackFactory; column.CellTemplate = cellTemplate;
return column;}
三、行功能增强
1. 行样式和模板
<!-- 行详细信息模板 --><DataGrid.RowDetailsTemplate> <DataTemplate> <Border Background="#FFF0F0F0" Padding="10" Margin="5"> <StackPanel> <TextBlock Text="{Binding Description}" TextWrapping="Wrap"/> <StackPanel Orientation="Horizontal" Margin="0,5,0,0"> <TextBlock Text="创建时间:" FontWeight="Bold"/> <TextBlock Text="{Binding CreateTime, StringFormat=yyyy-MM-dd}" Margin="5,0,0,0"/> </StackPanel> </StackPanel> </Border> </DataTemplate></DataGrid.RowDetailsTemplate><!-- 行样式 --><DataGrid.RowStyle> <Style TargetType="DataGridRow"> <Setter Property="Background" Value="White"/> <Setter Property="Height" Value="35"/>
<Style.Triggers> <!-- 鼠标悬停效果 --> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="Background" Value="#FFE3F2FD"/> </Trigger>
<!-- 选择行效果 --> <Trigger Property="IsSelected" Value="True"> <Setter Property="Background" Value="#FF2196F3"/> <Setter Property="Foreground" Value="White"/> </Trigger>
<!-- 行状态样式 --> <DataTrigger Binding="{Binding Status}" Value="Inactive"> <Setter Property="Background" Value="#FFFFCDD2"/> <Setter Property="Foreground" Value="#FFB71C1C"/> </DataTrigger>
<DataTrigger Binding="{Binding Status}" Value="Completed"> <Setter Property="Background" Value="#FFC8E6C9"/> <Setter Property="Foreground" Value="#FF1B5E20"/> </DataTrigger> </Style.Triggers> </Style></DataGrid.RowStyle>
2. 行号显示
// 添加行号列private void AddRowNumberColumn(){ DataGridTemplateColumn rowNumberColumn = new DataGridTemplateColumn(); rowNumberColumn.Header = "#"; rowNumberColumn.Width = new DataGridLength(40);
// 创建单元格模板 FrameworkElementFactory textBlockFactory = new FrameworkElementFactory(typeof(TextBlock)); textBlockFactory.SetBinding(TextBlock.TextProperty, new Binding(".") { RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, typeof(DataGridRow), 1), Converter = new RowNumberConverter() }); textBlockFactory.SetValue(TextBlock.HorizontalAlignmentProperty, HorizontalAlignment.Center); textBlockFactory.SetValue(TextBlock.VerticalAlignmentProperty, VerticalAlignment.Center);
DataTemplate cellTemplate = new DataTemplate(); cellTemplate.VisualTree = textBlockFactory; rowNumberColumn.CellTemplate = cellTemplate;
dataGrid.Columns.Insert(0, rowNumberColumn);}// 行号转换器public class RowNumberConverter : IValueConverter{ public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { DataGridRow row = value as DataGridRow; if (row != null) return row.GetIndex() + 1; return null; }
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { throw new NotImplementedException(); }}
四、排序和过滤
// 自定义排序public class CustomSorter{ public static void ApplySort(DataGrid dataGrid, string propertyName, ListSortDirection direction) { ICollectionView view = CollectionViewSource.GetDefaultView(dataGrid.ItemsSource); view.SortDescriptions.Clear(); view.SortDescriptions.Add(new SortDescription(propertyName, direction)); }
// 多列排序 public static void ApplyMultiSort(DataGrid dataGrid, params (string Property, ListSortDirection Direction)[] sorts) { ICollectionView view = CollectionViewSource.GetDefaultView(dataGrid.ItemsSource); view.SortDescriptions.Clear();
foreach (var sort in sorts) { view.SortDescriptions.Add(new SortDescription(sort.Property, sort.Direction)); } }}// 使用示例private void SortByNameAscending(){ CustomSorter.ApplySort(dataGrid, "Name", ListSortDirection.Ascending);}private void SortByMultipleColumns(){ CustomSorter.ApplyMultiSort(dataGrid, ("Department", ListSortDirection.Ascending), ("Salary", ListSortDirection.Descending) );}
2. 实时过滤
// 过滤管理器public class DataGridFilter{ private string _filterText = ""; private Predicate<object> _filterPredicate;
public void ApplyFilter(DataGrid dataGrid, string filterText, string[] searchProperties) { _filterText = filterText?.ToLower() ?? "";
if (string.IsNullOrEmpty(_filterText)) { _filterPredicate = null; } else { _filterPredicate = item => SearchInItem(item, searchProperties); }
ICollectionView view = CollectionViewSource.GetDefaultView(dataGrid.ItemsSource); view.Filter = _filterPredicate; }
private bool SearchInItem(object item, string[] properties) { foreach (var property in properties) { var propInfo = item.GetType().GetProperty(property); if (propInfo != null) { var value = propInfo.GetValue(item)?.ToString().ToLower(); if (value != null && value.Contains(_filterText)) return true; } } return false; }}// 使用示例private void SetupFiltering(){ var filter = new DataGridFilter();
// 设置搜索框文本变化事件 searchTextBox.TextChanged += (s, e) => { filter.ApplyFilter(dataGrid, searchTextBox.Text, new[] { "Name", "Department", "Email" }); };}
五、分页功能
public class PaginationManager<T>{ private readonly ObservableCollection<T> _allItems; private readonly int _pageSize; private int _currentPage = 1;
public ObservableCollection<T> CurrentPageItems { get; } = new ObservableCollection<T>(); public int TotalPages => (int)Math.Ceiling((double)_allItems.Count / _pageSize); public int CurrentPage => _currentPage;
public PaginationManager(ObservableCollection<T> allItems, int pageSize = 20) { _allItems = allItems; _pageSize = pageSize; UpdateCurrentPage(); }
public void GoToPage(int pageNumber) { if (pageNumber >= 1 && pageNumber <= TotalPages) { _currentPage = pageNumber; UpdateCurrentPage(); } }
public void NextPage() { if (_currentPage < TotalPages) { _currentPage++; UpdateCurrentPage(); } }
public void PreviousPage() { if (_currentPage > 1) { _currentPage--; UpdateCurrentPage(); } }
private void UpdateCurrentPage() { CurrentPageItems.Clear();
var startIndex = (_currentPage - 1) * _pageSize; var endIndex = Math.Min(startIndex + _pageSize, _allItems.Count);
for (int i = startIndex; i < endIndex; i++) { CurrentPageItems.Add(_allItems[i]); }
OnPageChanged?.Invoke(this, EventArgs.Empty); }
public event EventHandler OnPageChanged;}// 在DataGrid中使用分页private PaginationManager<Employee> _paginationManager;private void SetupPagination(){ _paginationManager = new PaginationManager<Employee>(Employees, 15); dataGrid.ItemsSource = _paginationManager.CurrentPageItems;
// 更新分页信息显示 _paginationManager.OnPageChanged += (s, e) => { UpdatePaginationInfo(); };
UpdatePaginationInfo();}private void UpdatePaginationInfo(){ pageInfoText.Text = $"第 {_paginationManager.CurrentPage} 页,共 {_paginationManager.TotalPages} 页"; prevButton.IsEnabled = _paginationManager.CurrentPage > 1; nextButton.IsEnabled = _paginationManager.CurrentPage < _paginationManager.TotalPages;}
通过这些高级技巧,你的DataGrid将具备:
✅ 强大的数据管理:实时更新、分页、过滤、排序
✅ 丰富的交互功能:多选、编辑、验证、导出
✅ 优秀的用户体验:虚拟化、主题切换、自定义样式
✅ 专业的视觉效果:行样式、单元格模板、动画效果
由于篇幅过长以上内容分为两篇哦敬请期待下一篇DataGrid进阶用法,有问题欢迎在评论区讨论哦!
|
|
|
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐




所有评论(0)