C#开发小技巧
一:小技巧
1.点击选中DataGriView中的某一行数据
private void gv_user_CellClick(object sender, DataGridViewCellEventArgs e) { //e.RowIndex选中行的索引 string emp_no = gv_user.Rows[e.RowIndex].Cells[1].Value.ToString(); MessageBox.Show(emp_no); }
2.配置文件传递参数
- 导入:using System.Configuration;
- 创建一个Config文件(用户应用配置文件);
- 定义全局变量,接收传递过来的参数的值;


项目重新生成后,有一个配置文件,直接在配置文件中修改参数的值。
3.动态修改配置文件
1.配置文件

2.获取配置文件

3. 编写方法,更新配置文件节点的相对应的key的value值
private void UpdateConfig(string key, string value) { // 通过Xml方式(需using System.xml;) XmlDocument doc = new XmlDocument(); doc.Load(Application.ExecutablePath + ".config"); XmlNode node = doc.SelectSingleNode(@"//add[@key='" + key + "']"); // 定位到add节点 XmlElement element = (XmlElement)node; element.SetAttribute("value", value); // 赋值 doc.Save(Application.ExecutablePath + ".config"); ConfigurationManager.RefreshSection("appSetting"); // 刷新节点 //// 利用Configuration //Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); //config.AppSettings.Settings[key].Value = value; //config.Save(ConfigurationSaveMode.Full); //ConfigurationManager.RefreshSection("appSettings"); }
4.代码调用存储过程
1.存储过程
create or replace procedure insert_emp(v_empno emp.empno%type, --输入参数 v_ename emp.ename%type, v_job emp.job%type, v_mgr emp.mgr%type, v_sal emp.sal%type, v_deptno emp.deptno%type) as v_count number; begin select count(*) into v_count from emp where empno = v_empno; if v_count > 0 then raise_application_error(-20789, '增加失败,该部门已经存在'); else insert into emp values (v_empno, v_ename, v_job, v_mgr, sysdate, v_sal, null, v_deptno); end if; commit; exception when others then dbms_output.put_line('sqlerrm=' || sqlerrm); rollback; end;
2.创建一个OracleManager类用来管理数据库的连接和SQL语句的执行等
public class OracleManager { static private OracleConnection conn; private OracleManager() { string connStr = "User Id=scott;Password=123456;Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.5.201)(PORT=1523)))(CONNECT_DATA=(SERVICE_NAME=ORCL)))"; conn = new OracleConnection(connStr); } /// <summary> /// 单例模式,对该类进行单例化 /// </summary> static public OracleManager Instance = new OracleManager(); /// <summary> /// 打开数据库连接 /// </summary> public void OpenDb() { try { if (conn.State == ConnectionState.Closed) conn.Open(); } catch (OracleException ex) { //MessageBox.Show(ex.Message); } } /// <summary> /// 关闭数据库连接 /// </summary> public void CloseDb() { try { if (conn.State != ConnectionState.Closed) conn.Close(); } catch (System.Exception ex) { //MessageBox.Show(ex.Message); } } }
3.创建一个函数Callproc来调用数据存储过程
public void CallProc(int empno, string ename, string job, int mgr, int sal, int deptno) { try { OracleCommand orc = conn.CreateCommand(); orc.CommandType = CommandType.StoredProcedure; orc.CommandText = "INSERT_EMP"; orc.Parameters.Add("v_empno", OracleDbType.Int32).Direction = ParameterDirection.Input; orc.Parameters["v_empno"].Value = empno; orc.Parameters.Add("v_ename", OracleDbType.Varchar2).Direction = ParameterDirection.Input; orc.Parameters["v_ename"].Value = ename; orc.Parameters.Add("v_job", OracleDbType.Varchar2).Direction = ParameterDirection.Input; orc.Parameters["v_job"].Value = job; orc.Parameters.Add("v_mgr", OracleDbType.Int32).Direction = ParameterDirection.Input; orc.Parameters["v_mgr"].Value = mgr; orc.Parameters.Add("v_sal", OracleDbType.Int32).Direction = ParameterDirection.Input; orc.Parameters["v_sal"].Value = sal; orc.Parameters.Add("v_deptno", OracleDbType.Int32).Direction = ParameterDirection.Input; orc.Parameters["v_deptno"].Value = deptno; orc.ExecuteNonQuery(); } catch (System.Exception ex) { } }
在CallProc中我们使用数据库连接对象conn创建了一个OracleCommand对象orc,该对象用来进行调用存储过程的相关设置:比如在其CommandText字段中设置过程名,在其Parameters字段中添加存储过程所需的参数等等。我们调用该方法:
OracleManager.Instance.OpenDb(); OracleManager.Instance.CallProc(7600, "Hyman", "SalesMan", 7698, 3000, 30);
OracleManager.Instance.CloseDb();
5.代码接收存储过程返回的结果集
create or replace procedure sp_getdept (result out sys_refcursor) as begin open result for select * from dept; end;
通过代码可以看到,oracle中通过游标sys_refcursor实现返回一个table格式的结构集。注意定义方式result out sys_refcursor,跟C#中out 参数类型有点类似。
sys_refcursor和cursor比较:
(1)sys_refcursor不能用open,close,fetch进行操作。可以用作参数。
(2)cursor可以用open,close,fetch操作。不可以用作参数
private void Form1_Load(object sender, EventArgs e) { OracleConnection con = new OracleConnection("server=orcl;uid=scott;pwd=tiger"); OracleCommand cmd = new OracleCommand("sp_getdept", con); cmd.CommandType = CommandType.StoredProcedure; OracleParameter p1 = new OracleParameter("result", OracleType.Cursor); p1.Direction = System.Data.ParameterDirection.Output; cmd.Parameters.Add(p1); OracleDataAdapter da = new OracleDataAdapter(cmd); DataSet ds = new DataSet(); da.Fill(ds); this.dataGridView1.DataSource = ds.Tables[0]; }
6.语音播报
(1) 添加System.Speech引用;
(2) using System.Speech.Synthesis;
(3) 方法:
private void Player(string str) { SpeechSynthesizer speech = new SpeechSynthesizer(); speech.Rate = 0;//语速为正常语速 speech.SpeakAsync(str); }
7.播放本地音频


音频放在程序生成的位置

8.窗体之间传参
1.添加两个窗体

(2)父窗体传递给子窗体
方法一:通过Form类构造方法的重载传参
//父窗体 public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { Form2 f2 = new Form2(textBox1.Text); f2.ShowDialog(); } } //子窗体 public partial class Form2 : Form { public Form2() { InitializeComponent(); } public Form2(string str) { InitializeComponent(); textBox2.Text = str;//这句必须放在InitializeComponent();的后面,否则会引起“空引用异常 } }
方法二:通过外部可访问的中间变量传参
(1)无法实现目的的做法
//父窗体 public partial class Form1 : Form { public Form1() { InitializeComponent(); } public string str; //public类型的实例字段 private void button1_Click(object sender, EventArgs e) { Form2 f2 = new Form2(); str = textBox1.Text; f2.ShowDialog(); } } //子窗体 public partial class Form2 : Form { public Form2() { InitializeComponent(); } private void Form2_Load(object sender, EventArgs e) { Form1 f1 = new Form1(); textBox2.Text = f1.str; } }
效果:

Form1 f1 = new Form1();相当于新建了一个对象,这个新对象的str初始值是null(只有该对象的button1被click的时候才会改变str的值)。textBox2.Text = f1.str;其实就是将null赋值textBox2.Text。
(2)正确做法
//父窗体 public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { Form2 f2 = new Form2(); f2.str = textBox1.Text; f2.ShowDialog(); } } //子窗体 public partial class Form2 : Form { public Form2() { InitializeComponent(); } public string str;//这里str是在Form2类中定义的,并且不需要static关键字 private void Form2_Load(object sender, EventArgs e) { Form1 f1 = new Form1(); textBox2.Text = str; } }
f2.str = textBox1.Text;将textBox1的值赋给f2.str,由于f2.ShowDialog();跳出来的刚好是这个对象,因此这个对象的str值不为空。最终通过textBox2.Text = str;将值传过去了。跟上一个例子的不同之处是:str声明的位置不一样,一个是在Form1类中,一个是在Form2类中。
(2)子窗体传递给父窗体
方法一:通过Owner设置窗口归属传值
public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { Form2 f2 = new Form2(); f2.ShowDialog(this);//这个this必不可少(将窗体显示为具有指定所有者:窗体f2的所有者是Form1类当前的对象) } } public partial class Form2 : Form { public Form2() { InitializeComponent(); } public string str;//这里str是在Form2类中定义的,并且不需要static关键字 private void Form2_Load(object sender, EventArgs e) { Form1 f1 = (Form1)this.Owner;//将本窗体的拥有者强制设为Form1类的实例f1 f1.Controls["textBox1"].Text = textBox2.Text; } }
方法二:通过提供外部可访问的属性和DialogResult的状态来传值(同时实现了父传子、子传父)
public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { Form2 f2 = new Form2(); f2.TextBox2Value = textBox1.Text;//顺便把父窗体的值先传给子窗体 if (f2.ShowDialog() == DialogResult.OK)//这样的语句是合法的:DialogResult f = f2.ShowDialog(); { textBox1.Text = f2.TextBox2Value; //f2.Close();//这一句写或者不写,f2都会关闭 } } } public partial class Form2 : Form { public Form2() { InitializeComponent(); } public string TextBox2Value //将外部不可访问的textBox2.Text封装成属性TextBox1Value { set { textBox2.Text = value; } get { return textBox2.Text; } } private void button2_Click(object sender, EventArgs e) { this.DialogResult = DialogResult.OK;//这里的DialogResult是Form2类对象的属性 } }
方法三:通过委托事件来传值。(这种方式可以实现不同控件数据实时联动的复杂功能)
public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { Form2 f2 = new Form2(); f2.ChangeText += new ChangeTextHandler(Change_Text);//将事件和处理方法绑在一起,这句话必须放在f2.ShowDialog();前面 f2.ShowDialog(); } public void Change_Text(string str) { textBox1.Text = str; } } //Form2窗体(子窗体传递值给父窗体) public delegate void ChangeTextHandler(string str); //定义委托 public partial class Form2 : Form { public Form2() { InitializeComponent(); } public event ChangeTextHandler ChangeText; //定义事件 private void button2_Click(object sender, EventArgs e) { if (ChangeText != null) { ChangeText(textBox2.Text);//执行委托实例 this.Close(); } } }
9.调用Bartender服务并打印bartender标签

添加引用

实现:
public partial class Form1 : Form { public Form1() { InitializeComponent(); } BarTender.Application btApp; BarTender.Format btFormat; private void button1_Click(object sender, EventArgs e) { int a =1;//设置打印数量的变量 btFormat = btApp.Formats.Open(@"D:\文档1.btw", false, ""); btFormat.PrintSetup.IdenticalCopiesOfLabel = 5; //设置同序列打印的份数 btFormat.PrintSetup.NumberSerializedLabels = a; //设置需要打印的序列数 btFormat.SetNamedSubStringValue("姓名", "车达辉"); //向bartender模板传递变量 btFormat.SetNamedSubStringValue("年龄", "26"); btFormat.SetNamedSubStringValue("性别", "男"); btFormat.SetNamedSubStringValue("工作", "MES开发工程师"); btFormat.SetNamedSubStringValue("住址", "广东"); btFormat.SetNamedSubStringValue("身份识别码", "车达辉最帅"); btFormat.PrintOut(true, true); //第二个false设置打印时是否跳出打印属性 //btFormat.Close(BarTender.BtSaveOptions.btSaveChanges); //退出时保存标签 btFormat.Close(BarTender.BtSaveOptions.btDoNotSaveChanges); //退出时不保存标签 } private void Form1_FormClosed(object sender, FormClosedEventArgs e) { btApp.Quit(BarTender.BtSaveOptions.btSaveChanges);//界面退出时同步退出bartender进程 } private void Form1_Load(object sender, EventArgs e) { btApp = new BarTender.Application(); } }
效果:


11..VS中监测程序运行的时间
System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch(); stopwatch.Start(); //监测运行的程序 if (CompareInputBarcodes() && chb_overstation.Checked) OverStation(); SetDataSource(); stopwatch.Stop(); //Console.WriteLine("{0}:{1}", "", stopwatch.ElapsedMilliseconds * 0.001); //Console.ReadLine(); MessageBox.Show((stopwatch.ElapsedMilliseconds * 0.001).ToString());
|
System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch(); stopwatch.Start(); //监测运行的程序 if (CompareInputBarcodes() && chb_overstation.Checked) OverStation(); SetDataSource(); stopwatch.Stop(); //Console.WriteLine("{0}:{1}", "", stopwatch.ElapsedMilliseconds * 0.001); //Console.ReadLine(); MessageBox.Show((stopwatch.ElapsedMilliseconds * 0.001).ToString()); |
即,将所要监测的程序放到stopwatch.Start()和stopwatch.Stop()中间;
12.读取Excel数据
方法一:
/// <summary> /// 读取Execel文件 /// </summary> /// <returns></returns> public DataTable getData() { //打开文件 OpenFileDialog file = new OpenFileDialog(); file.Filter = "Excel(*.xlsx)|*.xlsx|Excel(*.xls)|*.xls"; file.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); file.Multiselect = false; if (file.ShowDialog() == DialogResult.Cancel) return null; //判断文件后缀 var path = file.FileName; string fileSuffix = System.IO.Path.GetExtension(path); if (string.IsNullOrEmpty(fileSuffix)) return null; using (DataSet ds = new DataSet()) { //判断Excel文件是2003版本还是2007版本 string connString = ""; if (fileSuffix == ".xls") connString = "Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source=" + path + ";" + ";Extended Properties=\"Excel 8.0;HDR=YES;IMEX=1\""; else connString = "Provider=Microsoft.ACE.OLEDB.12.0;" + "Data Source=" + path + ";" + ";Extended Properties=\"Excel 12.0;HDR=YES;IMEX=1\""; //读取文件 string sql_select = " SELECT * FROM [Sheet1$]"; using (OleDbConnection conn = new OleDbConnection(connString)) using (OleDbDataAdapter cmd = new OleDbDataAdapter(sql_select, conn)) { conn.Open(); cmd.Fill(ds); } if (ds == null || ds.Tables.Count <= 0) return null; return ds.Tables[0]; } }
方法二:
/// <summary> /// 读取Bom表数据 /// </summary> /// <param name="filePath">路径</param> /// <returns></returns> public DataTable ReadExcelBom(string filePath) { try { DataSet dtSet = new DataSet(); //连接字符串 string connstring = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + filePath + ";Extended Properties='Excel 8.0;HDR=NO;IMEX=1';"; // Office 07及以上版本 不能出现多余的空格 而且分号注意 //string connstring = Provider=Microsoft.JET.OLEDB.4.0;Data Source=" + path + ";Extended Properties='Excel 8.0;HDR=NO;IMEX=1';"; //Office 07以下版本 using (OleDbConnection conn = new OleDbConnection(connstring)) { conn.Open(); DataTable sheetsName1 = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "Table" }); //得到所有sheet的名字 string firstSheetName1 = sheetsName1.Rows[0][2].ToString(); //得到第一个sheet的名字 string sql1 = string.Format("SELECT * FROM [{0}]", firstSheetName1); //查询字符串 OleDbDataAdapter ada1 = new OleDbDataAdapter(sql1, connstring); ada1.Fill(dtSet); DataTable dt = dtSet.Tables[0]; return dt; } } catch (Exception ex) { MessageBox.Show(ex.Message); return null; } }
13.操作Excel
(1)将数据写到已存在的Excel中
/// <summary> /// 将数据写入Excel模板中 /// </summary> /// <param name="filePath"></param> public void WriteExcel(string filePath) { try { //1.创建Applicaton对象 Microsoft.Office.Interop.Excel.Application xApp = new Microsoft.Office.Interop.Excel.Application(); //2.得到workbook对象,打开已有的文件 Microsoft.Office.Interop.Excel.Workbook xBook = xApp.Workbooks.Open(filePath, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value); //3.指定要操作的Sheet Microsoft.Office.Interop.Excel.Worksheet xSheet = (Microsoft.Office.Interop.Excel.Worksheet)xBook.Sheets[1]; //料号,产品型号,版本,打印日期,机器程序名 string[] msg = txt_message.Text.Split(','); //4.向相应对位置写入相应的数据 //xSheet.Cells[Column(列)][Row(行)] = result; //获取所有单元格,设置列格式 Microsoft.Office.Interop.Excel.Range myrange = xSheet.Cells; //设置单元格文本格式 myrange.NumberFormatLocal= "@"; //自动换行 myrange.WrapText = true; //获取第8行第一列到第400行第八列范围内的所有单元格 Microsoft.Office.Interop.Excel.Range range = xSheet.Range[xSheet.Cells[8,1],xSheet.Cells[400,8]];//.Cells[8]; //水平居中 range.HorizontalAlignment = Microsoft.Office.Interop.Excel.XlHAlign.xlHAlignCenter; //垂直居中 range.VerticalAlignment= Microsoft.Office.Interop.Excel.XlHAlign.xlHAlignCenter; //表头(1-7行是表头) xSheet.Cells[1][4] = "机器程序名:" + msg[4]; xSheet.Cells[1][6] = "产品型号product type:" + msg[1]; xSheet.Cells[5][5] = "半成品编号:" + msg[0]; xSheet.Cells[5][6] = "制表日期:" + msg[3]; xSheet.Cells[7][5] = "版本:" + msg[2]; //定义一个集合,用于存放合并单元格的范围值 List<string> list = new List<string>(); int index = 8; #region 表身 for (int i = 0; i < dgvTran.Rows.Count; i++) { string machine = dgvTran.Rows[i].Cells[0].Value.ToString();//机器 string station = dgvTran.Rows[i].Cells[1].Value.ToString()+" "; //站位 string itemcode = dgvTran.Rows[i].Cells[2].Value.ToString(); //料号 string description = dgvTran.Rows[i].Cells[3].Value.ToString();//描述 string numbers = dgvTran.Rows[i].Cells[4].Value.ToString();//用量 string positione = dgvTran.Rows[i].Cells[5].Value.ToString();//贴装位置 string feidaModel = dgvTran.Rows[i].Cells[6].Value.ToString();//飞达型号 //从第8行开始属于表身 xSheet.Cells[1][8 + i] = machine; xSheet.Cells[2][8 + i] = station; xSheet.Cells[3][8 + i] = itemcode; xSheet.Cells[4][8 + i] = description; xSheet.Cells[5][8 + i] = numbers; xSheet.Cells[6][8 + i] = positione; xSheet.Cells[7][8 + i] = feidaModel; //获取合并的范围值 if (i != 0) { //获取每个机器号相同的范围 if (machine != dgvTran.Rows[i - 1].Cells[0].Value.ToString()) { int endIndex = i - 1 + 8; string scope = index + "," + endIndex; list.Add(scope); index = i + 8; } } } #endregion //关闭EXCEL的提示框 xApp.DisplayAlerts = false; //合并第8行第一列到第8行第三列单元格 //range = xSheet.Range[xSheet.Cells[8, 1], xSheet.Cells[10, 1]]; //range.Merge(Missing.Value); //合并单元格 for (int i = 0; i < list.Count; i++) { int start = int.Parse(list[i].Split(',')[0].ToString()); int end= int.Parse(list[i].Split(',')[1].ToString()); range = xSheet.Range[xSheet.Cells[start, 1], xSheet.Cells[end, 1]]; range.Merge(Missing.Value); } int num = 8 + dgvTran.Rows.Count; range = xSheet.Range[xSheet.Cells[8, 1], xSheet.Cells[num, 8]]; //设置整个数据区边框为实线 range.Borders.LineStyle = 1; //5.保存保存WorkBook xBook.Save(); //6.从内存中关闭Excel对象 xSheet = null; xBook.Close(); xBook = null; //Excel从内存中退出 xApp.Quit(); xApp = null; } catch (Exception ex) { MessageBox.Show(ex.Message); } }
14.文本框不能手输,以及不能粘贴复制
//定义时间变量用于记录按钮KeyDown的时间 DateTime _dt = DateTime.Now; private void txt_one_KeyUp(object sender, KeyEventArgs e) { _dt = System.DateTime.Now; } /// <summary> /// 获取时间间隔(文本框只能扫描枪输入,手输不行) /// </summary> public int GetTimeParameter(string nodeName) { try { int time = 0; string FilePath = Application.StartupPath + "\\RESPONSETIMESETTING.xml"; XmlDocument xmlDoc = new XmlDocument(); xmlDoc.Load(FilePath); XmlNode cNodes = xmlDoc.SelectSingleNode("COLUMNS"); for (int i = 0; i < cNodes.ChildNodes.Count; i++) { XmlElement xe = (XmlElement)cNodes.ChildNodes[i]; if (xe.GetAttribute("NAME") == nodeName) { time = int.Parse((xe.Attributes["TimeValue"].Value)); } } return time; } catch (Exception ex) { return -1; } } private void txt_one_KeyDown(object sender, KeyEventArgs e) { DateTime _tempDt = System.DateTime.Now; TimeSpan ts = _tempDt.Subtract(_dt); int time = GetTimeParameter("time"); if(cbx_check.Checked) { if (ts.Milliseconds > 300) { MessageBox.Show("禁止手输"); txt_one.Text = "";//清空 } } }

浙公网安备 33010602011771号