yalan请进,请教你个问题 我用你的发帖的那个DataGridVeiw拖动行排序的帖子做了个库存管理的东西,可是你的代码的排序时不能用的,你说你知道怎么用循环写数据库,请问怎么写啊?急死我了,我大四刚找到工作,正在实习,经历让我做这个东西,我只会拖控件不会代码,帮帮我吧!你的代码我一点也看不懂,能否给我讲一下呢? 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 你说的是这个帖子吧:http://topic.csdn.net/u/20110210/23/35d508be-4ee2-49f2-8ef9-901571befab8.html用循环的方法写数据是很简单,但我总觉得效率不好,用SqlCommandBuilder更新又出错,郁闷!如果你的数据量比较小的话可以用我的循环的方法来解决,但是对于分页的数据和大量数据的排序并更新数据库我不能保证效率啊。你自己使用的时候改一下连接字符串和查询字符串就行了,别老给我发信息了,真不能帮你做程序,你正在实习,应该多学习,而不是为了做好一个东西讨好经理啊,很多时候经理不是为了让你做东西,而是考验你让你学习,不懂就问公司的前辈,多多学习!!源码:using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Data.SqlClient;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;namespace DragRow{ public partial class MainForm : Form { // 数据表 SqlConnection conn; DataSet ds = new DataSet(); SqlDataAdapter da = new SqlDataAdapter(); SqlCommand cmd = new SqlCommand(); // 拖动的源数据行索引 private int indexOfItemUnderMouseToDrag = -1; // 拖动的目标数据行索引 private int indexOfItemUnderMouseToDrop = -1; // 拖动中的鼠标所在位置的当前行索引 private int indexOfItemUnderMouseOver = -1; // 不启用拖放的鼠标范围 private Rectangle dragBoxFromMouseDown = Rectangle.Empty; public MainForm() { InitializeComponent(); } private void MainForm_Load(object sender, EventArgs e) { //绑定数据 bind(); } //绑定数据表 private void bind() { //从数据库读取数据信息 using (conn=new SqlConnection("data source=127.0.0.1;initial catalog=stlivead;user id=sa;password=sa;")) { SqlCommand cmd = new SqlCommand("select * from playlist order by orderid", conn); da.SelectCommand = cmd; //填充数据表 ds.Clear(); da.Fill(ds, "playlist"); } //设置dataGridView的数据源 dataGridView.DataSource = ds.Tables["playlist"]; } //响应鼠标按下时的事件 private void dataGridView_MouseDown(object sender, MouseEventArgs e) { // 通过鼠标按下的位置获取所在行的信息 //下面行使用了.Net 3.5的类型推断var关键字; //DataGridView的HitTest方法返回一个DataGridView.HitTestInfo,可以使用此方法确定 DataGridView 控件的哪个部分位于指定坐标。 //例如,可以调用方法来指定鼠标单击的坐标,从而确定所单击的单元格的行和列索引,或确定单击的是标头单元格还是滚动条 //因此,下面使用类型推断的语句实质是:DataGridView.HitTestInfo hitTest=dataGridView.HitTest(e.X,e.Y); var hitTest = dataGridView.HitTest(e.X, e.Y); //若不是点击的单元格,那么不执行任何操作,返回 if (hitTest.Type != DataGridViewHitTestType.Cell) return; // 记下要被拖动数据行的索引 indexOfItemUnderMouseToDrag = hitTest.RowIndex; //记下以鼠标按下坐标为中心的不会开始拖动的范围。>-1表示点击的行不是标题行才能进行拖动操作 if (indexOfItemUnderMouseToDrag > -1) { Size dragSize = SystemInformation.DragSize; dragBoxFromMouseDown = new Rectangle(new Point(e.X - (dragSize.Width / 2), e.Y - (dragSize.Height / 2)), dragSize); } else dragBoxFromMouseDown = Rectangle.Empty; } //响应鼠标抬起时的事件 private void dataGridView_MouseUp(object sender, MouseEventArgs e) { // 释放鼠标按键时清空变量为默认值 dragBoxFromMouseDown = Rectangle.Empty; } //当鼠标按下状态移动时开始拖放过程 private void dataGridView_MouseMove(object sender, MouseEventArgs e) { // 当鼠标按键不是鼠标左键时,不移动数据行 if ((e.Button & MouseButtons.Left) != MouseButtons.Left) return; // 如果鼠标在不启用拖动的范围内,不移动数据行 if (dragBoxFromMouseDown == Rectangle.Empty || dragBoxFromMouseDown.Contains(e.X, e.Y)) return; // 如果源数据行索引值不正确,不移动数据行 if (indexOfItemUnderMouseToDrag < 0) return; // 开始拖动,第一个参数表示要拖动的数据,可以自定义,一般是源数据行 var row = dataGridView.Rows[indexOfItemUnderMouseToDrag]; /*DragDropEffects枚举:指定拖放操作的效果 * DragDropEffects成员: * None:放置目标不接受该数据 * Copy:将数据复制到放置目标 * Move:将拖动源的数据移动到放置目标 * Link:将拖动源中的数据链接到放置目标 * Scroll:即将在放置目标中滚动或当前正在滚动 * All:从拖动源复制、移除数据,并将其滚动到放置目标中 */ DragDropEffects dropEffect = dataGridView.DoDragDrop(row, DragDropEffects.All); //拖动过程结束后清除拖动位置行的红线效果 OnRowDragOver(-1); } //当鼠标移动过数据行执行重绘 private void dataGridView_DragOver(object sender, DragEventArgs e) { // 把屏幕坐标转换成控件坐标:PointToClient方法将指定屏幕点的位置计算成工作区坐标。 Point p = dataGridView.PointToClient(new Point(e.X, e.Y)); // 通过鼠标按下的位置获取所在行的信息 // 如果不是在数据行或者在源数据行上则不能作为拖放的目标 var hitTest = dataGridView.HitTest(p.X, p.Y); //如果该位置信息对应的成员类型和拖动的成员类型不同或者位置信息和拖动源相同(相当于从哪里拖出来还放到原来的地方)那么不进行操作 if (hitTest.Type != DataGridViewHitTestType.Cell || hitTest.RowIndex == indexOfItemUnderMouseToDrag) { //不放置 e.Effect = DragDropEffects.None; //移除红线 OnRowDragOver(-1); return; } // 设置为作为拖放移动的目标 e.Effect = DragDropEffects.Move; // 通知目标行重绘,在经过的数据行绘制红线 OnRowDragOver(hitTest.RowIndex); } //当鼠标将数据行拖放至目的行释放时 private void dataGridView_DragDrop(object sender, DragEventArgs e) { // 把屏幕坐标转换成控件坐标 Point p = dataGridView.PointToClient(new Point(e.X, e.Y)); // 如果当前位置不是数据行 // 或者刚好是源数据行的下一行(本示例中假定拖放操作为拖放至目标行的上方) // 则不进行任何操作 var hitTest = dataGridView.HitTest(p.X, p.Y); if (hitTest.Type != DataGridViewHitTestType.Cell || hitTest.RowIndex == indexOfItemUnderMouseToDrag + 1) return; //鼠标放下的改行的行号即为拖放目的行 indexOfItemUnderMouseToDrop = hitTest.RowIndex; //数据推断,新建一个DataTable数据行 var tempRow = ds.Tables["playlist"].NewRow(); //该新建的DataTable数据行的数据即为拖动的源。 tempRow.ItemArray = ds.Tables["playlist"].Rows[indexOfItemUnderMouseToDrag].ItemArray; //因为新建了数据行,所以要移除旧行即拖动源 ds.Tables["playlist"].Rows.RemoveAt(indexOfItemUnderMouseToDrag); //ds.Tables["playlist"].Rows[indexOfItemUnderMouseToDrag].Delete(); if (indexOfItemUnderMouseToDrag < indexOfItemUnderMouseToDrop) indexOfItemUnderMouseToDrop--; //将新建的数据行插入到拖动的目的行 ds.Tables["playlist"].Rows.InsertAt(tempRow, indexOfItemUnderMouseToDrop); //选中被拖动的行 dataGridView.Rows[indexOfItemUnderMouseToDrop].Selected = true; //重排行号和更新数据库 for (int i = 0; i < dataGridView.Rows.Count; i++) { dataGridView.Rows[i].Cells["orderid"].Value = i + 1; using (conn) { conn.Open(); cmd.CommandText = "update playlist set orderid=" + (i + 1) + " where id=" + dataGridView.Rows[i].Cells["id"].Value; cmd.Connection = conn; cmd.ExecuteNonQuery(); conn.Close(); } } GC.Collect(); } private void dataGridView_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e) { // 如果当前行是鼠标拖放过程的所在行 if (e.RowIndex == indexOfItemUnderMouseOver) e.Graphics.FillRectangle(Brushes.Red, e.RowBounds.X, e.RowBounds.Y, e.RowBounds.Width, 3); } private void OnRowDragOver(int rowIndex) { // 如果和上次导致重绘的行是同一行则无需重绘 if (indexOfItemUnderMouseOver == rowIndex) return; int old = indexOfItemUnderMouseOver; indexOfItemUnderMouseOver = rowIndex; // 去掉原有行的红线 if (old > -1) dataGridView.InvalidateRow(old); // 绘制新行的红线 if (rowIndex > -1) dataGridView.InvalidateRow(rowIndex); } }} 这个回答应该够详细了呵呵,同时借用你的帖子问一下高手:我想让用户先拖动行排序,完成后点击保存按钮将所有操作更新到数据库。但是我使用SqlCommandBuilder更新的时候发现操作中拖动了多少行就会新增多少行数据,实在想不明白为什么。纠错的时候尝试使用Delect方法将行从DataSet中删除,但是排序时出错,只能RemoveAt,但是使用RemoveAt方法就会新增行。不明白为什么会这样。 c# 有关注释问题 如何保存一个二维数组的原始值? C#显示数据都是这样的“5.04E-06”,如何显示成0.00000504 .net(C#)接口实现问题,急!高手请进! DataGridView1内容清空 .NET下使用TransactionScope进行事务处理的问题 求大神帮忙数据类型的转换 困扰了N久的问题 新手求教一个有关界面制作的问题(非细节,只征求指导性意见)。。。。。。。。。 如何用C#做出类似与Visual Studio风格的窗体 KeyDown 与 KEYPRESS 用法区别在那里呀, process.start方法的权限问题
你说的是这个帖子吧:http://topic.csdn.net/u/20110210/23/35d508be-4ee2-49f2-8ef9-901571befab8.html用循环的方法写数据是很简单,但我总觉得效率不好,用SqlCommandBuilder更新又出错,郁闷!如果你的数据量比较小的话可以用我的循环的方法来解决,但是对于分页的数据和大量数据的排序并更新数据库我不能保证效率啊。你自己使用的时候改一下连接字符串和查询字符串就行了,别老给我发信息了,真不能帮你做程序,你正在实习,应该多学习,而不是为了做好一个东西讨好经理啊,很多时候经理不是为了让你做东西,而是考验你让你学习,不懂就问公司的前辈,多多学习!!源码:using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;namespace DragRow
{
public partial class MainForm : Form
{
// 数据表
SqlConnection conn;
DataSet ds = new DataSet();
SqlDataAdapter da = new SqlDataAdapter();
SqlCommand cmd = new SqlCommand();
// 拖动的源数据行索引
private int indexOfItemUnderMouseToDrag = -1;
// 拖动的目标数据行索引
private int indexOfItemUnderMouseToDrop = -1;
// 拖动中的鼠标所在位置的当前行索引
private int indexOfItemUnderMouseOver = -1;
// 不启用拖放的鼠标范围
private Rectangle dragBoxFromMouseDown = Rectangle.Empty; public MainForm()
{
InitializeComponent();
} private void MainForm_Load(object sender, EventArgs e)
{
//绑定数据
bind();
} //绑定数据表
private void bind()
{
//从数据库读取数据信息
using (conn=new SqlConnection("data source=127.0.0.1;initial catalog=stlivead;user id=sa;password=sa;"))
{
SqlCommand cmd = new SqlCommand("select * from playlist order by orderid", conn);
da.SelectCommand = cmd;
//填充数据表
ds.Clear();
da.Fill(ds, "playlist");
}
//设置dataGridView的数据源
dataGridView.DataSource = ds.Tables["playlist"]; } //响应鼠标按下时的事件
private void dataGridView_MouseDown(object sender, MouseEventArgs e)
{
// 通过鼠标按下的位置获取所在行的信息
//下面行使用了.Net 3.5的类型推断var关键字;
//DataGridView的HitTest方法返回一个DataGridView.HitTestInfo,可以使用此方法确定 DataGridView 控件的哪个部分位于指定坐标。
//例如,可以调用方法来指定鼠标单击的坐标,从而确定所单击的单元格的行和列索引,或确定单击的是标头单元格还是滚动条
//因此,下面使用类型推断的语句实质是:DataGridView.HitTestInfo hitTest=dataGridView.HitTest(e.X,e.Y);
var hitTest = dataGridView.HitTest(e.X, e.Y);
//若不是点击的单元格,那么不执行任何操作,返回
if (hitTest.Type != DataGridViewHitTestType.Cell)
return; // 记下要被拖动数据行的索引
indexOfItemUnderMouseToDrag = hitTest.RowIndex;
//记下以鼠标按下坐标为中心的不会开始拖动的范围。>-1表示点击的行不是标题行才能进行拖动操作
if (indexOfItemUnderMouseToDrag > -1)
{
Size dragSize = SystemInformation.DragSize;
dragBoxFromMouseDown = new Rectangle(new Point(e.X - (dragSize.Width / 2), e.Y - (dragSize.Height / 2)), dragSize);
}
else
dragBoxFromMouseDown = Rectangle.Empty; } //响应鼠标抬起时的事件
private void dataGridView_MouseUp(object sender, MouseEventArgs e)
{
// 释放鼠标按键时清空变量为默认值
dragBoxFromMouseDown = Rectangle.Empty;
} //当鼠标按下状态移动时开始拖放过程
private void dataGridView_MouseMove(object sender, MouseEventArgs e)
{
// 当鼠标按键不是鼠标左键时,不移动数据行
if ((e.Button & MouseButtons.Left) != MouseButtons.Left)
return;
// 如果鼠标在不启用拖动的范围内,不移动数据行
if (dragBoxFromMouseDown == Rectangle.Empty || dragBoxFromMouseDown.Contains(e.X, e.Y))
return;
// 如果源数据行索引值不正确,不移动数据行
if (indexOfItemUnderMouseToDrag < 0)
return; // 开始拖动,第一个参数表示要拖动的数据,可以自定义,一般是源数据行
var row = dataGridView.Rows[indexOfItemUnderMouseToDrag]; /*DragDropEffects枚举:指定拖放操作的效果
* DragDropEffects成员:
* None:放置目标不接受该数据
* Copy:将数据复制到放置目标
* Move:将拖动源的数据移动到放置目标
* Link:将拖动源中的数据链接到放置目标
* Scroll:即将在放置目标中滚动或当前正在滚动
* All:从拖动源复制、移除数据,并将其滚动到放置目标中
*/
DragDropEffects dropEffect = dataGridView.DoDragDrop(row, DragDropEffects.All); //拖动过程结束后清除拖动位置行的红线效果
OnRowDragOver(-1);
} //当鼠标移动过数据行执行重绘
private void dataGridView_DragOver(object sender, DragEventArgs e)
{
// 把屏幕坐标转换成控件坐标:PointToClient方法将指定屏幕点的位置计算成工作区坐标。
Point p = dataGridView.PointToClient(new Point(e.X, e.Y)); // 通过鼠标按下的位置获取所在行的信息
// 如果不是在数据行或者在源数据行上则不能作为拖放的目标
var hitTest = dataGridView.HitTest(p.X, p.Y);
//如果该位置信息对应的成员类型和拖动的成员类型不同或者位置信息和拖动源相同(相当于从哪里拖出来还放到原来的地方)那么不进行操作
if (hitTest.Type != DataGridViewHitTestType.Cell || hitTest.RowIndex == indexOfItemUnderMouseToDrag)
{
//不放置
e.Effect = DragDropEffects.None;
//移除红线
OnRowDragOver(-1);
return;
} // 设置为作为拖放移动的目标
e.Effect = DragDropEffects.Move;
// 通知目标行重绘,在经过的数据行绘制红线
OnRowDragOver(hitTest.RowIndex);
} //当鼠标将数据行拖放至目的行释放时
private void dataGridView_DragDrop(object sender, DragEventArgs e)
{
// 把屏幕坐标转换成控件坐标
Point p = dataGridView.PointToClient(new Point(e.X, e.Y)); // 如果当前位置不是数据行
// 或者刚好是源数据行的下一行(本示例中假定拖放操作为拖放至目标行的上方)
// 则不进行任何操作
var hitTest = dataGridView.HitTest(p.X, p.Y);
if (hitTest.Type != DataGridViewHitTestType.Cell || hitTest.RowIndex == indexOfItemUnderMouseToDrag + 1)
return; //鼠标放下的改行的行号即为拖放目的行
indexOfItemUnderMouseToDrop = hitTest.RowIndex; //数据推断,新建一个DataTable数据行
var tempRow = ds.Tables["playlist"].NewRow();
//该新建的DataTable数据行的数据即为拖动的源。
tempRow.ItemArray = ds.Tables["playlist"].Rows[indexOfItemUnderMouseToDrag].ItemArray;
//因为新建了数据行,所以要移除旧行即拖动源
ds.Tables["playlist"].Rows.RemoveAt(indexOfItemUnderMouseToDrag);
//ds.Tables["playlist"].Rows[indexOfItemUnderMouseToDrag].Delete(); if (indexOfItemUnderMouseToDrag < indexOfItemUnderMouseToDrop)
indexOfItemUnderMouseToDrop--;
//将新建的数据行插入到拖动的目的行
ds.Tables["playlist"].Rows.InsertAt(tempRow, indexOfItemUnderMouseToDrop);
//选中被拖动的行
dataGridView.Rows[indexOfItemUnderMouseToDrop].Selected = true;
//重排行号和更新数据库
for (int i = 0; i < dataGridView.Rows.Count; i++)
{
dataGridView.Rows[i].Cells["orderid"].Value = i + 1;
using (conn)
{
conn.Open();
cmd.CommandText = "update playlist set orderid=" + (i + 1) + " where id=" + dataGridView.Rows[i].Cells["id"].Value;
cmd.Connection = conn;
cmd.ExecuteNonQuery();
conn.Close();
}
}
GC.Collect();
} private void dataGridView_RowPostPaint(object sender, DataGridViewRowPostPaintEventArgs e)
{
// 如果当前行是鼠标拖放过程的所在行
if (e.RowIndex == indexOfItemUnderMouseOver)
e.Graphics.FillRectangle(Brushes.Red, e.RowBounds.X, e.RowBounds.Y, e.RowBounds.Width, 3);
} private void OnRowDragOver(int rowIndex)
{
// 如果和上次导致重绘的行是同一行则无需重绘
if (indexOfItemUnderMouseOver == rowIndex)
return; int old = indexOfItemUnderMouseOver;
indexOfItemUnderMouseOver = rowIndex; // 去掉原有行的红线
if (old > -1)
dataGridView.InvalidateRow(old); // 绘制新行的红线
if (rowIndex > -1)
dataGridView.InvalidateRow(rowIndex);
}
}
}