应用场景:1用SQL语句从数据库返回一个DataTable对象,2然后绑定到DataGridView控件上,DataGridView列头显示的是数据库里的英文字段名,3要显示中文,需要建个对应的EM实体模型,并设置DisplayName特性;4DataGridView的某一行数据赋值给EM实体实例;5EM实体实例绑定到PropertyGrid控件上;6在PropertyGrid上进行增删改查的操作是很方便的。
1窗口布局
新建一个WinForm项目:ReflectionAndAttribute;摆放一个SplitContainer,Dock=Fill;左边放一个DataGridView:dgv,Dock=Fill;右边放一个PropertyGrid:pg,Dock = Fill;创建好后布局大概如下图:
2绑定DataGridView:dgv
-窗口创建Load事件,代码如下:
private void Form1_Load(object sender, System.EventArgs e)
{
OracleDML.ConnectionString = "Data Source=CQYH;User Id=nmis;password=nmis";
DataTable dt = OracleDML.AllTables();
dgv.DataSource = dt;
}
-其中OracleDML.AllTables()代码如下:
/// <summary>
/// 数据库的全部表
/// </summary>
/// <returns></returns>
public static DataTable AllTables()
{
string sql_tables = @"select TABLE_NAME,COMMENTS ,TABLE_TYPE
from user_tab_comments
where table_type = 'TABLE'
order by table_name";
DataTable allTables = OracleDML.GetDataTable(sql_tables);
allTables.TableName = "allTables";
return allTables;
}
-其中OracleDML.GetDataTable()代码如下:
/// <summary>
/// 查询SQL_select,返回一个DataTable , 200207 add by Sufuq
/// </summary>
/// <param name="cmdText"></param>
/// <returns></returns>
public static DataTable GetDataTable(string SQL_select)
{
//OracleCommand cmd = new OracleCommand();
using (OracleConnection connection = new OracleConnection(ConnectionString))
{
OracleDataAdapter ada = new OracleDataAdapter(SQL_select, connection);
//OracleCommandBuilder ocb = new OracleCommandBuilder(ada); //更新时需要这个
DataTable dt = new DataTable();
ada.Fill(dt);
return dt;
}
}
-绑定后的运行效果
3创建EM实体类AllTables
创建换一个EM实体类,并加上[DisplayName()]特性
using System.ComponentModel;
namespace ReflectionAndAttribute
{
class AllTables
{
[DisplayName("表名")]
public string TABLE_NAME { get; set; }
[DisplayName("中文名")]
public string COMMENTS { get; set; }
[DisplayName("类型")]
public string TABLE_TYPE { get; set; }
}
}
4重点来了列头变中文名
-Form1_Load添加如下一样代码:
//列头设置为中文
AttributeHelper.SetColumnDisplayName(typeof(AllTables), dgv);
-其中SetColumnDisplayName()用到反射和特性
/// <summary>
/// 根据DataGridView绑定数据源的列名获取EM实体模型的显示名,用来设置列标题。
/// </summary>
/// <param name="em"></param>
/// <param name="dgv"></param>
public static void SetColumnDisplayName(Type em , DataGridView dgv)
{
for (int i = 0; i < dgv.Columns.Count; i++)
{
string colName = dgv.Columns[i].Name;
string DisName = GetDisplayName(em, colName);
dgv.Columns[i].HeaderCell.Value = DisName;
}
}
/// <summary>
/// 获取类的DisplayName显示名
/// </summary>
/// <param name="modelType">类名</param>
/// <param name="propertyDisplayName">类属性名</param>
/// <returns></returns>
public static string GetDisplayName(Type modelType, string propertyDisplayName)
{
DisplayNameAttribute dna = TypeDescriptor.GetProperties(modelType)[propertyDisplayName].Attributes[typeof(DisplayNameAttribute)] as DisplayNameAttribute ;
string displayName = "";
if (dna == null)
{
displayName = propertyDisplayName;
}
else
{
displayName = dna.DisplayName;
}
return displayName;
//return (TypeDescriptor.GetProperties(modelType)[propertyDisplayName].Attributes[typeof(DisplayNameAttribute)] as DisplayNameAttribute).DisplayName;
}
5DataGridView某行数据实例化allTables并绑定PropertyGrid
-Form1上dgv添加RowEnter事件
private void dgv_RowEnter(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex >= 0 && e.ColumnIndex >= 0)
{
int row = e.RowIndex;
//DataGridview行数据实例化AllTables
AllTables em = AttributeHelper.DgvRowBindTOEM(dgv, row, typeof(AllTables)) as AllTables;
//绑定到PropertyGrid
pg.SelectedObject = em;
}
}
-其中DgvRowBindTOEM用到反射和特性
/// <summary>
/// DataGridView的某行绑定到实体模型EM
/// </summary>
/// <param name="dgv"></param>
/// <param name="row"></param>
/// <param name="em"></param>
/// <returns></returns>
public static object DgvRowBindTOEM(DataGridView dgv ,int row,Type tEM)
{
//根据类型实例化一个对象
object emReturn = System.Activator.CreateInstance(tEM);
//dgv的一行数据复制给实体模型对象
for (int i = 0; i < dgv.Columns.Count; i++)
{
string colName = dgv.Columns[i].Name.ToLower(); //数据库名 = 列名.ToLower = 属性名
//string pName = StringHelper.FirstUpper(colName);//这里还可以加列名转属性名
PropertyInfo pInfo = tEM.GetProperty(colName); //根据列名取属性信息
object value = dgv.Rows[row].Cells[colName].Value; //列的数据值
if (value == System.DBNull.Value) value = value.ToString(); //数据库null转换为string
pInfo.SetValue(emReturn,value,null); //赋值给实例对象colName属性
}
return emReturn;
}
-最终完成效果
6对数据的增删改查
6.1查询, DataGridView的查询过滤参阅https://www.jianshu.com/p/b3d6ff3c93d6
6.2新增,只要把绑定在PropertyGrid的类清空即可
比如这样:
AllTables em = new AllTables();
pG.SelectedObject = em;
6.3删除,只要把PropertyGrid绑定的类传给数据访问层操作即可
AllTables em = (AllTables )pG.SelectedObject;
OracleDML.Delete(em);
6.4修改,只要把PropertyGrid绑定的类传给数据访问层操作即可
AllTables em = (AllTables )pG.SelectedObject;
OracleDML.Update(em);