NPOI exports the display data of the WPF DataGrid Control, npoiwpf
Recently, when I was working on a project, I needed to export the data displayed in the DataGrid. I encountered a lot of pitfalls in the middle. I would like to record them here for future reference. I also hope to provide some help to users.
The data displayed in the export DataGrid is not the ItemsSource of the export DataGrid. There is a difference between the two. Here we record the display data of the export DataGrid, that is, what you see is what you get.
For example:
I have a People object class, which contains six fields, as shown below:
public class People{ public string Name { get; set; } public int Age { get; set; } public int Sex { get; set; } public string ClassName { get; set; } public string GradeName { get; set; } public string SchoolName { get; set; }}
However, the List <People> set is assigned a value to the ItemsSource of the DataGrid. However, on my page, five fields are displayed, and even one converter is used.
<DataGrid x: Name = "dg_x" CanUserAddRows = "False" AutoGenerateColumns = "False"> <DataGrid. columns> <maid Header = "Name" Binding = "{Binding Name}" Width = "*"/> <maid Header = "Age" Binding = "{Binding Age}" Width = "*"/> <maid Header = "gender" Binding = "{Binding Sex, converter = {StaticResource sexcov} "Width =" * "/> <maid Header =" Grade "Binding =" {Binding GradeName} "Width =" * "/> <maid Header = "school" Binding = "{Binding SchoolName}" Width = "*"/> </DataGrid. columns> </DataGrid>
The result of the export is the data displayed on the DataGrid, with a few styles added.
Next, let's introduce the two pitfalls I encountered during code writing.
I. code sequence Problems
To achieve the above content, we usually need to do two jobs. The first one is to obtain the Cell value of the DataGrid. Basically, we can see a method in a hundred degrees. There are many blogs, as shown below:
Http://www.cnblogs.com/qq247039968/p/4066058.html
There is no problem with this method, but when the DataGrid has a scroll bar, that is, the Row of the DataGrid is not completely rendered.
Suppose I have 30 pieces of data, but I have not dragged the scroll bar. If I click Export directly, the following exception will be thrown:
After reading the code, it is because the presenter is Null. When the breakpoint tracking is continued, it is found that the value of numbench ALS is 0 instead of 1, that is, the returned Null is because no content is obtained.
The reason for the above problems is that the following code is sequential.
We all know that the UpdateLayout function is used to update the layout. The two sections of code first update the layout and then scroll to the rowIndex position. Therefore, the rendering is still not successful.
The correct method is to change the order of the two sentences, scroll first, and then update, so there will be no problem.
Public static class DataGridPlus {// <summary> // obtain the row of the DataGrid /// </summary> /// <param name = "dataGrid"> DataGrid Control </ param> /// <param name = "rowIndex"> DataGrid row number </param> /// <returns> the specified row number </returns> public static DataGridRow GetRow (this DataGrid dataGrid, int rowIndex) {DataGridRow rowContainer = (DataGridRow) dataGrid. itemContainerGenerator. containerFromIndex (rowIndex); if (rowContainer = null) {DataGrid. scrollIntoView (dataGrid. items [rowIndex]); dataGrid. updateLayout (); rowContainer = (DataGridRow) dataGrid. itemContainerGenerator. containerFromIndex (rowIndex);} return rowContainer ;} /// <summary> /// obtain the first sub-Visual Object of the specified type in the parent Visual Object /// </summary> /// <typeparam name = "T"> visual Object Type </typeparam> /// <param name = "parent"> parent Visual Object </param> /// <returns> the first sub-Visual Object of the specified type </returns> public static T GetVisualChild <T> (Visual parent) where T: Visual {T child = default (T); int numVisuals = VisualTreeHelper. getChildrenCount (parent); for (int I = 0; I <numrentals; I ++) {Visual v = (Visual) VisualTreeHelper. getChild (parent, I); child = v as T; if (child = null) {child = GetVisualChild <T> (v);} if (child! = Null) {break;} return child ;} /// <summary> /// obtain the DataGrid Control Cell /// </summary> /// <param name = "dataGrid"> DataGrid Control </param> /// <param name = "rowIndex"> row number of the cell </param> // <param name = "columnIndex"> column number of the cell </param> // <returns> specified cell </returns> public static DataGridCell GetCell (this DataGrid dataGrid, int rowIndex, int columnIndex) {maid = dataGrid. getRow (rowIndex); if (RowContainer! = Null) {maid = GetVisualChild <maid> (rowContainer); maid cell = (maid) presenter. itemContainerGenerator. containerFromIndex (columnIndex); if (cell = null) {dataGrid. scrollIntoView (rowContainer, dataGrid. columns [columnIndex]); cell = (DataGridCell) presenter. itemContainerGenerator. containerFromIndex (columnIndex);} return cell;} return null ;}}DataGridPlus
After you click Export, the scroll bar automatically rolls to the end of the DataGrid.
2. Too many styles and fonts have been created
NPOI's Style is for cells. Therefore, if you export the most common table above, you need at least nine styles. This is not in Font or Style, but in Border.
Rough and fine issues, basically a table, the outer frame of the thick lines, internal is thin lines.
Since NPOI was used for the first time, it was never used before. Therefore, when setting the style, we put it in the for. The idea at that time was to determine the position of the column, or the location of the row to set the Cell style.
However, when the number is small, there is no problem. When the number is large, the number of styles is copied due to the constant New, at that time, it seems that we tested about pieces of data.
Therefore, we need to propose all styles and define them at the beginning. If necessary, assign values directly.
The location is defined by enumeration for ease of use.
public enum CellPosition{ LeftTop, Top, RightTop, Left, Center, Right, LeftBottom, Bottom, RightBottom, None}
Note that NPOI can use DefaultColumnWidth to set the default width, but the default height of DefaultRowHeight and DefaultRowHeightInPoints is not good. I think the author has fixed this problem in 13 years, but I don't know why I still can't afford it. If you know it, I hope you can leave a message to inform me. Thank you.
DEMO source code