Author Topic: selecting numerous files in different locations  (Read 2119 times)

0 Members and 1 Guest are viewing this topic.

WOWENS

  • Newt
  • Posts: 59
selecting numerous files in different locations
« on: November 06, 2012, 10:02:31 AM »
maybe someone could help me.
I have some code that i use to select files, the problem i'm having is when i pick a new drive some time it take way to long to fill the folder tree.
any help would be great. autocad 2012 vb express 10.....C:\Working-Folder\testing\FileSelect-plug-in\FileSelect-plug-in\bin\Debug\FileSelect-plug-in.dll
the commmand is test.

Thanks

kaefer

  • Guest
Re: selecting numerous files in different locations
« Reply #1 on: November 06, 2012, 11:39:28 AM »
I have some code that i use to select files, the problem i'm having is when i pick a new drive some time it take way to long to fill the folder tree.

Not that I can be bothered to wade through oodles of VB, but, by any chance, does your problem have anything to do with populating a TreeView eagerly? If so, see e.g. this historical contribution of our esteemed Mr T.

WOWENS

  • Newt
  • Posts: 59
Re: selecting numerous files in different locations
« Reply #2 on: November 06, 2012, 11:57:50 AM »
thanks for the information, i will be sure to look at this.

Jeff H

  • Needs a day job
  • Posts: 6150
Re: selecting numerous files in different locations
« Reply #3 on: November 06, 2012, 12:49:31 PM »
Here is one with a example adapted for block references to show a way of doing it for files.
Basiclly for example with the root drive it checks if a folder has an item and if so adds a "dummy or filler" then in BeforeExpand event  removes the "filler" and does the same for that level.
 
So basiclly search the root drive folder add all files and if it is a folder check if it is not empty and if not just add a "placeholder" to create a "+" sign.
 
When the "+" is clicked it fires the BeforeExpand event and do the same thing.
 
So if you have 100,000,000,000 files and 97,000,000,000 are in the root drive folder will not help much but in most cases people do not put thousands of files in one folder so does not seem lag to bad for them.
 
 
http://forums.autodesk.com/t5/NET/Listing-all-block-s-in-drawing-file/m-p/3078424#M24184
 
 
« Last Edit: November 06, 2012, 12:54:30 PM by Jeff H »

Jeff H

  • Needs a day job
  • Posts: 6150
Re: selecting numerous files in different locations
« Reply #4 on: November 06, 2012, 12:59:37 PM »
Found a old Appdev VB example for ya
Code - Visual Basic: [Select]
  1.  
  2.  Imports System.IO
  3. Imports System.Collections.Generic
  4. Public Class TreeViewListViewDemo
  5. #Region " TreeView Code "
  6.   Private Function FixPath(ByVal path As String) As String
  7.     If path.EndsWith("\") Then
  8.       Return path
  9.     Else
  10.       Return path & "\"
  11.     End If
  12.   End Function
  13.   Private Sub FillDrives()
  14.     For Each drive As DriveInfo In DriveInfo.GetDrives()
  15.       Dim key As String = "Drive"
  16.       Dim name As String = drive.Name
  17.       ' For drive names, remove the trailing "\":
  18.      If name.EndsWith("\") Then
  19.         name = name.Substring(0, name.Length - 1)
  20.       End If
  21.       key = GetImageKey(drive)
  22.       Dim node As TreeNode = _
  23.          FoldersTreeView.Nodes.Add(name, name, key, key)
  24.       ' Add a node so you see a +.
  25.      node.Nodes.Add("FILLER")
  26.     Next
  27.   End Sub
  28.   Private Function GetImageKey( _
  29.    ByVal drive As DriveInfo) As String
  30.     Dim key As String
  31.     Select Case drive.DriveType
  32.       Case DriveType.CDRom
  33.         key = "CDDrive"
  34.       Case DriveType.Fixed
  35.         key = "Drive"
  36.       Case DriveType.Network
  37.         key = "NetworkDrive"
  38.       Case DriveType.Removable
  39.         key = "Floppy"
  40.       Case Else
  41.         key = "Drive"
  42.     End Select
  43.     Return key
  44.   End Function
  45.   Private Sub FilesTreeView_BeforeExpand( _
  46.    ByVal sender As Object, _
  47.    ByVal e As TreeViewCancelEventArgs) _
  48.    Handles FoldersTreeView.BeforeExpand
  49.     Try
  50.       Dim currentNode As TreeNode = e.Node
  51.       ' Remove the filler node, if it's there:
  52.      currentNode.Nodes.Clear()
  53.       ' Now go get all the folders.
  54.      Dim fullPathString As String = _
  55.        FixPath(currentNode.FullPath)
  56.       For Each folderString As String In _
  57.        Directory.GetDirectories(fullPathString)
  58.         ' Handle each folder:
  59.        Dim fileName As String = Path.GetFileName(folderString)
  60.         Dim newNode As TreeNode = _
  61.          currentNode.Nodes.Add(fileName, fileName, _
  62.          "ClosedFolder", "OpenFolder")
  63.         ' Add the filler node:
  64.        newNode.Nodes.Add("FILLER")
  65.         newNode.ToolTipText = newNode.FullPath
  66.       Next
  67.     Catch ex As Exception
  68.       MessageBox.Show(ex.Message, _
  69.        "Error Displaying Information")
  70.     End Try
  71.   End Sub
  72.   Private Sub FilesTreeView_AfterSelect( _
  73.     ByVal sender As System.Object, _
  74.     ByVal e As TreeViewEventArgs) _
  75.     Handles FoldersTreeView.AfterSelect
  76.     FillFiles(e.Node)
  77.   End Sub
  78. #End Region
  79. #Region " ListView Code "
  80.   ' Store the current grouping column:
  81.  Private selectedColumn As Integer = 0
  82.   ' Show groups?
  83.  Private showGroups As Boolean = False
  84.   ' Keep track of the sort order:
  85.  Private order As SortOrder = SortOrder.None
  86.   Private Function AddIconToImageList(ByVal fileName As String) As String
  87.     ' If the icon for the file isn't already stored
  88.    ' within the image list, add it now.
  89.    Dim ext As String = Path.GetExtension(fileName)
  90.     If String.IsNullOrEmpty(ext) Then
  91.       ext = "Empty"
  92.     End If
  93.     If Not images.Images.ContainsKey(ext) Then
  94.       ' Get the icon from the Windows association,
  95.      ' and add it to the ImageList:
  96.      Dim ico As Icon = _
  97.        Drawing.Icon.ExtractAssociatedIcon(fileName)
  98.       images.Images.Add(ext, ico)
  99.       largeImages.Images.Add(ext, ico)
  100.     End If
  101.     Return ext
  102.   End Function
  103.   Private Sub FillFiles(ByVal node As TreeNode)
  104.     FileListView.Items.Clear()
  105.     Try
  106.       ' Handle each file.
  107.      For Each fileString As String In _
  108.        Directory.GetFiles(FixPath(node.FullPath))
  109.         Dim fi As New FileInfo(fileString)
  110.         Dim ext As String = AddIconToImageList(fileString)
  111.         Dim lvi As New ListViewItem(fi.Name, ext)
  112.         lvi.SubItems.Add(fi.Length.ToString("N0"))
  113.         lvi.SubItems.Add( _
  114.          fi.LastWriteTime.ToShortDateString())
  115.         ' Add the new item to the ListView control:
  116.        FileListView.Items.Add(lvi)
  117.       Next
  118.       ' Note that you cannot show groups unless
  119.      ' the operating system is Windows XP or later.
  120.      ' See the Environment.OSVersion property for info
  121.      ' on detecting the version:
  122.      If showGroups Then
  123.         ' Although it's possible to group on columns
  124.        ' other than the first, this demo doesn't.
  125.        SetGroups(0)
  126.       End If
  127.     Catch ex As Exception
  128.       ' If the code fails, just fail silently.
  129.    End Try
  130.   End Sub
  131.   Private Sub FileListView_DoubleClick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles FileListView.DoubleClick
  132.     ' If you double-click on a file, this code
  133.    ' attempts to run the associated application:
  134.    Try
  135.       Process.Start(FixPath(FoldersTreeView.SelectedNode.FullPath) & _
  136.        FileListView.FocusedItem.Text)
  137.     Catch ex As Exception
  138.       MessageBox.Show("Unable to start: " & ex.Message, "Run Application")
  139.     End Try
  140.   End Sub
  141.   Private Sub SetGroups(ByVal column As Integer)
  142.     ' Sets FileListView to the groups created for
  143.    ' the filename column.
  144.    ' Although you could ostensibly support grouping
  145.    ' on any column, this example groups only on the
  146.    ' file name column.
  147.    ' Remove the current groups.
  148.    FileListView.Groups.Clear()
  149.     ' Keep track of whether you've used the
  150.    ' group name yet:
  151.    Dim groups As New List(Of String)
  152.     ' Iterate through the items in FileListView.
  153.    For Each item As ListViewItem In FileListView.Items
  154.       ' Retrieve the text value for the column.
  155.      Dim groupName As String = _
  156.        item.Text.Substring(0, 1).ToUpper()
  157.       ' If the groups table does not already contain a group
  158.      ' for the value, add a new group:
  159.      If groups.Contains(groupName) Then
  160.         ' Group name exists: retrieve a reference:
  161.        item.Group = FileListView.Groups(groupName)
  162.       Else
  163.         ' Group name doesn't exist. Add it now:
  164.        groups.Add(groupName)
  165.         item.Group = _
  166.          FileListView.Groups.Add(groupName, groupName)
  167.       End If
  168.     Next item
  169.   End Sub
  170.   Private Sub FileListView_ColumnClick( _
  171.    ByVal sender As System.Object, _
  172.    ByVal e As ColumnClickEventArgs) _
  173.    Handles FileListView.ColumnClick
  174.     Try
  175.       ' Hide updates until you're done.
  176.      FileListView.BeginUpdate()
  177.       ' Don't sort if showing groups:
  178.      If Not showGroups Then
  179.         ' If you've clicked on the same column again,
  180.        ' toggle the sort order. If it's a different column,
  181.        ' sort ascending.
  182.        If e.Column <> selectedColumn Then
  183.           ' Different column? Always sort ascending:
  184.          order = SortOrder.Ascending
  185.         Else
  186.           ' Same column? Toggle the order:
  187.          If order = SortOrder.Descending Then
  188.             order = SortOrder.Ascending
  189.           Else
  190.             order = SortOrder.Descending
  191.           End If
  192.         End If
  193.         ' Select the correct IComparer:
  194.        Dim sorter As IComparer = Nothing
  195.         Select Case e.Column
  196.           Case 0
  197.             ' File name:
  198.            sorter = New _
  199.              ListViewStringSorter(e.Column, order)
  200.           Case 1
  201.             ' File size:
  202.            sorter = New _
  203.              ListViewSizeSorter(e.Column, order)
  204.           Case 2
  205.             ' File date:
  206.            sorter = New _
  207.              ListViewDateSorter(e.Column, order)
  208.           Case Else
  209.             ' Any other column? Sort as a string:
  210.            sorter = New _
  211.              ListViewStringSorter(e.Column, order)
  212.         End Select
  213.         ' Set the sorter, and sort the data.
  214.        ' Setting the control's Sorting property
  215.        ' also automatically sorts the data, but
  216.        ' only on the first "column" of data:
  217.        FileListView.ListViewItemSorter = sorter
  218.       End If
  219.     Finally
  220.       FileListView.EndUpdate()
  221.       selectedColumn = e.Column
  222.     End Try
  223.   End Sub
  224.   Private Sub LargeIconToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles LargeIconToolStripMenuItem.Click
  225.     FileListView.View = View.LargeIcon
  226.   End Sub
  227.   Private Sub DetailsToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles DetailsToolStripMenuItem.Click
  228.     FileListView.View = View.Details
  229.   End Sub
  230.   Private Sub SmallIconToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SmallIconToolStripMenuItem.Click
  231.     FileListView.View = View.SmallIcon
  232.   End Sub
  233.   Private Sub ListToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ListToolStripMenuItem.Click
  234.     FileListView.View = View.List
  235.   End Sub
  236.   Private Sub TileToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TileToolStripMenuItem.Click
  237.     FileListView.View = View.Tile
  238.   End Sub
  239.   Private Sub GroupFileNamesToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles GroupFileNamesToolStripMenuItem.Click
  240.     showGroups = Not showGroups
  241.     FileListView.ShowGroups = showGroups
  242.     GroupFileNamesToolStripMenuItem.Checked = Not GroupFileNamesToolStripMenuItem.Checked
  243.     FillFiles(FoldersTreeView.SelectedNode)
  244.   End Sub
  245.   Private Sub TreeViewContextMenuStrip_Opening(ByVal sender As System.Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles TreeViewContextMenuStrip.Opening
  246.     LargeIconToolStripMenuItem.Checked = False
  247.     DetailsToolStripMenuItem.Checked = False
  248.     SmallIconToolStripMenuItem.Checked = False
  249.     ListToolStripMenuItem.Checked = False
  250.     TileToolStripMenuItem.Checked = False
  251.     GroupFileNamesToolStripMenuItem.Checked = False
  252.     Select Case FileListView.View
  253.       Case View.Details
  254.         DetailsToolStripMenuItem.Checked = True
  255.       Case View.LargeIcon
  256.         LargeIconToolStripMenuItem.Checked = True
  257.       Case View.List
  258.         ListToolStripMenuItem.Checked = True
  259.       Case View.SmallIcon
  260.         SmallIconToolStripMenuItem.Checked = True
  261.       Case View.Tile
  262.         TileToolStripMenuItem.Checked = True
  263.     End Select
  264.     GroupFileNamesToolStripMenuItem.Checked = FileListView.ShowGroups
  265.   End Sub
  266. #End Region
  267.   Private Sub TreeViewListViewDemo_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
  268.     FileListView.SmallImageList = images
  269.     FileListView.LargeImageList = largeImages
  270.     FillDrives()
  271.   End Sub
  272. End Class
  273.  

TheMaster

  • Guest
Re: selecting numerous files in different locations
« Reply #5 on: November 07, 2012, 03:54:53 PM »
maybe someone could help me.
I have some code that i use to select files, the problem i'm having is when i pick a new drive some time it take way to long to fill the folder tree.
any help would be great. autocad 2012 vb express 10.....C:\Working-Folder\testing\FileSelect-plug-in\FileSelect-plug-in\bin\Debug\FileSelect-plug-in.dll
the commmand is test.

Thanks

If you're using the WinForms TreeView, you might find that adding many nodes at once using the TreeNodeCollection's AddRange() method can be much faster than adding one node at a time. The TreeNode stores its child nodes in an array that must be resized whenever more capacity is needed, and AddRange() will do the required reallocation of memory in a single operation rather than potentially many operations that might be needed when adding one node at a time.  A simple example: Adding 1025 nodes, one at a time will require around 7 or 8 memory reallocations (the capacity is doubled on each reallocation, starting at 4 items). If you add all the nodes at once via a single call to AddRange() it will require only one memory reallocation regardless of how many nodes you add. Each 'automatic' reallocation that happens when adding a single node at a time involves creating a new array whose capacity is double the size of the existing array, and copying the contents of the existing array to the new array.  You can take advantage of that when using either the 'eager' or the lazy approach, and especially with the latter, where the user must wait for child nodes to be added the first time they expand a parent node. If there are many child nodes to add, the delay will be quite noticeable.

If you look at the code from my post that Kaefer linked to, you'll notice that I made the same mistake there, and most of the TreeView code I have here now was corrected.

Here's the relevant code from that attachment:

Code - C#: [Select]
  1. // FolderTreeNode.cs
  2.  
  3. protected virtual int CreateChildren()
  4. {
  5.    Cursor saved = Cursor.Current;
  6.    Cursor.Current = Cursors.WaitCursor;
  7.    if( this.TreeView != null )
  8.       this.TreeView.BeginUpdate();
  9.    this.Nodes.Clear();
  10.    try
  11.    {
  12.       if( !string.IsNullOrEmpty( this.folder ) && Directory.Exists( this.folder ) )
  13.       {
  14.          foreach( string folder in Directory.GetDirectories( this.folder ) )
  15.          {
  16.             this.Nodes.Add( new FolderTreeNode( folder ) );
  17.          }
  18.       }
  19.       return this.Nodes.Count;
  20.    }
  21.    finally
  22.    {
  23.       Cursor.Current = saved;
  24.       if( this.TreeView != null )
  25.          this.TreeView.EndUpdate();
  26.    }
  27. }
  28.  
  29.  

And here's how it should have been written:

Code - C#: [Select]
  1.  
  2.  
  3. protected virtual int CreateChildren()
  4. {
  5.    Cursor saved = Cursor.Current;
  6.    Cursor.Current = Cursors.WaitCursor;
  7.    if( this.TreeView != null )
  8.       this.TreeView.BeginUpdate();
  9.    this.Nodes.Clear();
  10.    try
  11.    {
  12.       if( !string.IsNullOrEmpty( this.folder ) && Directory.Exists( this.folder ) )
  13.       {
  14.          var directories = Directory.GetDirectories( this.Folder );
  15.          if( directories.Length > 0 )
  16.          {
  17.             TreeNode[] array = new TreeNode[directories.Length];
  18.             for( int i = 0; i < directories.Length; i++ )
  19.             {
  20.                array[i] = new FolderTreeNode( directories[i] );
  21.             }
  22.             this.Nodes.AddRange( array );
  23.          }
  24.       }
  25.       return this.Nodes.Count;
  26.    }
  27.    finally
  28.    {
  29.       Cursor.Current = saved;
  30.       if( this.TreeView != null )
  31.          this.TreeView.EndUpdate();
  32.    }
  33. }
  34.  
  35. // Missy
  36.  
  37.  
« Last Edit: November 07, 2012, 04:12:58 PM by TT »

WOWENS

  • Newt
  • Posts: 59
Re: selecting numerous files in different locations
« Reply #6 on: November 08, 2012, 10:09:19 AM »
thank you all for all your help, I really appreciate it.

kaefer

  • Guest
Re: selecting numerous files in different locations
« Reply #7 on: November 08, 2012, 10:14:41 AM »
If you're using the WinForms TreeView, you might find that adding many nodes at once using the TreeNodeCollection's AddRange() method can be much faster than adding one node at a time.

Yay, Tony, that's a useful addition!

I translated your venerable example to F# and tried to reduce it to the bare bones, but failed utterly at making it generic. That is, instead of the projections toName : string -> string, getChildNodes : string -> string[] and predicate : string -> bool, it should be possible, at least in theory, to replace the string argument with any type 'T.

Anyway, these are the path and directory-specific functions encapsulated in a module:
Code - F#: [Select]
  1. [<AutoOpen>]
  2. module internal FolderTreeNodeModule =
  3.    
  4.     let toName path =
  5.         let name = System.IO.Path.GetFileName path
  6.         if System.String.IsNullOrEmpty name then path else name
  7.  
  8.     let getChildNodes path =
  9.         System.IO.Directory.GetDirectories path
  10.         |> Array.filter (fun dir ->
  11.             not <| (System.IO.File.GetAttributes dir).HasFlag
  12.                 System.IO.FileAttributes.ReparsePoint )
  13.  
  14.     let predicate path =
  15.         not <| System.String.IsNullOrEmpty path &&
  16.         System.IO.Directory.Exists path

Here's the lazy TreeNode. The placeholder property is coded by an out-of-band value, null.
Code - F#: [Select]
  1. type FolderTreeNode (folder) as this =
  2.     inherit TreeNode(toName folder)
  3.  
  4.     let addNodes =
  5.         Array.map (fun dir -> new FolderTreeNode(dir) :> TreeNode)
  6.         >> this.Nodes.AddRange
  7.  
  8.     let update f =
  9.         if this.TreeView <> null then
  10.             this.TreeView.BeginUpdate()
  11.         this.Nodes.Clear()
  12.         {   new System.IDisposable with
  13.                 member me.Dispose() =
  14.                     f()
  15.                     if this.TreeView <> null then
  16.                         this.TreeView.EndUpdate() }
  17.  
  18.     let error f arg =
  19.         try f arg with ex ->
  20.             this.Text <- sprintf "%s (Error: %s)" this.Text ex.Message
  21.  
  22.     let createChildren asPlaceHolder =
  23.         match asPlaceHolder, getChildNodes folder with
  24.         | _, [| |] -> Array.empty
  25.         | true, _ -> [| null |]
  26.         | _, childNodes -> childNodes
  27.         |> addNodes
  28.  
  29.     do  
  30.         if folder <> null then
  31.             use d = update ignore
  32.             error createChildren true
  33.            
  34.     member __.IsPlaceHolder = folder = null
  35.  
  36.     member me.Expanding() =
  37.         if  me.Nodes.Count = 1 &&
  38.             (me.FirstNode :?> FolderTreeNode).IsPlaceHolder &&
  39.             predicate folder then
  40.  
  41.             let saved = Cursor.Current
  42.             use d = update (fun () -> Cursor.Current <- saved)
  43.             Cursor.Current <- Cursors.WaitCursor
  44.             error createChildren false
  45.  
  46.     member __.IsPlaceHolder = folder = null
  47.  
  48.     member me.Expanding() =
  49.         if folder <> null && me.Nodes.Count = 1 &&
  50.            (me.FirstNode :?> FolderTreeNode).IsPlaceHolder then
  51.  
  52.             try createChildren folder
  53.             with ex ->
  54.                 this.Text <- sprintf "%s (Error: %s)" this.Text ex.Message

And here's the point of use inside the TreeView.
Code - F#: [Select]
  1. type FolderTreeView() =
  2.     inherit TreeView()
  3.     ...
  4.     override me.OnBeforeExpand e =
  5.         base.OnBeforeExpand e
  6.         match e.Cancel, box e.Node with
  7.         | false, (:? FolderTreeNode as ftn) -> ftn.Expanding()
  8.         | _ -> ()

Edit: Logic's been screwed up inside FolderTreeNode class
« Last Edit: November 08, 2012, 05:16:12 PM by kaefer »