其实鼠标右键菜单也是一个控件,不过这个控件不会在UI里面参与布局,使用的时候需要绑定其它UI控件使用。
拖一个contextMenuStrip到项目中,IDE自动命名为contextMenuStrip1,选中这个控件,在IDE的左上角就会给出输入框,可以输入菜单的名称,其实就是菜单项的Text属性值,可以使用IDE自动命名的名字,也可以自行修改,但要保证name属性值是唯一的。
项目中contextMenuStrip是要绑定dataGridView1来使用的,也就是dataGridView1列出的记录里面才会有鼠标右键菜单,先对dataGridView1的一些属性进行修改,如不能多选,每次只能选择一行,不能只选一个单元格,一选就是一行,而且可以使用鼠标右键来选。把MutiSelect设置为False,意思就是不能选单元格;把SelectionMode设为FullRowSelect,意思是选中一行。
好,现在开始绑定鼠标右键。找到dataGridView1的CellMouseDown事件,编写代码就搞定了。
private void dataGridView1_CellMouseDown(object sender, DataGridViewCellMouseEventArgs e)//浏览会议数据鼠标右键菜单
{
if (e.Button == MouseButtons.Right)
{
if (e.RowIndex >= 0)
{
dataGridView1.ClearSelection();
dataGridView1.Rows[e.RowIndex].Selected = true;
dataGridView1.CurrentCell = dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex];
contextMenuStrip1.Show(MousePosition.X, MousePosition.Y);
}
}
}
这代码很简单,先是检测是否为鼠标右键按下 if (e.Button == MouseButtons.Right)就是干这个活的,接着看是否有数据,if (e.RowIndex >= 0)负责干这活,满足条件就开始干活,先清除所有已经选择的选项,其实是多余的,怕前面有全选,如果dataGridView1没有设置单选一行可能会造成这问题,所以安全起见,清除一下,接着指定鼠标位置所在行为选中行,并在鼠标当前位置弹出右键菜单。鼠标右键菜单就那么简单,几句代码就搞定了。
效果如上图,我添加了好几个右键菜单,操作选项添加同样的内容,有了鼠标右键菜单是不是感觉操作选项是多余的?我就是这么想的。右键菜单功能很多,不要想多了,我不会把所有功能代码都给出来的,哈哈,留点想法给小家伙们去实现。
会议是有计划的,但计划不如变化,标题可能会改,时间也可能会改,会议室也可能会改,甚至会取消,所以先实现“编辑基本资料”,修改资料。
当前窗体是无法满足修改的资料的需要了,所以需要新建一个窗体来完成,这个新建我会详细讲讲,以后就不会再讲,一律以新建××窗体来说,反正方法都是一个鸟样的。
在MeetingManage用鼠标右键,弹出菜单中选择“添加->新建Windows 窗体”,自己改个好听的名字的,本例中就用EditMeeting,记住这个名字,后面操作都是依靠这个名字来玩的。
设置一下EditMeeting的属性,让它看起来有点样子,把最小化、最大化的图标关掉,把样式设置为对话框的样式,取消任务栏图标,拖一堆需要的控件的,如下图。
接下来就讲讲如何使用鼠标右键菜单弹出这个窗体,并把会议的资料传递到这个新窗体中。
先在EditMeeting窗体中定义一个全局变量,并在窗体构造函数中进行赋值。
public string sID = "";
public EditMeeting(string sMeetingID)
{
sID = sMeetingID;
InitializeComponent();
很简单的代码,定义一个全局字符串变量sID,修改构造函数,添加参数string sMeetingID,并在构造函数里面给sID赋值,sID = sMeetingID。
回到主窗体,由于鼠标右键菜单和操作选项都需要使用同一个操作,就弄个函数来弹出新窗体,代码量能省一点是一点嘛。
private void EditMeetingInfo(string sMeetingID)//弹窗编辑会议基本资料
{
EditMeeting eForm = new EditMeeting(sMeetingID);
eForm.Owner = this;
eForm.ShowDialog();
}
代码很简单,先创建一个EditMeeting窗体实例,注意参数,把这个函数的参数传递到EditMeeting窗体去了,接着声明弹窗的主体是本窗体,这样关闭掉弹窗后就会回到本窗体了,最后声明弹窗的方式是ShowDialog(),意思就是对话框的方式弹窗,这样弹出的新窗体未关闭前,其余窗体都无法使用,避免误操作。
好,现在是在鼠标右键菜单中选第一个菜单,就是“编辑基本资料”那个菜单,在其事件中找到Click事件,编写代码,本例中这条菜单命名为toolStripMenuItem1,这样代码就如下了。
private void toolStripMenuItem1_Click(object sender, EventArgs e)
{
string sMeetingID = dataGridView1.CurrentRow.Cells[0].Value.ToString();
EditMeetingInfo(sMeetingID);
}
先获取选择行里面第一列的数据,就是会议的ID,把它作为参数传递到EditMeeting窗体中去。如果要使用操作选项也是一样的,这里就不再多说了。
接下来初始化EditMeeting窗体,加载数据库中的数据,对控件进行初始化,总得显示原来的资料是什么,方便修改嘛。
在EditMeeting窗体中找到Load事件,在这个事件中初始化。
private void EditMeeting_Load(object sender, EventArgs e)
{
//sID是上文讲到的全局变量,在构造函数中进行赋值的。
DataTable DT = MeetingData.MdbData.GetDataTable("select * from Meeting where ID="+sID);
//对textBox1进行赋值,从数据库中读取的mName字段
textBox1.Text = DT.Rows[0]["mName"].ToString();
//对开始和结束时间进行赋值,注意这里使用Convert.ToDateTime()函数,因为读取出来的是obj对象,要先转成字符串,再转成日期时间格式才能赋值。
dateTimePicker1.Value = Convert.ToDateTime(DT.Rows[0]["mTimeStar"].ToString());
dateTimePicker2.Value = Convert.ToDateTime(DT.Rows[0]["mTimeOver"].ToString());
//读取会议的ID,为了防止是手工玩数据库的,先判断一下有没有这个ID的会议室
string sRoom = DT.Rows[0]["mRoom"].ToString();
DT= MeetingData.MdbData.GetDataTable("Select * from MeetingRoom");
if (DT.Rows.Count > 0)
{
comboBox1.DataSource = DT;
comboBox1.DisplayMember = "mName";
comboBox1.ValueMember = "ID";
}
else
MessageBox.Show("请先添加会议室!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
//历遍comboBox1选项,就是会议室列表,如果其值与读取出来的会议室ID一样,把它设为选中项。这个有点取巧,如果列表很长,会出现刷屏现象的。
for (int i = 0; i < comboBox1.Items.Count; i++)
{
comboBox1.SelectedIndex = i;
if (comboBox1.SelectedValue.ToString() == sRoom)
break;
}
}
接下来就是提交资料进行修改了,和添加新会议大同小异,区别我会进行注释的。
private void button2_Click(object sender, EventArgs e)//修改会议资料
{
string sTitle = textBox1.Text.Trim();
DateTime dStar = dateTimePicker1.Value;
DateTime dEnd = dateTimePicker2.Value;
string sRoom = comboBox1.SelectedValue.ToString();
if (sTitle == "")
{
MessageBox.Show("会议标题不能为空!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
if (dStar >= dEnd)
{
MessageBox.Show("会议开始时间大于或等于结束时间!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
if (Convert.ToInt32(sRoom) < 1)
{
MessageBox.Show("请选择开会的会议室!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
string[] sField = { "mName", "mTimeStar", "mTimeOver", "mRoom" };
string[] sValue = { "'" + sTitle + "'", "'" + dStar.ToString() + "'", "'" + dEnd.ToString() + "'", sRoom };
//区别一,生成更新指令,而不是插入指令。
string sCmd = MeetingData.MdbData.SQLUpdate("Meeting", sField, sValue,"ID="+sID);
MeetingData.MdbData.SQLCom(sCmd);
if(MessageBox.Show("会议基本资料修改成功,请刷新会议室。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information)==DialogResult.OK)
//区别二,成功后把本窗体关闭掉,回到主窗体。
this.Close();
}
这样关闭窗体回到主窗体,主窗体的dataGridView1不会自动刷新数据的,要手动刷新一下才能看到效果,在窗体设计一个刷新按钮就这用途。
好,看到一个“终止此会议”的按钮吧,右键菜单也看到了吧,就讲讲如何实现这功能吧。
打开数据库,打开Meeting表,添加一个字段“mState”,数据类型为“数字”,默认值为1,用来保存会议的状态,用不同数字来表示不同状态,如规定0代表会议终止,1代表会议准备召开,2代表会议正在召开,反正想怎么定自己说了算。
private void button1_Click(object sender, EventArgs e)//终止此会议
{
MeetingData.MdbData.SQLCom("Update Meeting set mState=0 where ID="+sID);
if (MessageBox.Show("会已经终止!请刷新会议室。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information) == DialogResult.OK)
this.Close();
}
一句SQL语句搞定,就修改个状态而已,同理,可以在窗体的右键菜单里面玩同样的代码。启动会议也一样,把值修改2即可。
由于多了mState这个字段,这样在主窗体中dataGridView1加载时SQL语句就要稍微修改了,要添加筛选条件了。原来是使用“Select ID,mName,mTimeStar,mTimeOver,mRoom from Meeting”的,表示全部选出来,这样我们根据需要,加上筛选条件,如要列出准备召开的会议,就可以使用“Select ID,mName,mTimeStar,mTimeOver,mRoom from Meeting where mState=1”,列出非终止的会议,就可以使用“Select ID,mName,mTimeStar,mTimeOver,mRoom from Meeting where mState<>0”或“Select ID,mName,mTimeStar,mTimeOver,mRoom from Meeting where mState=1 OR mState=2”,这些都是SQL命令而已,深入研究可以百度之。
好,到目前为止,发现这个项目其实就是利用C#来玩弄数据库而已,不外乎就是插入新数据或更新数据而已,其它需要扩展功能也是一样的玩,根据需要在数据库中设计相应的表和字段,通过插入数据或更新数据而已。
下篇博文讲添加会议议程和上传会议文件,其实百度一下C#控件用法,自己也可以搞定的,就是多行文本框的使用和文件拷贝操作而已。