TreeView的撤销操作问题?
在进行TreeView节点移动的时候,如果用户不小心移动错误,那么该如何设置一个
按钮来允许用户进行撤销操作啊。怎么才能实现撤销啊?真是麻烦啊!谢谢大侠啦!
^-^ --------------------编程问答-------------------- 沙发,帮忙顶 --------------------编程问答-------------------- MIDAS --------------------编程问答-------------------- 设置一个类用来保存要移动的节点的位置以及数据,撤消时再添加回去。 --------------------编程问答-------------------- 节点还要绑定数据,数据也要变回原来的 --------------------编程问答-------------------- 哪位大好人帮忙给写一下啊? --------------------编程问答-------------------- 不会,帮顶! --------------------编程问答-------------------- mark 帮顶 --------------------编程问答-------------------- treeview类没有你要的现成的功能函数,需要你自己写一个这样的函数。每一步操作都保存记录(可以是多个便于恢复多步),一旦需要就调用这个函数,每操作一步,更新保存的信息。这样就行了,以前做个!
--------------------编程问答-------------------- gisfarmer(菜菜阿杰) 以前做过能不能给个例子啊?我的邮箱shidongye123456@163.com --------------------编程问答-------------------- 不好意思!找了半天,也没有找到。不难,以前我是用VC写的。
--------------------编程问答-------------------- 哦,不过我自己写可真的是费劲啊。真是郁闷!唉,不过谢谢你啦^-^ --------------------编程问答-------------------- 帮顶 --------------------编程问答-------------------- 等我写完就散分,放心吧,不会很久地!也就十天半月的吧!^-^ --------------------编程问答-------------------- 我会耐心的等
zhaowen6666678() ( ) 信誉:100 2007-08-20 15:08:26 得分: 0
等我写完就散分,放心吧,不会很久地!也就十天半月的吧!^-^
--------------------编程问答-------------------- 呵呵....马上快有结果啦!嘿嘿.... --------------------编程问答-------------------- 不知道还有没有人关注
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Collections;
namespace UndoTreeView
{
public partial class Form1 : Form
{
int CtrlMask = 8;
ArrayList nDestNote = new ArrayList();
ArrayList nSource = new ArrayList();
public Form1()
{
InitializeComponent();
}
private void button3_Click(object sender, EventArgs e)
{
Undo();
}
private void treeView_ItemDrag(object sender, ItemDragEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
//DoDragDrop 方法确定当前光标位置下的控件。然后它将检查该控件是否是有效的放置目标。
DoDragDrop(e.Item, DragDropEffects.Move | DragDropEffects.Copy);
}
}
private void treeView_DragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent("System.Windows.Forms.TreeNode"))
{
if ((e.KeyState & CtrlMask) == CtrlMask)
{
e.Effect = DragDropEffects.Copy;
}
else
{
//MessageBox.Show("该节点将被删除!");
e.Effect = DragDropEffects.Move;
}
}
else
{
e.Effect = DragDropEffects.None;
}
}
private void treeView_DragDrop(object sender, DragEventArgs e)
{
TreeNode OriginationNode = (TreeNode)e.Data.GetData("System.Windows.Forms.TreeNode"); //(TreeNode)OriginationNode.Clone()
if (e.Data.GetDataPresent("System.Windows.Forms.TreeNode", false))
{
Point pt = ((TreeView)sender).PointToClient(new Point(e.X, e.Y));
TreeNode DestinationNode = ((TreeView)sender).GetNodeAt(pt);
if (((TreeNode)OriginationNode).Index - 1 >= 0)
{
nSource.Add(((TreeNode)OriginationNode).Parent.Nodes[((TreeNode)OriginationNode).Index - 1]);
}
else
{
MessageBox.Show("你移动的是Index为0的节点!");
}
if (IfMove(DestinationNode, (TreeNode)OriginationNode))
{
if (DestinationNode.Parent == ((TreeNode)OriginationNode).Parent) //DestinationNode.Name.Length == ((TreeNode)OriginationNode).Name.Length && (TreeNode)OriginationNode.Parent!=null
{
DestinationNode.Parent.Nodes.Insert(DestinationNode.Index + 1, (TreeNode)OriginationNode.Clone());
//DestinationNode.Expand();
if ((e.KeyState & CtrlMask) != CtrlMask)
{
OriginationNode.Remove();
}
nDestNote.Add(DestinationNode.Parent.Nodes[DestinationNode.Index+1]);
}
else
{
DestinationNode.Parent.Nodes.Insert(DestinationNode.Index + 1, (TreeNode)OriginationNode.Clone());
//DestinationNode.Expand();
if ((e.KeyState & CtrlMask) != CtrlMask)
{
OriginationNode.Remove();
}
nDestNote.Add(DestinationNode.Parent.Nodes[DestinationNode.Index + 1]);
//MessageBox.Show("不是平级移动!");
}
}
}
i = nDestNote.Count;
}
//判断nDest是否在nSource内部,是则不允许移动
private bool IfMove(TreeNode nDest, TreeNode nSource)
{
if (nDest.Parent != nSource && nDest.Parent != null)
{
IfMove(nDest.Parent, nSource); //一直比到nDest.Parent = null为止
}
else if (nDest.Parent == null)
{
return true;
}
else if (nDest.Parent == nSource)
{
return false;
}
return IfMove(nDest.Parent, nSource);
}
//创建撤销函数
private int i;
private void Undo()
{
i = i - 1;
if (i > -1)
{
TreeNode AlreadyInsertName = new TreeNode();
TreeNode SourceUpOneNode = new TreeNode();
AlreadyInsertName = ((TreeNode)nDestNote[i]);
SourceUpOneNode = ((TreeNode)nSource[i]);
//记住变化后的节点Name,将变化后的重新移动到原来的位置(记住原来的Name上一个节点的Name位置(SourceUpOneNode)和插入后节点的name位置(AlreadyInsertName))
//将AleadyInsertNode出入到SourceUpOneNode下面,将原来的删除
AlreadyInsertName.Remove();
SourceUpOneNode.Parent.Nodes.Insert(SourceUpOneNode.Index + 1, AlreadyInsertName);
nDestNote.Remove((TreeNode)nDestNote[i]);
nSource.Remove((TreeNode)nSource[i]);
}
else
{
MessageBox.Show("已经撤消到了最后一步!");
}
}
}
} --------------------编程问答-------------------- 这是我写的撤销程序,不过只有撤销的第一步是完全正确的,撤销多步都有Bug请高手帮忙指点!我真的有点急啊! --------------------编程问答-------------------- 我自己做了一个,完全没问题 --------------------编程问答-------------------- 那应该还可以恢复误删的节点还要保存删除节点子树,还要恢复误改的文字。。。
简单的做法是保存一份整个树的克隆
TreeView TV = new TreeView();
foreach (TreeNode Node in treeView1.Nodes)
TV.Nodes.Add((TreeNode)Node.Clone());
要撤销,反过来
treeView1.Nodes.Clear();
foreach (TreeNode Node in TV.Nodes)
treeView1.Nodes.Add((TreeNode)Node.Clone());
TV.Dispose();
--------------------编程问答-------------------- 设计模式 command模式 --------------------编程问答-------------------- public partial class Form1 : Form
{
public enum ChangeType
{
Add,
Delete,
Edit,
Move,
None
}
public class TreeNodeRecoding
{
public TreeNodeRecoding()
{
node = null;
Parent = null;
Index = -1;
changeType = ChangeType.None;
}
public TreeNode node;
public ChangeType changeType;
public object Parent;
public int Index;
}
public Form1()
{
InitializeComponent();
}
List<TreeNodeRecoding> tnrList = new List<TreeNodeRecoding>();
TreeNode DraggingNode;
TreeNode dragDestNode;
private void treeView1_NodeMouseHover(object sender, TreeNodeMouseHoverEventArgs e)
{
if(DraggingNode !=null)
dragDestNode = e.Node;
}
private void treeView1_ItemDrag(object sender, ItemDragEventArgs e)
{
DraggingNode = e.Item as TreeNode;
}
private void treeView1_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
{
this.treeView1.SelectedNode = e.Node;
}
/// <summary>
/// 移动节点
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void treeView1_MouseUp(object sender, MouseEventArgs e)
{
if (DraggingNode != null)
{
bool ex = false;
if (dragDestNode.Parent == null)
{
if (dragDestNode.Equals(DraggingNode))
ex = true;
}
else
{
TreeNode temp = dragDestNode;
while (temp.Parent != null)//如果父节点不为空,往上一级查找以确定是否是子节点
{
temp = temp.Parent;
if (temp.Equals(DraggingNode))
{
ex = true;
break;
}
}
}
if (!ex)
{
treeView1.Nodes.Remove(DraggingNode);
Record(DraggingNode, ChangeType.Delete, DraggingNode.Parent == null ?(object) treeView1 :(object) DraggingNode.Parent, DraggingNode.Index);
try
{
int idx = dragDestNode.Index;
//int idx = dragDestNode.Parent.Nodes.IndexOf(dragDestNode);
dragDestNode.Parent.Nodes.Insert(idx, DraggingNode);
Record(null, ChangeType.Move, dragDestNode.Parent, idx);
}
catch
{
try
{
int idx = dragDestNode.Index;
//int idx = treeView1.Nodes.IndexOf(dragDestNode);
treeView1.Nodes.Insert(idx, DraggingNode);
Record(null, ChangeType.Move, treeView1, idx);
}
catch
{
UnDoTreeView();
}
}
}
}
DraggingNode = null;
}
void Record(TreeNode tn,ChangeType ct,object parent,int idx )
{
if (tnrList.Count == 40)
{
if (tnrList[0].changeType == ChangeType.Delete)//如果是删除操作
{
tnrList.Remove(tnrList[0]);
if (tnrList[0].changeType == ChangeType.Move)//检查前面一个是否是移动操作,如果是则一起删除
{
tnrList.Remove(tnrList[0]);
}
}
else
tnrList.Remove(tnrList[0]);
}
TreeNodeRecoding tnr = new TreeNodeRecoding();
tnr.node = tn;
tnr.changeType = ct;
tnr.Parent = parent;
tnr.Index = idx;
tnrList.Add(tnr);
}
--------------------编程问答-------------------- void UnDoTreeView()
{
if (tnrList.Count == 0)
MessageBox.Show("已经到了最后一步了");
else
{
TreeNodeRecoding tnr = tnrList[tnrList.Count - 1];
switch (tnr.changeType)
{
case ChangeType.Move:
if (tnr.Parent is TreeView)
{
treeView1.Nodes.RemoveAt(tnr.Index);
//treeView1.Nodes.Remove(treeView1.Nodes[tnr.Index]);
}
else if (tnr.Parent is TreeNode)
{
(tnr.Parent as TreeNode).Nodes.RemoveAt(tnr.Index);
//(tnr.Parent as TreeNode).Nodes.Remove((tnr.Parent as TreeNode).Nodes[tnr.Index]);
}
tnrList.Remove(tnr);
UnDoTreeView();
break;
case ChangeType.Add :
if (tnr.Parent is TreeView)
{
treeView1.Nodes.Remove(treeView1.Nodes[tnr.Index]);
}
else if (tnr.Parent is TreeNode)
{
(tnr.Parent as TreeNode).Nodes.Remove((tnr.Parent as TreeNode).Nodes[tnr.Index]);
}
break;
case ChangeType.Delete:
if (tnr.Parent is TreeView)
{
treeView1.Nodes.Insert(tnr.Index,tnr.node);
}
else if (tnr.Parent is TreeNode)
{
(tnr.Parent as TreeNode).Nodes.Insert(tnr.Index,tnr.node);
}
break;
case ChangeType.Edit:
if (tnr.Parent is TreeView)
{
treeView1.Nodes[tnr.Index] = tnr.node;
}
else if (tnr.Parent is TreeNode)
{
(tnr.Parent as TreeNode).Nodes[tnr.Index] = tnr.node;
}
break;
default:
break;
}
tnrList.Remove(tnr);
}
//if(tnrList.Count ==0 )
// MessageBox.Show("已经到了最后一步了");
//else
//{
// //TreeNodeRecoding tnr = tnrList[tnrList.Count - 1];
// //if (tnr.curIndex != -1)//如果有新位置不为空,为添加操作
// //{
// // if (tnr.oldIndex != -1)//如果旧位置不为空,为移动操作或编辑操作
// // {
// // if (tnr.oldIndex != tnr.curIndex) //如果新旧不相等,说明为移动操作
// // {
// // if (tnr.curParent is TreeView)
// // {
// // (tnr.curParent as TreeView).Nodes.Remove((tnr.curParent as TreeView).Nodes[tnr.curIndex]);
// // }
// // else if(tnr.curParent is TreeNode)
// // {
// // (tnr.curParent as TreeNode).Nodes.Remove((tnr.curParent as TreeNode).Nodes[tnr.curIndex]);
// // }
// // if (tnr.oldParent is TreeView)
// // {
// // (tnr.oldParent as TreeView).Nodes.Insert(tnr.oldIndex , tnr.node);
// // }
// // else if(tnr.oldParent is TreeNode)
// // {
// // (tnr.oldParent as TreeNode).Nodes.Insert(tnr.oldIndex, tnr.node);
// // }
// // tnrList.Remove(tnr);
// // }
// // else//编辑操作
// // {
// // }
// // }
// // else//如果旧位置为空,为单纯的添加操作
// // {
// // }
// //}
// //else//如果新位置为空,为删除操作
// //{
// //}
//}
}
private void 添加子级ToolStripMenuItem_Click(object sender, EventArgs e)
{
try
{
treeView1.SelectedNode.Nodes.Add("新建节点");
Record(null, ChangeType.Add, treeView1.SelectedNode, treeView1.SelectedNode.Nodes.Count - 1);
}
catch
{
MessageBox.Show("请先选择要删除的节点");
}
}
private void 删除记录ToolStripMenuItem_Click(object sender, EventArgs e)
{
try
{
TreeNode tn = treeView1.SelectedNode;
int idx = tn.Index;
object p = tn.Parent ==null?(object)treeView1:(object)tn.Parent;
treeView1.Nodes.Remove(treeView1.SelectedNode);
Record(tn, ChangeType.Delete, p, idx);
}
catch
{
MessageBox.Show("请先选择要删除的节点");
}
}
private void 插入记录ToolStripMenuItem_Click(object sender, EventArgs e)
{
try
{
TreeNode newTn = new TreeNode();
TreeNode tn = treeView1.SelectedNode;
int idx = tn.Index;
object p = tn.Parent == null ? (object)treeView1 : (object)tn.Parent;
if (p is TreeView)
{
treeView1.Nodes.Insert(idx, "新建节点");
newTn = treeView1.Nodes[idx];
}
else if (p is TreeNode)
{
(p as TreeNode).Nodes.Insert(idx, "新建节点");
newTn =(p as TreeNode).Nodes[idx];
}
Record(newTn, ChangeType.Add, p, idx);
}
catch
{
MessageBox.Show("请先选择要删除的节点");
}
}
private void 编辑节点ToolStripMenuItem_Click(object sender, EventArgs e)
{
try
{
}
catch
{
MessageBox.Show("请先选择要删除的节点");
}
}
private void 撤销操作ToolStripMenuItem_Click(object sender, EventArgs e)
{
UnDoTreeView();
}
private void treeView1_Click(object sender, EventArgs e)
{
}
private void Form1_Load(object sender, EventArgs e)
{
}
} --------------------编程问答-------------------- 还不错撒,注意的是如果是移动操作的话要继续撤销,就差一个编辑操作了,很容易啦,提交之前保存内容,提交之后在记录中加入之前的保存就好了,
补充:.NET技术 , C#