C#dataGridView动态增加行时遍历数据结构图的遍历是否存在

c#中datagridview控件动态添加行,如何实现相同数据自动加数据_百度知道
c#中datagridview控件动态添加行,如何实现相同数据自动加数据
如题:c#中datagridview控件动态添加行,如下图数据,当加入新的行时判断当前datagridview是否在该商品(用商品编号标识),如果存在即给该 商品数据加1、金额同样用新数量*价格,如果不存在即把该商品添加到datagridview且数据是1。十分感谢!
我有更好的答案
然后再重新绑定,刷新web页面而你的描述是datagridview是否在该商品怎么会进入死胡同呢,你要插第二条数据的时候,去数据库那边查出来判断,是否存在这条数据,如果存在更新操作,如果不存在就添加操作
采纳率:50%
直接操作数据源就完了呗。
为您推荐:
其他类似问题
datagridview的相关知识
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)
第一章 ASP.NET 教程 (基础)
第二章 ASP.NET 教程(高级)c# datagridview新增列,如何显示更新的内容_百度知道
c# datagridview新增列,如何显示更新的内容
代码1:增加列
DataGridViewTextBoxColumn tb = new DataGridViewTextBoxColumn();
tb.Name = &cjyf&;
tb.HeaderText = &车间应发&;
this.dataGridView1.Columns.Add(tb);
this.dataGridView1.DataSourc...
DataGridView 动态添加新行:DataGridView控件在实际应用中非常实用,特别需要表格显示数据时。可以静态绑定数据源,这样就自动为DataGridView控件添加相应的行。假如需要动态为DataGridView控件添加新行,方法有很多种,下面简单介绍如何为DataGridView控件动态添加新行的两种方法:方法一:int index=this.dataGridView1.Rows.Add();this.dataGridView1.Rows[index].Cells[0].Value = &1&;this.dataGridView1.Rows[index].Cells[1].Value = &2&;this.dataGridView1.Rows[index].Cells[2].Value = &监听&;利用dataGridView1.Rows.Add()事件为DataGridView控件增加新的行,该函数返回添加新行的索引号,即新行的行号,然后可以通过该索引号操作该行的各个单元格,如dataGridView1.Rows[index].Cells[0].Value = &1&。这是很常用也是很简单的方法。方法二:DataGridViewRow row = new DataGridViewRow();DataGridViewTextBoxCell textboxcell = new DataGridViewTextBoxCell();textboxcell.Value = &aaa&;row.Cells.Add(textboxcell);DataGridViewComboBoxCell comboxcell = new DataGridViewComboBoxCell();row.Cells.Add(comboxcell);dataGridView1.Rows.Add(row);2.DataGridView 取得或者修改当前单元格的内容:当前单元格指的是 DataGridView 焦点所在的单元格,它可以通过 DataGridView 对象的 CurrentCell 属性取得。如果当前单元格不存在的时候,返回Nothing(C#是null)// 取得当前单元格内容Console.WriteLine(DataGridView1.CurrentCell.Value);// 取得当前单元格的列 IndexConsole.WriteLine(DataGridView1.CurrentCell.ColumnIndex);// 取得当前单元格的行 IndexConsole.WriteLine(DataGridView1.CurrentCell.RowIndex);另外,使用 DataGridView.CurrentCellAddress 属性(而不是直接访问单元格)来确定单元格所在的行: DataGridView.CurrentCellAddress.Y列:DataGridView.CurrentCellAddress.X 。这对于避免取消共享行的共享非常有用。当前的单元格可以通过设定 DataGridView 对象的 CurrentCell 来改变。可以通过 CurrentCell 来设定DataGridView 的激活单元格。将 CurrentCell 设为 Nothing(null) 可以取消激活的单元格。// 设定 (0, 0) 为当前单元格DataGridView1.CurrentCell = DataGridView1[0, 0];在整行选中模式开启时,你也可以通过 CurrentCell 来设定选定行。/// 向下遍历private void button4_Click(object sender, EventArgs e)...{int row = this.dataGridView1.CurrentRow.Index + 1;if (row & this.dataGridView1.RowCount - 1)row = 0;this.dataGridView1.CurrentCell = this.dataGridView1[0, row];}/// 向上遍历private void button5_Click(object sender, EventArgs e)...{int row = this.dataGridView1.CurrentRow.Index - 1;if (row & 0)row = this.dataGridView1.RowCount - 1;this.dataGridView1.CurrentCell = this.dataGridView1[0, row];}* 注意: this.dataGridView 的索引器的参数是: columnIndex, rowIndex 或是 columnName, rowIndex这与习惯不同。3.DataGridView 行的用户删除操作的自定义:1)无条件的限制行删除操作。默认时,DataGridView 是允许用户进行行的删除操作的。如果设置 DataGridView对象的AllowUserToDeleteRows属性为 False 时,用户的行删除操作就被禁止了。// 禁止DataGridView1的行删除操作。DataGridView1.AllowUserToDeleteRows =但是,通过 DataGridViewRowCollection.Remove 还是可以进行行的删除。补足: 如果 DataGridView 绑定的是 DataView 的话,通过 DataView.AllowDelete 也可以控制行的删除。2)行删除时的条件判断处理。用户在删除行的时候,将会引发 DataGridView.UserDeletingRow 事件。在这个事件里,可以判断条件并取消删除操作。// DataGridView1 的 UserDeletingRow 事件private void DataGridView1_UserDeletingRow( object sender, DataGridViewRowCancelEventArgs e){// 删除前的用户确认。if (MessageBox.Show(&确认要删除该行数据吗?&, &删除确认&,MessageBoxButtons.OKCancel, MessageBoxIcon.Question) != DialogResult.OK){// 如果不是 OK,则取消。e.Cancel =}}4.DataGridView 行、列的隐藏和删除:1) 行、列的隐藏// DataGridView1的第一列隐藏DataGridView1.Columns[0].Visible =// DataGridView1的第一行隐藏DataGridView1.Rows[0].Visible =2) 行头、列头的隐藏// 列头隐藏DataGridView1.ColumnHeadersVisible =// 行头隐藏DataGridView1.RowHeadersVisible = 3) 行和列的删除' 删除名为&Column1&的列DataGridView1.Columns.Remove(&Column1&);' 删除第一列DataGridView1.Columns.RemoveAt(0);' 删除第一行DataGridView1.Rows.RemoveAt(0);4) 删除选中行foreach (DataGridViewRow r in DataGridView1.SelectedRows){if (!r.IsNewRow){DataGridView1.Rows.Remove(r);}}5.DataGridView 列顺序的调整:设定 DataGridView 的 AllowUserToOrderColumns 为 True 的时候,用户可以自由调整列的顺序。当用户改变列的顺序的时候,其本身的 Index 不会改变,但是 DisplayIndex 改变了。你也可以通过程序改变 DisplayIndex 来改变列的顺序。 列顺序发生改变时会引发 ColumnDisplayIndexChanged 事件:// DataGridView1的ColumnDisplayIndexChanged事件处理方法private void DataGridView1_ColumnDisplayIndexChanged(object sender,DataGridViewColumnEventArgs e){Console.WriteLine(&{0} 的位置改变到 {1} &,e.Column.Name, e.Column.DisplayIndex);}6.DataGridView 的右键菜单(ContextMenuStrip):DataGridView, DataGridViewColumn, DataGridViewRow, DataGridViewCell 有 ContextMenuStrip 属性。可以通过设定 ContextMenuStrip 对象来控制 DataGridView 的右键菜单的显示。 DataGridViewColumn 的 ContextMenuStrip 属性设定了除了列头以外的单元格的右键菜单。 DataGridViewRow 的 ContextMenuStrip 属性设定了除了行头以外的单元格的右键菜单。DataGridViewCell 的 ContextMenuStrip 属性设定了指定单元格的右键菜单。// DataGridView 的 ContextMenuStrip 设定DataGridView1.ContextMenuStrip = this.ContextMenuStrip1;// 列的 ContextMenuStrip 设定DataGridView1.Columns[0].ContextMenuStrip = this.ContextMenuStrip2;// 列头的 ContextMenuStrip 设定DataGridView1.Columns[0].HeaderCell.ContextMenuStrip = this.ContextMenuStrip2;// 行的 ContextMenuStrip 设定DataGridView1.Rows[0].ContextMenuStrip = this.ContextMenuStrip3;// 单元格的 ContextMenuStrip 设定DataGridView1[0, 0].ContextMenuStrip = this.ContextMenuStrip4;对于单元格上的右键菜单的设定,优先顺序是: Cell & Row & Column & DataGridView⇒ CellContextMenuStripNeeded、RowContextMenuStripNeeded 事件利用 CellContextMenuStripNeeded 事件可以设定单元格的右键菜单,尤其但需要右键菜单根据单元格值的变化而变化的时候。比起使用循环遍历,使用该事件来设定右键菜单的效率更高。但是,在DataGridView使用了DataSource绑定而且是VirtualMode的时候,该事件将不被引发。// CellContextMenuStripNeeded事件处理方法private void DataGridView1_CellContextMenuStripNeeded(object sender,DataGridViewCellContextMenuStripNeededEventArgs e){DataGridView dgv = (DataGridView)if (e.RowIndex & 0){// 列头的ContextMenuStrip设定e.ContextMenuStrip = this.ContextMenuStrip1;}else if (e.ColumnIndex & 0){// 行头的ContextMenuStrip设定e.ContextMenuStrip = this.ContextMenuStrip2;}else if (dgv[e.ColumnIndex, e.RowIndex].Value is int){// 如果单元格值是整数时e.ContextMenuStrip = this.ContextMenuStrip3;}}同样,可以通过 RowContextMenuStripNeeded 事件来设定行的右键菜单。// RowContextMenuStripNeeded事件处理方法private void DataGridView1_RowContextMenuStripNeeded(object sender,DataGridViewRowContextMenuStripNeededEventArgs e){DataGridView dgv = (DataGridView)// 当&Column1&列是Bool型且为True时、设定其的ContextMenuStripobject boolVal = dgv[&Column1&, e.RowIndex].VConsole.WriteLine(boolVal);if (boolVal is bool && (bool)boolVal){e.ContextMenuStrip = this.ContextMenuStrip1;}}CellContextMenuStripNeeded 事件处理方法的参数中、「e.ColumnIndex=-1」表示行头、「e.RowIndex=-1」表示列头。RowContextMenuStripNeeded则不存在「e.RowIndex=-1」的情况。7.DataGridView 单元格表示值的自定义:通过CellFormatting事件,可以自定义单元格的表示值。(比如:值为Error的时候,单元格被设定为红色)下面的示例:将“Colmn1”列的值改为大写。//CellFormatting 事件处理方法private void DataGridView1_CellFormatting(object sender,DataGridViewCellFormattingEventArgs e){DataGridView dgv = (DataGridView)// 如果单元格是“Column1”列的单元格if (dgv.Columns[e.ColumnIndex].Name == &Column1& && e.Value is string){// 将单元格值改为大写string str = e.Value.ToString();e.Value = str.ToUpper();// 应用该Format,Format完毕。e.FormattingApplied =}}CellFormatting事件的DataGridViewCellFormattingEventArgs对象的Value属性一开始保存着未被格式化的值。当Value属性被设定表示用的文本之后,把FormattingApplied属性做为True,告知DataGridView文本已经格式化完毕。如果不这样做的话,DataGridView会根据已经设定的Format,NullValue,DataSourceNullValue,FormatProvider属性会将Value属性会被重新格式化一遍。8.DataGridView 用户输入时,单元格输入值的设定:通过 DataGridView.CellParsing 事件可以设定用户输入的值。下面的示例:当输入英文文本内容的时候,立即被改变为大写。//CellParsing 事件处理方法private void DataGridView1_CellParsing(object sender,DataGridViewCellParsingEventArgs e){DataGridView dgv = (DataGridView)//单元格列为“Column1”时if (dgv.Columns[e.ColumnIndex].Name == &Column1& &&e.DesiredType == typeof(string)){//将单元格值设为大写e.Value = e.Value.ToString().ToUpper();//解析完毕e.ParsingApplied =}}9.DataGridView 新加行的默认值的设定:需要指定新加行的默认值的时候,可以在DataGridView.DefaultValuesNeeded事件里处理。在该事件中处理除了可以设定默认值以外,还可以指定某些特定的单元格的ReadOnly属性等。// DefaultValuesNeeded 事件处理方法private void DataGridView1_DefaultValuesNeeded(object sender,DataGridViewRowEventArgs e){// 设定单元格的默认值e.Row.Cells[&Column1&].Value = 0;e.Row.Cells[&Column2&].Value = &-&;}10.DataGridView 设定单元格只读:1) 使用 ReadOnly 属性如果希望,DataGridView 内所有单元格都不可编辑, 那么只要:// 设置 DataGridView1 为只读DataGridView1.ReadOnly =此时,用户的新增行操作和删除行操作也被屏蔽了。如果希望,DataGridView 内某个单元格不可编辑, 那么只要:// 设置 DataGridView1 的第2列整列单元格为只读DataGridView1.Columns[1].ReadOnly =// 设置 DataGridView1 的第3行整行单元格为只读DataGridView1.Rows[2].ReadOnly =// 设置 DataGridView1 的[0,0]单元格为只读DataGridView1[0, 0].ReadOnly =2) 使用 EditMode 属性DataGridView.EditMode 属性被设置为 DataGridViewEditMode.EditProgrammatically 时,用户就不能手动编辑单元格的内容了。但是可以通过程序,调用 DataGridView.BeginEdit 方法,使单元格进入编辑模式进行编辑。DataGridView1.EditMode = DataGridViewEditMode.EditP3) 根据条件设定单元格的不可编辑状态当一个一个的通过单元格坐标设定单元格 ReadOnly 属性的方法太麻烦的时候,你可以通过 CellBeginEdit 事件来取消单元格的编辑。// CellBeginEdit 事件处理方法private void DataGridView1_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e){DataGridView dgv = (DataGridView)//是否可以进行编辑的条件检查if (dgv.Columns[e.ColumnIndex].Name == &Column1& && !(bool)dgv[&Column2&, e.RowIndex].Value){// 取消编辑e.Cancel =}}
采纳率:94%
来自团队:
Tables[0],i].Value =cjyf.ToString(),然后dataGridView1;DataSource 指向一个Table。然后直接dataGridView1[&cjyf&;赋值给dataGridView1,就相当于是表面赋值,dataGridView1指向的数据源并没更新。查询的时候应该是查询dataGridView1.DataSource的数据,所以你更新应该更新Table.DataSource = ds你的 dataGridView1.DataSource 指向你更新的Table,查看表时应该就能看到了。一切均为我个人猜想,有待验证
本回答被提问者和网友采纳
你手动调一些cellvaluechange方法应该就出来了。
为您推荐:
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。随笔- 206&
评论- 850&
  在开发WinForm窗体程序时,我们希望增加一个对DataGridView数据进行查找的对话框,类似于Visual Studio中的“查找和替换”对话框,但是功能没有这么复杂,需求如下:
  1. 用户可以通过主窗体中的菜单打开数据查找对话框。
  2. DataGridView数据未加载前不显示查找对话框。
  3. 查找对话框中可以进行大小写匹配和全字匹配。
  4. 查找对话框以非模式对话框的形式显示在主窗体的上面。
  5. DataGridView中高亮显示被查找到的关键字所在的行。
  6. 用户可以在查找对话框中DataGridView中的数据进行循环查找,即用户每进行一次查找,DataGridView都将从上一次查找到的位置开始向下进行查找直到最后一行,然后再从第一行开始继续查找。
  7. 可对DataGridView进行逐行逐列查找。
  对DataGridView进行逐行逐列的遍历并匹配关键字然后高亮显示当前行,这个功能实现起来应该没有什么难度,关键在于如何实现循环查找,并且能够很好地与子窗体(查找对话框)进行互动。另外就是需要实现大小写匹配和圈子匹配,这里需要使用到正则表达式。我们先看一下程序的主界面。
&  主窗体的实现我在这里不具体介绍了,这不是本文的重点,况且上面这个程序截图中还实现了许多其它的功能。我在这里主要介绍一下子窗体的功能以及如何实现DataGridView数据的循环查找。
先来看一下如何打造一个相对美观的查找对话框
  如上图,你可以将用于设置查询参数部分的控件(Match case,Match whole word)放到一个布局控件中,如GroupBox。这样界面看起来会比较专业一些。然后你还需要对子窗体进行一些参数设置,使其看起来更像一个对话框。
  FormBorderStyle: FixedDialog
  Text: Find Record
  Name: FindRecord
  StartPosition: CenterScreen
  AcceptButton: btFindNext (Find Next按钮)
  CancelButton: btCancel (Cancel按钮)
  MaximizeBox: False
  MinimizeBox: False
  ShowIcon: False
  ShowInTaskbar: False
  TopMost: True
给对话框增加一些功能
  首先对话框应该是在全局有效的,否则我们就不能记录每一次查找后DataGridView中被命中的记录的Index。所以对话框窗体的实例应该是在主窗体中被初始化,并且只被实例化一次。每次打开对话框时只是调用实例的Show()方法,关闭对话框时只调用窗体的Hide()方法而不是Close()方法,因为Close()方法会将窗体的实例在内存中注销掉。那么我们需要定义btCancel按钮的事件和重写窗体的FormClosing事件并在其中调用窗体的Hide()方法。
  查询参数中的大小写匹配和全字匹配都是复选框控件,这意味着参数会有多种组合方式,不妨将这些组合定义成一个枚举,一共是四种情况:任意匹配(None),大小写匹配(MatchCase),全字匹配(MatchWholeCase),大小写和全字匹配(MatchCaseAndWholeWord)。
  以事件模型来实现数据查找功能在这里再好不过了。首先需要在查询对话框中定义一个EventHandler,然后在主窗体中订阅这个事件,事件的执行代码写到子窗体的btFindNext按钮的事件中,一共传递三个参数:查询内容,DataGridView的当前行号(用于定位下一次查找),以及查询参数枚举变量。下面是子窗体的具体实现代码:
<span style="color: #&using S <span style="color: #&using System.Collections.G <span style="color: #&using System.ComponentM <span style="color: #&using System.D <span style="color: #&using System.D <span style="color: #&using System.L <span style="color: #&using System.T <span style="color: #&using System.Windows.F <span style="color: #& <span style="color: #&namespace ListItemEditor.UI <span style="color: #&{ <span style="color: #&&&& public&partial&class FindRecord : Form <span style="color: #&&&& { <span style="color: #&&&&&&&& public EventHandler&FindRecordWindowEventArgs& OnFindClick =&null; <span style="color: #&&&&&&&& public&enum FindOptions { None, MatchCase, MatchWholeWord, MatchCaseAndWholeWord } <span style="color: #&&&&&&&& public&int CurrentIndex =&-<span style="color: #; <span style="color: #& <span style="color: #&&&&&&&& public FindRecord() <span style="color: #&&&&&&&& { <span style="color: #&&&&&&&&&&&& InitializeComponent(); <span style="color: #&&&&&&&& } <span style="color: #& <span style="color: #&&&&&&&& private&void btCancel_Click(object sender, EventArgs e) <span style="color: #&&&&&&&& { <span style="color: #&&&&&&&&&&&& this.Hide(); <span style="color: #&&&&&&&& } <span style="color: #& <span style="color: #&&&&&&&& private&void FindRecord_FormClosing(object sender, FormClosingEventArgs e) <span style="color: #&&&&&&&& { <span style="color: #&&&&&&&&&&&& this.Hide(); <span style="color: #&&&&&&&&&&&& e.Cancel =&true; <span style="color: #&&&&&&&& } <span style="color: #& <span style="color: #&&&&&&&& private&void btFindNext_Click(object sender, EventArgs e) <span style="color: #&&&&&&&& { <span style="color: #&&&&&&&&&&&& if (this.tbFindTxt.Text.Trim().Length &&<span style="color: #) <span style="color: #&&&&&&&&&&&& { <span style="color: #&&&&&&&&&&&&&&&& FindOptions options = FindOptions.N <span style="color: #&&&&&&&&&&&&&&&& if (this.chbMatchCase.Checked &&&this.chbMatchWholeWord.Checked) <span style="color: #&&&&&&&&&&&&&&&& { <span style="color: #&&&&&&&&&&&&&&&&&&&& options = FindOptions.MatchCaseAndWholeW <span style="color: #&&&&&&&&&&&&&&&& } <span style="color: #&&&&&&&&&&&&&&&& else&if (this.chbMatchCase.Checked &&&!this.chbMatchWholeWord.Checked) <span style="color: #&&&&&&&&&&&&&&&& { <span style="color: #&&&&&&&&&&&&&&&&&&&& options = FindOptions.MatchC <span style="color: #&&&&&&&&&&&&&&&& } <span style="color: #&&&&&&&&&&&&&&&& else&if (!this.chbMatchCase.Checked &&&this.chbMatchWholeWord.Checked) <span style="color: #&&&&&&&&&&&&&&&& { <span style="color: #&&&&&&&&&&&&&&&&&&&& options = FindOptions.MatchWholeW <span style="color: #&&&&&&&&&&&&&&&& } <span style="color: #&&&&&&&&&&&&&&&& else <span style="color: #&&&&&&&&&&&&&&&& { <span style="color: #&&&&&&&&&&&&&&&&&&&& options = FindOptions.N <span style="color: #&&&&&&&&&&&&&&&& } <span style="color: #&&&&&&&&&&&&&&&& OnFindClick(this, new FindRecordWindowEventArgs(this.tbFindTxt.Text, CurrentIndex, options)); <span style="color: #&&&&&&&&&&&& } <span style="color: #&&&&&&&& } <span style="color: #&&&& } <span style="color: #& <span style="color: #&&&& public&class FindRecordWindowEventArgs : EventArgs <span style="color: #&&&& { <span style="color: #&&&&&&&& private&string sFindT <span style="color: #&&&&&&&& private&int iIndex =&<span style="color: #; <span style="color: #&&&&&&&& private FindRecord.FindOptions findO <span style="color: #& <span style="color: #&&&&&&&& public&string FindTxt <span style="color: #&&&&&&&& { <span style="color: #&&&&&&&&&&&& get { return&this.sFindT } <span style="color: #&&&&&&&& } <span style="color: #& <span style="color: #&&&&&&&& public&int Index <span style="color: #&&&&&&&& { <span style="color: #&&&&&&&&&&&& get { return&this.iI } <span style="color: #&&&&&&&& } <span style="color: #& <span style="color: #&&&&&&&& public FindRecord.FindOptions FindOptions <span style="color: #&&&&&&&& { <span style="color: #&&&&&&&&&&&& get { return&this.findO } <span style="color: #&&&&&&&& } <span style="color: #& <span style="color: #&&&&&&&& public FindRecordWindowEventArgs(string _findTxt, int _index, FindRecord.FindOptions _options) <span style="color: #&&&&&&&& { <span style="color: #&&&&&&&&&&&& this.sFindTxt = _findT <span style="color: #&&&&&&&&&&&& this.iIndex = _ <span style="color: #&&&&&&&&&&&& this.findOptions = _ <span style="color: #&&&&&&&& } <span style="color: #&&&& } <span style="color: #&}
主窗体做了什么
  首先我们需要在主窗体中实例化子窗体并定义查询事件,因此下面这几行代码是必须的:
&1&public&partial&class&Form1&:&Form&2&{&3&&&&&private&FindRecord&winFind&=&new&FindRecord();&4&&5&&&&&public&Form1()&6&&&&&{&7&&&&&&&&&InitializeComponent();&8&&9&&&&&&&&&this.winFind.OnFindClick&+=&new&EventHandler&FindRecordWindowEventArgs&(this.winFind_OnFindClick);<span style="color: #&&&&&}<span style="color: #&}
  FindRecord即子窗体所在的类。下面是具体的数据查询实现及菜单响应代码:
&1&private&void&tlbFind_Click(object&sender,&EventArgs&e)&2&{&3&&&&&if&(!this.DataLoaded)&return;&4&&&&&winFind.Show();&5&}&6&&7&private&void&Form1_KeyDown(object&sender,&KeyEventArgs&e)&8&{&9&&&&&if&(!this.DataLoaded)&return;<span style="color: #&&&&&if&(e.Modifiers&==&Keys.Control&&&&e.KeyCode&==&Keys.F)<span style="color: #&&&&&{<span style="color: #&&&&&&&&&tlbFind.PerformClick();<span style="color: #&&&&&}<span style="color: #&}<span style="color: #&<span style="color: #&private&void&winFind_OnFindClick(object&sender,&FindRecordWindowEventArgs&e)<span style="color: #&{<span style="color: #&&&&&string&s&=&e.FindT<span style="color: #&&&&&int&index&=&e.I<span style="color: #&&&&&bool&bFind&=&false;<span style="color: #&<span style="color: #&&&&&RegexOptions&regOptions&=&RegexOptions.IgnoreC<span style="color: #&&&&&string&pattern&=&Regex.Escape(s);<span style="color: #&<span style="color: #&&&&&if&(e.FindOptions&==&FindRecord.FindOptions.MatchCase&||&e.FindOptions&==&FindRecord.FindOptions.MatchCaseAndWholeWord)<span style="color: #&&&&&{<span style="color: #&&&&&&&&&regOptions&=&RegexOptions.N<span style="color: #&&&&&}<span style="color: #&<span style="color: #&&&&&if&(e.FindOptions&==&FindRecord.FindOptions.MatchWholeWord&||&e.FindOptions&==&FindRecord.FindOptions.MatchCaseAndWholeWord)<span style="color: #&&&&&{<span style="color: #&&&&&&&&&pattern&=&"\\b"&+&pattern&+&"\\b";<span style="color: #&&&&&}<span style="color: #&<span style="color: #&&&&&foreach&(DataGridViewRow&row&in&theGrid.Rows)<span style="color: #&&&&&{<span style="color: #&&&&&&&&&this.winFind.CurrentIndex&=&row.I<span style="color: #&&&&&&&&&foreach&(DataGridViewCell&cel&in&row.Cells)<span style="color: #&&&&&&&&&{<span style="color: #&&&&&&&&&&&&&//if&(cel.Value.ToString().Contains(s))<span style="color: #&&&&&&&&&&&&&if&(Regex.IsMatch(cel.Value.ToString(),&pattern,&regOptions))<span style="color: #&&&&&&&&&&&&&{<span style="color: #&&&&&&&&&&&&&&&&&bFind&=&true;<span style="color: #&&&&&&&&&&&&&&&&&if&(cel.RowIndex&&&index)<span style="color: #&&&&&&&&&&&&&&&&&{<span style="color: #&&&&&&&&&&&&&&&&&&&&&this.theGrid.ClearSelection();<span style="color: #&&&&&&&&&&&&&&&&&&&&&this.theGrid.Rows[cel.RowIndex].Selected&=&true;<span style="color: #&&&&&&&&&&&&&&&&&&&&&return;<span style="color: #&&&&&&&&&&&&&&&&&}<span style="color: #&&&&&&&&&&&&&}<span style="color: #&&&&&&&&&}<span style="color: #&&&&&}<span style="color: #&<span style="color: #&&&&&if&(this.winFind.CurrentIndex&==&this.theGrid.Rows.Count&-&<span style="color: #&&&&bFind)<span style="color: #&&&&&{<span style="color: #&&&&&&&&&this.winFind.CurrentIndex&=&-<span style="color: #;<span style="color: #&&&&&&&&&MessageBox.Show("Find&the&last&record.",&"List&Item&Editor",&MessageBoxButtons.OK,&MessageBoxIcon.Information);<span style="color: #&&&&&&&&&return;<span style="color: #&&&&&}<span style="color: #&<span style="color: #&&&&&if&(!bFind)<span style="color: #&&&&&{<span style="color: #&&&&&&&&&this.winFind.CurrentIndex&=&-<span style="color: #;<span style="color: #&&&&&&&&&MessageBox.Show(string.Format("The&following&specified&text&was&not&found:\r\n{0}",&s),&"List&Item&Editor",&MessageBoxButtons.OK,&MessageBoxIcon.Information);<span style="color: #&&&&&}<span style="color: #&}
  tlbFind_Click是菜单点击事件,在显示子窗体前我们需要通过DataLoaded变量来判断DataGridView是否已经完成数据加载了,这是一个布尔变量,在主窗体中定义的私有变量。Form1_KeyDown事件用来响应Ctrl + F快捷键,如果DataGridView已经完成数据加载并且用户使用了键盘上的Ctrl + F组合键,则执行与tblFind_Click事件相同的操作,这是通过tlbFind.PerformClick()这条语句来完成的。
  winFind_OnFindClick事件实现了具体的数据查询操作,这个事件是子窗体数据查询EventHandler的具体实现。还记得前面提到过的这个吗?我们在子窗体的这个EventHandler中定义了三个参数,用来传递要查询的内容,以及DataGridView的行号和查询参数枚举值。现在在主窗体的这个事件函数中可以通过对象e来获取到这些值。代码中通过两个foreach语句来逐行逐列遍历DataGridView,字符串匹配操作使用了正则表达式,根据查询参数中的枚举值来使用不同的正则表达式匹配项:
  1. 默认情况下正则表达式匹配项被设置成了大小写敏感(RegexOptions.IgnoreCase)
  2. 如果用户在子窗体中选择了大小写匹配,则将正则表达式匹配项修改成None(RegexOptions.None)
  3. 如果用户在子窗体中选择了全字匹配,则使用自定义的正则表达式进行匹配。在正则表达式中,'\b'用来判断单词边界,而'\B'用来判断非单词边界。有关如何使用正则表达式进行全字匹配可以参考下这里的一篇文章。
  也有关于如何使用\b和\B的介绍,并且描述简单明了。
  子窗体中还有一个公共整型变量CurrentIndex,主窗体在遍历DataGridView的同时会修改这个值,将DataGridView的当前行号传递回子窗体,当用户下一次进行查询时,子窗体又会将这个行号传回到主窗体中。你应该已经注意到了在内层的foreach循环语句中有一个判断,如果命中的DataGridView行的行号小于CurrentIndex值,则继续向下查找,直到找到下一个匹配的行,且这个行号要大于CurrentIndex值。如果已经找到DataGridView的最后一行则弹出一个提示信息。bFind布尔变量用于指示是否已经找到匹配的值,如果没有找到,则在程序的最后会弹出一个提示信息。
  好了,程序的所有核心实现都在这里了。其实就是使用了一点小技巧,再就是子窗体通过事件模型去驱动主窗体的数据查询功能,这比直接在子窗体中定义一个public类型的方法要优雅得多,因为这样做避免了在不同的窗体间传递参数的麻烦,代码更加简洁!
阅读(...) 评论()

我要回帖

更多关于 数据结构二叉树遍历 的文章

 

随机推荐