使用ClosedXML导出DataGrid至Excel仅显示10行数据求助
问题原因
WPF DataGrid默认启用UI虚拟化机制,仅为当前视图可见的行创建对应的UI控件(比如TextBlock)。你通过GetCellContent(item)读取数据时,未在视图中显示的行没有生成UI元素,返回值为null,导致这些行的数据无法被捕获,最终只导出了可见的10行。
解决办法
方法一:临时关闭UI虚拟化(快速生效)
在DataGrid的XAML标签里添加两个属性,直接关闭虚拟化:
VirtualizingStackPanel.IsVirtualizing="False" VirtualizingStackPanel.VirtualizationMode="Standard"
修改后的DataGrid代码:
<DataGrid AutoGenerateColumns="False" ItemsSource="{Binding Source}" CanUserAddRows="False" HeadersVisibility="All" Name="dgDisplay" VirtualizingStackPanel.IsVirtualizing="False" VirtualizingStackPanel.VirtualizationMode="Standard"> <DataGrid.Columns> <DataGridTextColumn Header="Day" Binding="{Binding Day}"/> <DataGridTextColumn Header="Data" Binding="{Binding Data}"/> </DataGrid.Columns> </DataGrid>
60行数据量很小,关闭虚拟化不会有性能问题,能快速解决导出不全的问题。
方法二:直接从数据源导出(MVVM规范做法)
既然用了MVVM.Toolkit,别绕UI控件取数据,直接操作ViewModel里的Source集合才是正确思路,既规避虚拟化问题,也符合MVVM设计原则。
修改RelayCommand代码:
[RelayCommand] public void SaveDataGridToExcel() { DataTable dt = new DataTable(); // 先添加列 dt.Columns.Add("Day"); dt.Columns.Add("Data"); // 直接遍历绑定的数据源 foreach (var item in Source) // Source是你ViewModel中绑定给DataGrid的集合 { DataRow dr = dt.NewRow(); dr["Day"] = item.Day; dr["Data"] = item.Data; dt.Rows.Add(dr); } SaveFileDialog saveFileDialog = new SaveFileDialog(); saveFileDialog.Filter = "Excel files (*.xlsx)|*.xlsx"; if (saveFileDialog.ShowDialog() == DialogResult.OK) { using (XLWorkbook wb = new XLWorkbook()) { wb.Worksheets.Add(dt, "Sheet1"); wb.SaveAs(saveFileDialog.FileName); } } }
同时修改Button的绑定,不用再传DataGrid参数:
<Button Command="{Binding SaveDataGridToExcelCommand}"/>
这种方法从根源上解决问题,也是MVVM模式下的最佳实践。
内容的提问来源于stack exchange,提问作者zyp8x
相关产品推荐
相关产品推荐

