实习那会儿,公司里WinFrom的数据表格也是根据xml配置文件动态生成列的,只怪当时没有好好看源码,后来上网学习里一些有关xml才下手搞一个基于wpf 、c# 动态生成DataGrid列。
想要通过代码生成数据表格列还是得需要了解DataGrid的Columns结构,至于使用xml配置文件可以看我之前的:c#通过model生成/读取xml文件。
简单看一下数据表格列的xaml文本显示的结构:
<DataGrid x:Name="DataGridContent" LoadingRow="DGBuilding_LoadingRow">
<DataGrid.Columns>
<DataGridTextColumn Header="1" Width="150" Binding="{Binding column1}"></DataGridTextColumn>
<DataGridTextColumn Header="2" Width="170" Binding="{Binding column2}"></DataGridTextColumn>
<DataGridTextColumn Header="3" Width="120" Binding="{Binding column3}"></DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
可以看到DataGrid下有<DataGrid.Columns>再下一层就是具体的列了。
现在开始简单搭建页面:
<Window x:Class="Demo_XMLLoadDataGridColumn.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Demo_XMLLoadDataGridColumn"
mc:Ignorable="d"
Title="XML配置文件加载数据表格列" Height="450" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition Height="376*"/>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" ScrollViewer.HorizontalScrollBarVisibility="Auto" x:Name="StackPanelControl">
<Button Width="100" Height="20" Content="Column1" x:Name="Column1" Click="Column1_Click" Margin="10"/>
<Button Width="100" Height="20" Content="Column2" x:Name="Column2" Click="Column2_Click" Margin="10"/>
<Button Width="100" Height="20" Content="清除" x:Name="Eliminate" Click="Eliminate_Click" Margin="10"/>
</StackPanel>
<Grid Grid.Row="1">
<DataGrid x:Name="DataGridContent" LoadingRow="DGBuilding_LoadingRow">
</DataGrid>
</Grid>
</Grid>
</Window>
效果图:
再写一个Model用来生成xml配置文件和用来加载数据表格列的。
public class DataGridColumn
{
private string _templateType = string.Empty;
private string _header = string.Empty;
private string _binding = string.Empty;
private string _width = string.Empty;
/// <summary>
/// 数据模板
/// </summary>
public string TemplateType
{
get { return _templateType; }
set { _templateType = value; }
}
/// <summary>
/// 列名字
/// </summary>
public string Header
{
get { return _header; }
set { _header = value; }
}
/// <summary>
/// 绑定
/// </summary>
public string Binding
{
get { return _binding; }
set { _binding = value; }
}
/// <summary>
/// 列长度
/// </summary>
public string Width
{
get { return _width; }
set { _width = value; }
}
}
在页面的构造函数里写生成xml配置文件的代码:
public MainWindow()
{
InitializeComponent();
Directory.CreateDirectory("Xml");//在bin> debug 文件夹下创建名为Xml的文件夹,除非已经存在。
List<DataGridColumn> lstDataGridColumn = new List<DataGridColumn>();
lstDataGridColumn.Add(new DataGridColumn() { Header = "学生姓名", Binding = "Student" ,Width = "100"});
lstDataGridColumn.Add(new DataGridColumn() { Header = "性别", Binding = "Sex" ,Width = "100"});
lstDataGridColumn.Add(new DataGridColumn() { Header = "班级", Binding = "Class" ,Width = "100"});
SetXML("Column1", lstDataGridColumn);
List<DataGridColumn> lstDataGridColumn2 = new List<DataGridColumn>();
lstDataGridColumn2.Add(new DataGridColumn() { TemplateType = "DTTextBlock", Header = "序号", Width = "50" });
lstDataGridColumn2.Add(new DataGridColumn() { Header = "班级", Width = "50" });
lstDataGridColumn2.Add(new DataGridColumn() { Header = "类别", Width = "50" });
SetXML("Column2",lstDataGridColumn2);
}
//初始化XML配置文件
void SetXML(string strXMLName, List<DataGridColumn> lstDataGridColumn)
{
using (Stream stream = File.Open(string.Format("Xml/{0}.xml", strXMLName), FileMode.Create))//在此路径创建一个新xml文件,如果已存在则覆盖
{
var serializer = new XmlSerializer(lstDataGridColumn.GetType());//这个是关键。根据model的属性创建xml节点
serializer.Serialize(stream, lstDataGridColumn);
}
}
关于DataGrid的数据模板,我是在资源字典里写好的,然后再根据key加载到DataGrid里,首先创建一个资源字典:
然后再里面写数据模板。
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Demo_XMLLoadDataGridColumn">
<DataTemplate x:Key="DTTextBlock">
<TextBlock Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType={x:Type DataGridRow}}, Path=Header}"
HorizontalAlignment="Left" VerticalAlignment="Center" Margin="10,0,0,0"></TextBlock>
</DataTemplate>
</ResourceDictionary>
然后记得在主程序的App.xaml写引用此资源字典。
<Application x:Class="Demo_XMLLoadDataGridColumn.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Demo_XMLLoadDataGridColumn"
StartupUri="MainWindow.xaml">
<Application.Resources>
<ResourceDictionary Source="DataGridColumnBase.xaml"/><!--资源字典-->
</Application.Resources>
</Application>
先运行一下程序,让她跑一下生成xml配置文件的代码看看,发现已经成功生成xml配置文件了:
然后再给Column1、Column2和清除按钮添加点击事件,读取配置文件然后把配置文件里的数据给到之前新建的model:DataGridColumn,然后再做代码添加列的操作,详细如下:
private void Column1_Click(object sender, RoutedEventArgs e)
{
SetXMLDataGridColumns("Column1");
}
private void Column2_Click(object sender, RoutedEventArgs e)
{
SetXMLDataGridColumns("Column2");
}
private void Eliminate_Click(object sender, RoutedEventArgs e)
{
DataGridContent.Items.Clear();//移除所有数据
DataGridContent.Columns.Clear();//清除表格的列
}
void SetXMLDataGridColumns(string strDataGridColumnName)
{
DataGridContent.Columns.Clear();//清除表格的列
List<DataGridColumn> lstDataGridColumns = new List<DataGridColumn>();
Directory.CreateDirectory("Xml");
//确定指定的文件是否存在
if (File.Exists(string.Format("Xml/{0}.xml", strDataGridColumnName)))
{
using (var stream = File.OpenRead(string.Format("Xml/{0}.xml", strDataGridColumnName)))
{
var serializer = new XmlSerializer(lstDataGridColumns.GetType());
lstDataGridColumns = serializer.Deserialize(stream) as List<DataGridColumn>;
}
foreach (DataGridColumn item in lstDataGridColumns)
{
Binding binding = new Binding();
if (!string.IsNullOrWhiteSpace(item.Binding))
binding.Path = new PropertyPath(item.Binding);
if (string.IsNullOrWhiteSpace(item.TemplateType))
{
DataGridTextColumn dataGridTextColumn = new DataGridTextColumn();
dataGridTextColumn.Header = item.Header;
dataGridTextColumn.Width = new DataGridLength(Convert.ToDouble(item.Width));
if (!string.IsNullOrWhiteSpace(item.Binding))
dataGridTextColumn.Binding = new Binding(item.Binding);
DataGridContent.Columns.Add(dataGridTextColumn);
}
else
{
DataGridTemplateColumn dataGridTemplateColumn = new DataGridTemplateColumn();
dataGridTemplateColumn.Header = item.Header;
dataGridTemplateColumn.CellTemplate = (DataTemplate)DataGridContent.FindResource(item.TemplateType);//这里根据xml的数据值找到对应的资源文件里的key值的数据模板
DataGridContent.Columns.Add(dataGridTemplateColumn);
}
}
}
else
MessageBox.Show("不存在配置文件!");
}
给数据表格添加行加载事件:LoadingRow;
private void DGBuilding_LoadingRow(object sender, DataGridRowEventArgs e)
{
e.Row.Header = e.Row.GetIndex() + 1;
}
这个是用于数据模板“序号“需要使用到的。
运行程序看一下效果: