一、前言
C# 是一种全新的面向对象的语言,是应用于开发 .NET应用程序的专属语言。C# 可以利用 .NET及其开发环境中的所有新特性,从而开发出各种功能丰富的应用系统。
操作界面的设计是应用项目系统中一个十分重要的环节,界面的友好性直接影响用户的操作与使用。以前,我们设计界面时往往是一个窗体设计成一个操作区域,区域上的各类标识与操作控件是绝对地固定在这一个区域内,区域及上面任何一个元素需要改变时都必须通过程序员才能完成,此种方法给用户带来许多不方便。如果程序员在设计应用系统时,将用户操作界面设计成一个动态的、可由用户任意拖拉改变界面区域大小的窗体,在不同的区域上显示不同的、但数据之间又具有关联关系的信息,当某个区域上信息被掩盖时,用户利用鼠标拖拉增加该区域大小,从而显示出被掩盖的内容,这种操作界面显得更加友好与方便,同时又类似微软操作系统中的资源管理器。
二、简介
笔者在设计湘电集团公司基础代码体系管理项目中,利用以上思路设计出程序的主操作界面,达到了很好的使用效果。界面分为四个部分,上部为菜单栏与常用功能操作快捷菜单栏,底部为状态栏,中间部分又分左右两部分,左边为代码系统分类树,右边为显示某类代码记录的数据区,用户可以改变左右部分的大小。效果如1所示。
图1 效果图
三、实现
1.定义数据表结构
材料类别表主要存储材料类别信息,该表中的数据主要通过TreeView控件显示,表的结构类似于递归法设计,表中的数据显示在界面的左部分;材料数据表主要存储材料信息,数据通过DataGridView控件显示,表中的数据显示在界面的右部分。
2.窗体
新建一个解决方案,名称为CodeSys,在方案中新建一个Windows窗体,名称为FrmMain.cs,作为系统的主操作界面。动态区域操作界面的设计,主要用到了SplitContainer控件,本例中Orientation属性为“Vertical”(水平)。窗体中用到的主要控件如表2所示。
图2 主要控件的属性设置及用途
3.窗体代码设计
using System;
using System.Collections.Generic;
usin g System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace CodeSys
{
public partial class FrmMain : Form
{
BaseClass.Operation oper = new BaseClass.Operation();
//声明Operation类对象,用于调用其中的方法。
public FrmMain()
{
InitializeComponent();
}
private void FrmMain_Load(object sender, EventArgs e) //窗体初始化
{
this.DataBindGridViewList(); //自定义方法调用
this.SetTreeView(); //自定义方法调用
}
private void DataBindGridViewList() //自定义方法:设置列表列标题、列宽
{
DataSet P_dsDataGridView = null;
DataSet P_dsZC = null;
P_dsDataGridView = oper.GetDataGridViewList(); //表头汉化表数据.
P_dsZC = oper.GetDataSetAll(); //获取真实数据.
dataGridView1.DataSource = P_dsZC.Tables[0].DefaultView;
for (int j = 0; j < P_dsZC.Tables[0].Columns.Count; j++) //列表头汉化.
{
for (int i = 1; i < P_dsDataGridView.Tables[0].Rows.Count; i++)
if (P_dsDataGridView.Tables[0].Rows[i]["fieldName"].ToString() == P_dsZC.Tables[0].Columns[j].ColumnName)
{
dataGridView1.Columns[i-1].HeaderText = P_dsDataGridView.Tables[0].Rows[i]["title"].ToString();
dataGridView1.Columns[i-1].Width = Convert.ToInt16(P_dsDataGridView.Tables[0].Rows[i]["width"].ToString());
dataGridView1.Columns[i-1].Visible = Convert.ToBoolean(P_dsDataGridView.Tables[0].Rows[i]["visible"].ToString());
}
}
}
private void SetTreeView() //自定义方法:通过TreeView显示类别树状菜单
{
trvFile.Nodes.Clear();
//设置TreeView控件的菜单项
DataSet ds = null;
ds = oper.TreeFill();
TreeNode RootNode = null;
TreeNode chileNode = null;
DataTable dt = ds.Tables[0].Copy(); //将类别列表另存一份为dt
DataView dv = new DataView(dt);
dv.RowFilter = "firstID = -1";
//将数据集中的所有记录逐个根据他们之间的关系添加到树形表中
if (dv.Count > 0)
{
foreach (DataRowView myRow in dv)
{
//设置根节点,然后该函数会递归添加所有子节点。
trvFile.Nodes.Add(RootNode = new TreeNode(myRow["Name"].ToString()));
childTreeView(myRow["Name"].ToString(), trvFile.Nodes[0], myRow);
trvFile.SelectedNode = trvFile.Nodes[0]; //选中第一个节点
}
}
chileNode = RootNode.Nodes.Add("未分类", "未分类", 2);
}
private void childTreeView(string childPart, TreeNode childNode, DataRowView childRow)
//自定义方法:将数据添加到TreeView的子节点中
{
string strdeptCharCode = "";
string strdeptName = "";
DataSet ds = null;
ds = oper.TreeFill();
DataTable dt = ds.Tables[0].Copy();
DataView dv = new DataView(dt);
//筛选获得当前传递过来的节点的子项,并将其添加到树形图中
//判断方法是:凡parentIndex等于传递过来的节点的absIndex的,就是该节点的子项
dv.RowFilter = "firstID = '" + childRow["secondID"].ToString() + "'";
//递归的添加每一个节点的所有子节点
foreach (DataRowView myRow in dv)
{
strdeptCharCode = myRow["CharCode"].ToString();
if (strdeptCharCode == "") //特征码为空.
{
strdeptName = myRow["Name"].ToString();
}
if (strdeptCharCode != "") //特征码不为空.
{
strdeptName = "[" + myRow["CharCode"].ToString() + "]" + myRow["Name"].ToString();
}
TreeNode myNode = new TreeNode(strdeptName);
childNode.Nodes.Add(myNode);
//函数递归调用,将所有节点按顺序添加完毕.
childTreeView(strdeptName, myNode, myRow);
}
}
private void FrmMain_FormClosed(object sender, FormClosedEventArgs e) //退出系统.
{
Application.Exit();
}
private void MenuItem7_2_Click(object sender, EventArgs e) //退出系统.
{
if (MessageBox.Show("请确认退出!", "系统提示", MessageBoxButtons.YesNo, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1) == DialogResult.Yes)
Application.Exit();
}
private void timer1_Tick(object sender, EventArgs e) //刷新状态栏显示的日期.
{
staDataTime.Text = DateTime.Now.ToString();
}
private void toolStripButton6_Click(object sender, EventArgs e) //退出系统.
{
if (MessageBox.Show("请确认退出!", "系统提示", MessageBoxButtons.YesNo, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1) == DialogResult.Yes)
Application.Exit();
}
private void trvFile_AfterSelect(object sender, TreeViewEventArgs e)
//选中某节点后,显示对应的信息.
{
DataSet ds = null;
if (e.Node.Text == "湘电代码系统")
{
ds = oper.GetDataSetAll();//所有数据信息
}
else
{
string cNodeText0 = ""; //父节点
string cNodeText1 = ""; //子节点
string cNodeText2 = "";
string cNodeText3 = ""; //特征码
string cNodeValue = ""; //(父+子)节点
cNodeText0 = e.Node.Parent.Text;
cNodeText1 = e.Node.Text;
if(cNodeText1.IndexOf("]")<=-1)
{
if (cNodeText0 == "湘电代码系统") //父节点
{
cNodeValue = cNodeText1; //类名称.
}
else
{
cNodeValue = cNodeText0 + "." + cNodeText1; //类名称.
}
ds = oper.GetDataSetBy_CateNo(cNodeValue); //根据[CateNo]号获取代码.
}
else
{
cNodeText2 = cNodeText1.Substring(0, cNodeText1.IndexOf("]"));
cNodeText3 = cNodeText2.Remove(0, 1); //特征码.
ds = oper.GetDataSetBy_Character(cNodeText3);
//根据[Character]号获取代码.
}
}
dataGridView1.DataSource = ds.Tables[0].DefaultView;
}
private void dataGridView1_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e)
//列序号自动生成,保证每次选取不同节点后,数据按自然顺序生成序号.
{
try
{
using (SolidBrush b = new SolidBrush(this.dataGridView1.RowHeadersDefaultCellStyle.ForeColor))
{
int linenum = e.RowIndex;
DataRowView CurDataRow = (DataRowView)dataGridView1.Rows[linenum].DataBoundItem;
string line = (linenum + 1).ToString();
e.Graphics.DrawString(line, e.InheritedRowStyle.Font, b, e.RowBounds.Location.X + 10, e.RowBounds.Location.Y + 5);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString(), "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}
4.公共类设计
开发项目中以类的形式来组织、封装一些常用的方法和事件,不仅可以提高代码的重用率,也大大方便了代码的管理。
(1)数据层设计
数据层设计主要用于建立逻辑业务层与SQL Server数据库之间的一个访问桥。该层主要实现打开/关闭数据库连接,执行数据的增、删、改、查等功能。
#region 打开数据库连接:主要通过 SqlConnection 类实现,并初始化数据连接字行串,然后通过State属性判断连接状态,如果数据库连接状态为关,则打开数据库连接。
// <summary>
private void Open() // 打开数据库连接
{
if (con == null)
{
//con = new SqlConnection("Data Source=(local);DataBase=DB_CodeSys;User ID=sa;PWD=sa");
con = new SqlConnection("Data Source=×××.×××.×××.×××;DataBase=DB_CodeSys;User ID=sa;PWD=sa");
}
if (con.State == System.Data.ConnectionState.Closed)
con.Open();
}
#endregion
#region 关闭数据库连接:主要通过 SqlConnection 对象的 Close 方法实现。
// <summary>
// 关闭数据库连接
// </summary>
public void Close()
{
if (con != null)
con.Close();
}
#endregion
#region 释放数据库连接资源:主要通过 SqlConnection 对象的 Dispose 方法实现。
// <summary>
// 释放资源
// </summary>
public void Dispose()
{
// 确认连接是否已经关闭
if (con != null)
{
con.Dispose();
con = null;
}
}
#endregion
#region 执行参数命令文本或SQL语句,主要用于执行添加、修改和删除操作.
/// <summary>
/// 执行命令
/// </summary>
/// <param name="procName">命令文本</param>
/// <param name="prams">参数对象</param>
/// <returns></returns>
public int RunProc(string procName, SqlParameter[] prams)
{
SqlCommand cmd = CreateCommand(procName, prams);
cmd.ExecuteNonQuery();
this.Close();
//得到执行成功返回值
return (int)cmd.Parameters["ReturnValue"].Value;
}
/// <summary>
/// 直接执行SQL语句
/// </summary>
/// <param name="procName">命令文本</param>
/// <returns></returns>
public int RunProc(string procName)
{
this.Open();
SqlCommand cmd = new SqlCommand(procName, con);
cmd.ExecuteNonQuery();
this.Close();
return 1;
}
#endregion
(2)逻辑业务层设计
逻辑业务层是建立在数据层设计和表示层设计之上完成的,就是处理功能窗体与数据库操作的业务功能。
namespace CodeSys.BaseClass
{
#region 设置主窗体TreeView菜单项。
/// <summary>
/// 获取TreeView菜单项
/// </summary>
/// <returns></returns>
public DataSet TreeFill()
{
return data.RunProcReturn("select * from tb_CodeTree", "tb_CodeTree");
}
/// <summary>
/// 获取主窗体DataGridView控件的属性设置
/// </summary>
/// <returns></returns>
public DataSet GetDataGridViewList()
{
return data.RunProcReturn("select * from tb_DataGridViewList", "tb_DataGridViewList");
}
#endregion
#region 代码信息——添加
public int InsertBaseZcmc(string zcmc)
{
SqlParameter[] prams = { data.MakeInParam("@zcmc", SqlDbType.VarChar, 50, zcmc),
};
return (data.RunProc("INSERT INTO tb_MTL (zcmc) VALUES (@zcmc)", prams));
}
#endregion
#region 代码信息——修改
public int InsertZcMain(cZcMain zcMain)
{
SqlParameter[] prams = {
data.MakeInParam("@cateno", SqlDbType.VarChar, 50, zcMain.CateNo),
data.MakeInParam("@Character ", SqlDbType.VarChar, 50, zcMain.Character),
data.MakeInParam("@GuiGeCode ", SqlDbType.VarChar, 50, zcMain. GuiGeCode),
data.MakeInParam("@No", SqlDbType.VarChar, 50, zcMain.No),
};
return (data.RunProc("INSERT INTO tb_MTL (cateno,Character,GuiGeCode,No)
"VALUES (@cateno,@Character,@GuiGeCode,@No)", prams));
}
#endregion
#region 代码信息——删除
public int DeleteZcMain(string BH)
{
return data.RunProc("delete from tb_MTL where bh='" + BH + "'");
}
#endregion
}
四、结语
通过使用C# 中标准控件、类模块程序,很好地实现了项目开发的预期目标,使整个系统操作起来更显个性化,特色化。C# 是一种全新的面向对象的语言,程序设计过程中只要充分挖掘 C# 中的一些新个性、新特征,我们可以设计出更为友好的、符合用户要求的不同操作界面。此程序只是起到一个抛砖引玉的作用,大家可以根据自己开发MIS系统的实际要求,借鉴本文所述设计思路,实现个性化的系统设计。
|