 |
|
 |
Hi, I love your code and am wanting to use it in an application I am making but I have a question for you. I have tried to wrap my head around your code and how to do this but I can't figure it out. I am wanting to make a version that only lets nodes be in folders and not the root. Also, I want to make it where there can't be a folder inside of a folder. Could you help me out?
Thanks! -Matt
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Thank you for this project. It will save me days of work.
I trapped and fixed the error you mentioned in your History entry for June 2005. The error was "Conversion from string "|" to type double was not valid". This was caused because VB.Net does not automatically convert the tnCurNode.Index, which is an integer, to a string when you try to concatenate the string to add to the stringbuilder named NewNodeMap. Obviously the C# version does the converstion to a string automatically. I used a Try..Catch clause to trap the error.
Adding a .ToString after the integer fixes the problem, as in this: (tnCurNode.Index + 1).ToString
Here is the fixed code, which appears to work fine:
Private Sub SetNewNodeMap(ByVal tnNode As TreeNode, ByVal boolBelowNode As Boolean) ''' ''' If NewNodeMap.Length = 0 AndAlso boolBelowNode = True Then NewNodeMap.Insert(0, (tnCurNode.Index + 1).ToString + "|") Else NewNodeMap.Insert(0, tnCurNode.Index.ToString + "|") End If '''' End Sub
|
| Sign In·View Thread·PermaLink | 5.00/5 (1 vote) |
|
|
|
 |
|
 |
Or, alternatively, you could use the "&" for string concatenation instead of the ambiguous "+". Thus, NewNodeMap.Insert(0, (tnCurNode.Index + 1) + "|") and NewNodeMap.Insert(0, tnCurNode.Index + "|") become NewNodeMap.Insert(0, (tnCurNode.Index + 1) & "|") and NewNodeMap.Insert(0, tnCurNode.Index & "|"), respectively.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hi , Seems fine tree - but I need/want a tree who support drag/drop (like this one) and can be put as an asp.net server/client gui Is it possible to converate this tree or something like this to asp.net?
Thanks Tal
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hi,
Nice code you've made.
I am just making a little application using this, and it works great. I have one little problem however, and wonder if it is possible: From another application, for example Word, I would like to be able to drag one word into the treeview, converting it to a node, and being able to place it like the nodes allready in the tree.
I think it is probably very simple, but as a beginner i C# it is not quite clear for me how to do this.
Sincerely/Best regards Mads Aggerholm Denmark
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
First, thanks for writing this, it saved me tons of time figuring out how to do this myself! It didn't take but a few minutes to copy the event handlers and get it working in my XTree (you should see it in an upcoming article soon!)
I didn't want the code to be dependent on image index numbering, so I removed all the references to ImageIndex. As a result, I removed the "- NodeOverImageWidth" calculation and commented out the code that was assigning ParentDragDrop in the "Allow drag drop to parent branches" region.
This may have had the following side effect, which is that I wanted to be able to treat all nodes as possible "folders", able to accept child nodes.
So, right after the first "if" in treeView1_DragOver, I added another test:
if ( (NodeOver.Nodes.Count > 0) || ( (NodeOver.Index == (NodeOver.Parent.Nodes.Count - 1)) && ( (OffsetY < NodeOver.Bounds.Height / 3) || (OffsetY > 2*NodeOver.Bounds.Height/3) ) ) )
which tests whether you're at the last node AND and the top or bottom third of the node, allowing the drag operation to insert before or after.
Anyways, thanks for your efforts, and the efforts of "creatio"!
Marc
Pensieve Some people believe what the bible says. Literally. At least [with Wikipedia] you have the chance to correct the wiki -- Jörgen Sigvardsson
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Marc,
I've read and appreciate many of your articles on the code project as well. I'm glad to be able to return the favor 
Gabe
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Gabe Anguiano wrote: I've read and appreciate many of your articles on the code project as well.
Thanks! BTW, here's[^] the article I was mentioning, with your code helping out. 
Marc
Pensieve Some people believe what the bible says. Literally. At least [with Wikipedia] you have the chance to correct the wiki -- Jörgen Sigvardsson
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Man... This is the worst code I've ever seen in my life... think about some refactoring.
Thou Shalt Not Repeat Your Code!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Perhaps I should delete this article and go into hiding? I just feel awful that though the article may be of help to many people - it is so painful for your eyes!
Please... If you are going to shoot off some wise-ass comment, do the CodeProject community a favor and post some suggestions or code changes. Childish remarks such as this do no good.
Thou Shalt Not Post Childish Remarks to Free Knowledge!
Gabe
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
I'm sorry for being so straightforward with my criticism, however, I was really, and I mean *really* frustrated by the fact that being a software developer for 15 years now I could not understand whatever is going on inside the code.
Consider it a friendly advice - comments in the code do wonders with other people' understanding, and refactoring it instead of copying and pasting the same code over and over again does wonders with the code quality, speed and size (which also has a direct impact on understanding).
No hard feelings. I demand the same from myself.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
that is too personal. bang ur head into the wall. look at the main topic of this article, he din post a "let refactoring treeview code etc" every article has its objective.
from, -= aLbert =-
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
By only slightly modifying the code I was able to drag nodes between multiple treeviews. This has saved me a LOT of headaches, awesome work!!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
 |
Hi : How can I darg-drop item to a WebBrowser control ? I created an application written by C#,it includes two forms , one form
includes a TreeView control , the other includes a WebBrower control and a
TextBox control, now we call them as Form1 and Form2. First , I try drag a item to the TextBox control,(I have set TreeView for
drag well ) I set "this.textBox1.AllowDrop = true;" then add Events and write these methods: this.textBox1.DragOver += new System.Windows.Forms.DragEventHandler
(this.textBox1_DragOver); this.textBox1.DragDrop += new System.Windows.Forms.DragEventHandler
(this.textBox1_DragDrop); this.textBox1.DragEnter += new System.Windows.Forms.DragEventHandler
(this.textBox1_DragEnter); Run this application,and drag item from TreeView which in Form1 to TextBox
which in Form2,the TextBox 3 Events (DragOver,DragDrop,DragEnter) is done
well. But when I want drag item to the WebBrower,I can not find DragEnter Event and
others Events related to "Drag-Drop",so I can not drop Item to WebBrowser. Also I have tryed set WebBrowser's Document.DesignMode="On",but can not drop
too. Then I Write a HTMLBody's ondragenter Event ,but this ondragenter() can not
trigger. So I think it must be solved by COM knowledge. Can any one give my some suggestion, because my COM knowledge is poor, if anyone give me an all solved code ,I
will be very appreciated.Thanks very 
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hey,
I'm sorry, I have only a little bit of experience with the web browser control and one thing I remember is that it is not fully supported by .NET and buggy.
Sorry I couldn't be more help.
Gabe
|
| Sign In·View Thread·PermaLink | 1.00/5 (1 vote) |
|
|
|
 |
|
|
 |
|
 |
Anything is possible in VC++ however I do not have the time to convert this project over to that language - sorry.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
 |
|
 |
I am trying to do some thing similar to what you have done, i will study you sample a bit, thanks for sharing your code
|
| Sign In·View Thread·PermaLink | 2.00/5 (1 vote) |
|
|
|
 |
|
|
 |
|
 |
Hi.
Good description and nice code made it realy usable and valuable. However, while analyzing your code I spotted several minor bugs.
1. The drag'n'drop is dependant on the image index of the TreeNode thus preventing us from using different images on different levels (or branches)of the tree.
2. You have used the type string for your NewNodeMap variable, which lead to the frequent memory reallocations, while filling this map. This lead to the unpleasant delays.
3. Many peaces of the code are duplicated about four times (!).
Of course it wouldn't be a comprehansive message if only I wouldn't added my own version of this bugs fixes. I didn't tested it much, but I fixed bugs 2 and 3 and felt myself a bit lazy for the first one 
May be my code will inspire you to fix even the first mentioned bug. 
private const int MAPSIZE = 128; private StringBuilder NewNodeMap = new StringBuilder(MAPSIZE);
private void treeView1_DragOver(object sender, System.Windows.Forms.DragEventArgs e) { TreeNode NodeOver = this.treeView1.GetNodeAt(this.treeView1.PointToClient(Cursor.Position)); TreeNode NodeMoving = (TreeNode)e.Data.GetData("System.Windows.Forms.TreeNode");
// A bit long, but to summarize, process the following coe only if the nodeover is null // and either the nodeover is not the same thing as nodemoving UNLESSS nodeover happens // to be the last node in the branch (so we can allow drag & drop below a parent branch) if(NodeOver != null && (NodeOver != NodeMoving || (NodeOver.Parent != null && NodeOver.Index == (NodeOver.Parent.Nodes.Count - 1)))) { int OffsetY = this.treeView1.PointToClient(Cursor.Position).Y - NodeOver.Bounds.Top;
////////////////////////////////////////////////////////////////////////// //BAD!!!! Can't use images other then with ImageIndex == 1 for the folders ////////////////////////////////////////////////////////////////////////// // Image index of 1 is the non-folder icon if(NodeOver.ImageIndex == 1) { #region Standard Node if(OffsetY < (NodeOver.Bounds.Height / 2)) { //this.lblDebug.Text = "top"; #region If NodeOver is a child then cancel TreeNode tnParadox = NodeOver; while(tnParadox.Parent != null) { if(tnParadox.Parent == NodeMoving) { this.NodeMap = ""; return; }
tnParadox = tnParadox.Parent; } #endregion #region Store the placeholder info into a pipe delimited string SetNewNodeMap(NodeOver); if(SetMapsEqual() == true) return;
#endregion #region Clear placeholders above and below this.Refresh(); #endregion #region Draw the placeholders DrawLeafTopPlaceholders(NodeOver); #endregion } else { //this.lblDebug.Text = "bottom"; #region If NodeOver is a child then cancel TreeNode tnParadox = NodeOver; while(tnParadox.Parent != null) { if(tnParadox.Parent == NodeMoving) { this.NodeMap = ""; return; }
tnParadox = tnParadox.Parent; } #endregion #region Allow drag drop to parent branches TreeNode ParentDragDrop = null; // If the node the mouse is over is the last node of the branch we should allow // the ability to drop the "nodemoving" node BELOW the parent node if(NodeOver.Parent != null && NodeOver.Index == (NodeOver.Parent.Nodes.Count - 1)) { int XPos = this.treeView1.PointToClient(Cursor.Position).X; if(XPos < NodeOver.Bounds.Left) { ParentDragDrop = NodeOver.Parent; while(true) { if(XPos > (ParentDragDrop.Bounds.Left - this.treeView1.ImageList.Images[ ParentDragDrop.ImageIndex].Size.Width)) break;
if(ParentDragDrop.Parent != null) ParentDragDrop = ParentDragDrop.Parent; else break; } } } #endregion #region Store the placeholder info into a pipe delimited string // Since we are in a special case here, use the ParentDragDrop node as the current "nodeover" TreeNode tnPlaceholderInfo = ParentDragDrop != null ? ParentDragDrop : NodeOver;
SetNewNodeMap(tnPlaceholderInfo); if(SetMapsEqual() == true) return; #endregion #region Clear placeholders above and below this.Refresh(); #endregion #region Draw the placeholders DrawLeafBottomPlaceholders(NodeOver, ParentDragDrop); #endregion } #endregion } else { #region Folder Node if(OffsetY < (NodeOver.Bounds.Height / 3)) { //this.lblDebug.Text = "folder top";
#region If NodeOver is a child then cancel TreeNode tnParadox = NodeOver; while(tnParadox.Parent != null) { if(tnParadox.Parent == NodeMoving) { this.NodeMap = ""; return; }
tnParadox = tnParadox.Parent; } #endregion #region Store the placeholder info into a pipe delimited string SetNewNodeMap(NodeOver); if(SetMapsEqual() == true) return; #endregion #region Clear placeholders above and below this.Refresh(); #endregion #region Draw the placeholders #endregion } else if((NodeOver.Parent != null && NodeOver.Index == 0) && (OffsetY > (NodeOver.Bounds.Height - (NodeOver.Bounds.Height / 3)))) { //this.lblDebug.Text = "folder bottom"; #region If NodeOver is a child then cancel TreeNode tnParadox = NodeOver; while(tnParadox.Parent != null) { if(tnParadox.Parent == NodeMoving) { this.NodeMap = ""; return; }
tnParadox = tnParadox.Parent; } #endregion #region Store the placeholder info into a pipe delimited string SetNewNodeMap(NodeOver); if(SetMapsEqual() == true) return; #endregion #region Clear placeholders above and below this.Refresh(); #endregion #region Draw the placeholders DrawFolderTopPlaceholders(NodeOver); #endregion } else { //this.lblDebug.Text = "folder over"; if(NodeOver.Nodes.Count > 0) { NodeOver.Expand(); //this.Refresh(); } else { #region Prevent the node from being dragged onto itself if(NodeMoving == NodeOver) return; #endregion #region If NodeOver is a child then cancel TreeNode tnParadox = NodeOver; while(tnParadox.Parent != null) { if(tnParadox.Parent == NodeMoving) { this.NodeMap = ""; return; }
tnParadox = tnParadox.Parent; } #endregion #region Store the placeholder info into a pipe delimited string SetNewNodeMap(NodeOver); NewNodeMap = NewNodeMap.Insert(NewNodeMap.Length, "|0");
if(SetMapsEqual() == true) return; #endregion #region Clear placeholders above and below this.Refresh(); #endregion #region Draw the "add to folder" placeholder DrawAddToFolderPlaceholder(NodeOver); #endregion } } #endregion } } }//eom
private void DrawLeafTopPlaceholders(TreeNode NodeOver) { Graphics g = this.treeView1.CreateGraphics();
int NodeOverImageWidth = this.treeView1.ImageList.Images[NodeOver.ImageIndex].Size.Width + 8; int LeftPos = NodeOver.Bounds.Left - NodeOverImageWidth; int RightPos = this.treeView1.Width - 4;
Point[] LeftTriangle = new Point[5]{ new Point(LeftPos, NodeOver.Bounds.Top - 4), new Point(LeftPos, NodeOver.Bounds.Top + 4), new Point(LeftPos + 4, NodeOver.Bounds.Y), new Point(LeftPos + 4, NodeOver.Bounds.Top - 1), new Point(LeftPos, NodeOver.Bounds.Top - 5)};
Point[] RightTriangle = new Point[5]{ new Point(RightPos, NodeOver.Bounds.Top - 4), new Point(RightPos, NodeOver.Bounds.Top + 4), new Point(RightPos - 4, NodeOver.Bounds.Y), new Point(RightPos - 4, NodeOver.Bounds.Top - 1), new Point(RightPos, NodeOver.Bounds.Top - 5)};
g.FillPolygon(System.Drawing.Brushes.Black, LeftTriangle); g.FillPolygon(System.Drawing.Brushes.Black, RightTriangle); g.DrawLine(new System.Drawing.Pen(Color.Black, 2), new Point(LeftPos, NodeOver.Bounds.Top), new Point(RightPos, NodeOver.Bounds.Top));
}//eom
private void DrawLeafBottomPlaceholders(TreeNode NodeOver, TreeNode ParentDragDrop) { Graphics g = this.treeView1.CreateGraphics();
int NodeOverImageWidth = this.treeView1.ImageList.Images[NodeOver.ImageIndex].Size.Width + 8; // Once again, we are not dragging to node over, draw the placeholder using the ParentDragDrop bounds int LeftPos, RightPos; if(ParentDragDrop != null) LeftPos = ParentDragDrop.Bounds.Left - (this.treeView1.ImageList.Images[ParentDragDrop.ImageIndex].Size.Width + 8); else LeftPos = NodeOver.Bounds.Left - NodeOverImageWidth; RightPos = this.treeView1.Width - 4;
Point[] LeftTriangle = new Point[5]{ new Point(LeftPos, NodeOver.Bounds.Bottom - 4), new Point(LeftPos, NodeOver.Bounds.Bottom + 4), new Point(LeftPos + 4, NodeOver.Bounds.Bottom), new Point(LeftPos + 4, NodeOver.Bounds.Bottom - 1), new Point(LeftPos, NodeOver.Bounds.Bottom - 5)};
Point[] RightTriangle = new Point[5]{ new Point(RightPos, NodeOver.Bounds.Bottom - 4), new Point(RightPos, NodeOver.Bounds.Bottom + 4), new Point(RightPos - 4, NodeOver.Bounds.Bottom), new Point(RightPos - 4, NodeOver.Bounds.Bottom - 1), new Point(RightPos, NodeOver.Bounds.Bottom - 5)};
g.FillPolygon(System.Drawing.Brushes.Black, LeftTriangle); g.FillPolygon(System.Drawing.Brushes.Black, RightTriangle); g.DrawLine(new System.Drawing.Pen(Color.Black, 2), new Point(LeftPos, NodeOver.Bounds.Bottom), new Point(RightPos, NodeOver.Bounds.Bottom)); }//eom
private void DrawFolderTopPlaceholders(TreeNode NodeOver) { Graphics g = this.treeView1.CreateGraphics(); int NodeOverImageWidth = this.treeView1.ImageList.Images[NodeOver.ImageIndex].Size.Width + 8;
int LeftPos, RightPos; LeftPos = NodeOver.Bounds.Left - NodeOverImageWidth; RightPos = this.treeView1.Width - 4;
Point[] LeftTriangle = new Point[5]{ new Point(LeftPos, NodeOver.Bounds.Top - 4), new Point(LeftPos, NodeOver.Bounds.Top + 4), new Point(LeftPos + 4, NodeOver.Bounds.Y), new Point(LeftPos + 4, NodeOver.Bounds.Top - 1), new Point(LeftPos, NodeOver.Bounds.Top - 5)};
Point[] RightTriangle = new Point[5]{ new Point(RightPos, NodeOver.Bounds.Top - 4), new Point(RightPos, NodeOver.Bounds.Top + 4), new Point(RightPos - 4, NodeOver.Bounds.Y), new Point(RightPos - 4, NodeOver.Bounds.Top - 1), new Point(RightPos, NodeOver.Bounds.Top - 5)};
g.FillPolygon(System.Drawing.Brushes.Black, LeftTriangle); g.FillPolygon(System.Drawing.Brushes.Black, RightTriangle); g.DrawLine(new System.Drawing.Pen(Color.Black, 2), new Point(LeftPos, NodeOver.Bounds.Top), new Point(RightPos, NodeOver.Bounds.Top));
}//eom private void DrawAddToFolderPlaceholder(TreeNode NodeOver) { Graphics g = this.treeView1.CreateGraphics(); int RightPos = NodeOver.Bounds.Right + 6; Point[] RightTriangle = new Point[5]{ new Point(RightPos, NodeOver.Bounds.Y + (NodeOver.Bounds.Height / 2) + 4), new Point(RightPos, NodeOver.Bounds.Y + (NodeOver.Bounds.Height / 2) + 4), new Point(RightPos - 4, NodeOver.Bounds.Y + (NodeOver.Bounds.Height / 2)), new Point(RightPos - 4, NodeOver.Bounds.Y + (NodeOver.Bounds.Height / 2) - 1), new Point(RightPos, NodeOver.Bounds.Y + (NodeOver.Bounds.Height / 2) - 5)};
this.Refresh(); g.FillPolygon(System.Drawing.Brushes.Black, RightTriangle); }//eom
private void SetNewNodeMap(TreeNode tnNode) { NewNodeMap.Length = 0; NewNodeMap.Insert(0, (int)tnNode.Index);
TreeNode tnCurNode = tnNode;
while(tnCurNode.Parent != null) { tnCurNode = tnCurNode.Parent; NewNodeMap.Insert(0, tnCurNode.Index + "|"); } }//oem
private bool SetMapsEqual() { if(this.NewNodeMap.ToString() == this.NodeMap) return true; else { this.NodeMap = this.NewNodeMap.ToString(); return false; } }//oem
By the way, thanks for a good job!
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
creatio, thanks for your input and your valuable recommended code. I'll make some time to go over it this weekend and implement a new version. I've always known that code reuse was minimal with this project - I didn't have time to fully perfect it.
Thanks for your help!
Gabe
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
You wellcome Gabe!
One more very small issue. 
It's not safe to rely on ImageIndex property blindly. As if someone would decide to use DefaultImageIndex and not to assign ImageIndex. The last mentioned will have a value of -1. And your code that uses ImageIndex as an indexer parameter will gladly throw an exception.
int NodeOverImageWidth = ImageList.Images[NodeOver.ImageIndex].Size.Width + 8; //exception here
A simple check will be enough to overcome this trouble.
int NodeOverImageWidth = (NodeOver.ImageIndex == -1 ? ImageList.Images[NodeOver.ImageIndex].Size.Width : ImageList.Images[this.DefaultImageIndex].Size.Width) + 8;
The same problem is in the following code:
// Image index of 1 is the non-folder icon if(NodeOver.ImageIndex == 1)
However I wouldn't use here the same solution. As any node (theoretically) may become a container, it would be more flexible not to cut the ability to drug items into non folder items. So a timer may be handful in this situation. The algorithm is: When draged for a specified amount of time - we are getting an "add to folder" state. If moved - resetting timer, and once again we are in the default positionning state.
This behaviour is like in Explorer (R) tree: dragging over the "+" icon for a second, expands a tree branch.
P.S. My code is a bit different, because I moved all the needed code into the TreeView derived class and compiling it as a custom control DLL.
Best Regards, Alex.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|