表头
在上一节里面,我们已经知道,表头其实是一个Grid。那么有两个最需要解决的问题:
(1)表头列宽变化时,主体和表尾的列宽怎么跟着变化。
(2)如何初始化这个复杂的表头。
第一个问题其实并不难,在Grid每一列右侧,都加入一个GridSplitter,然后添加DragDelta和DragCompleted两个拖动事件即可。
gs.DragDelta += GridSplitter_DragDelta;
gs.DragCompleted += GridSplitter_DragCompleted;
private void GridSplitter_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
{
ResizeWidth();
}
private void GridSplitter_DragCompleted(object sender, System.Windows.Controls.Primitives.DragCompletedEventArgs e)
{
ResizeWidth();
}
在ResizeWidth方法里面,我们调整主体和表尾每一列的宽度。
private void ResizeWidth()
{
if (init)
{
double total = 0;
for (int i = 0; i < total_column; i++)
{
double width = HeadGrid.ColumnDefinitions[i].ActualWidth;
total += width;
BodyGrid.Columns[i].Width = new DataGridLength(width);
foreach (UIElement obj in BottomPanel.Children)
{
StackPanel sp = (StackPanel)obj;
(sp.Children[i] as TextBlock).Width = width;
}
}
HeadGrid.Width = total + 18;
BottomPanel.Width = total;
}
}
对于第二个问题,不同的项目需求,使用的方法也会不一样。我使用了以下的结构体存储表头的结构:
public class HeaderClass
{
public string n { get; set; }
public List<HeaderClass> l { get; set; }
}
这类似于树的节点。可以用XML文件去初始化,也可以读入数据库。读入数据之后,扫描这个结构体,算出有多少行多少列,哪些列需要合并。最核心的三个方法如下:
public void InitHeader(HeaderClass hc)
{
HeadGrid.Children.Clear();
HeadGrid.ColumnDefinitions.Clear();
HeadGrid.RowDefinitions.Clear();
total_row = 0;
total_column = 0;
int layer = 1;
GetRowColumn(hc, layer, ref total_row, ref total_column);
for (int i = 0; i < total_row; i++)
{
HeadGrid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1) });
HeadGrid.RowDefinitions.Add(new RowDefinition());
}
for (int i = 0; i < total_column; i++)
{
HeadGrid.ColumnDefinitions.Add(new ColumnDefinition());
}
HeadGrid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(20) });
int row = 0;
int col = 0;
CreateHeader(hc, row, total_row, ref col);
}
private void GetRowColumn(HeaderClass hc, int layer, ref int row, ref int column)
{
if (hc.l != null && hc.l.Count != 0)
{
layer++;
if (layer > row)
{
row = layer;
}
foreach (HeaderClass hci in hc.l)
{
GetRowColumn(hci, layer, ref row, ref column);
}
}
else
{
column++;
}
}
private int CreateHeader(HeaderClass hc, int row, int total_row, ref int col)
{
if (hc.l != null && hc.l.Count != 0)
{
row++;
int my_col = col;
int col_span = 0;
foreach (HeaderClass hci in hc.l)
{
col_span += CreateHeader(hci, row, total_row, ref col);
}
AddHeader(row * 2 - 1, 1, my_col, col_span, hc.n);
return col_span;
}
else
{
row++;
AddHeader(row * 2 - 1, (total_row - row + 1) * 2 - 1, col, 1, hc.n);
col++;
return 1;
}
}