(NET) NET (2016)

TreeView FileSelector by ReactiveNET and TheArtOfDev.HtmlRenderer (SpellChecker project).

This project was begun as service for my site for spell checking and this is a evolution of many my previous projects Building TreeView by Reactive Extensions NET (Recursive observe directory, Iterator function with Yield, Windows native thread)., SiteChecker - утилита оптимизация сайта с открытым исходным текстом.. But this project too big to describe it in one page, therefore in this page I been describe only two form of this MDI-form project.

First form is a form with Rx (Reacive Net) for selection a file to processing. It works in four mode - for file and directory or directory only and for filesystem tree or flat. Below you can see both mode of fileselector form.



This is a name of controls variables.



   1:  Imports System.Reactive.Concurrency
   2:  Imports System.Reactive.Linq
   3:  Imports System.Threading
   4:  Imports System.Collections.Generic
   5:  Imports System.ComponentModel
   6:  Imports System.Data
   7:  Imports System.Drawing
   8:  Imports System.Linq
   9:  Imports System.Text
  10:  Imports System.Windows.Forms
  11:  Imports System.IO
  12:   
  13:  ''' <summary>
  14:  ''' Provides an example of using the RxFramework to get directory listings using a background thread.
  15:  ''' </summary>
  16:  Partial Public Class DirectoriesForm
  17:   
  18:   
  19:      ' The current observer that is observing on one of the observables.
  20:      Private Observer As IDisposable
  21:   
  22:      ' An observable providing a directory as soon as it is encountered.
  23:      Private Directories As IObservable(Of String)
  24:   
  25:      ' An observable providing directories in groups.
  26:      Private BufferedDirectories As IObservable(Of IList(Of String))
  27:   
  28:      Private Sub DirectoriesForm_Load(sender As Object, e As EventArgs) Handles Me.Load
  29:          FolderBrowseStyleComboBox.SelectedIndex = 0
  30:          FolderBrowseTypeComboBox.SelectedIndex = 0
  31:          Me.butStop.Enabled = False
  32:      End Sub
  33:   
  34:   
  35:      Private Sub butOpen_Click(sender As Object, e As EventArgs) Handles butOpen.Click
  36:          Dim FB As New FolderBrowserDialog
  37:          FB.Description = "Select folder to observe"
  38:          If FB.ShowDialog = DialogResult.OK Then
  39:              Dim SyncContext = SynchronizationContext.Current
  40:              FolderBrowseStyleComboBox.Enabled = False
  41:              FolderBrowseTypeComboBox.Enabled = False
  42:              SearchPatternTextBox.Enabled = False
  43:              TreeViewDirectories.Nodes.Clear()
  44:              FileCount = 0
  45:              FolderCount = 0
  46:              If FolderBrowseStyleComboBox.Text = "Flat" Then
  47:   
  48:                  ' Observe the enumeration of all directories using the winforms thread.
  49:                  Directories = GetAllContents(FB.SelectedPath, SearchPatternTextBox.Text, FolderBrowseTypeComboBox.Text).
  50:                  ToObservable(Scheduler.ThreadPool).
  51:                  ObserveOn(SyncContext)
  52:   
  53:                  If Observer Is Nothing Then
  54:                      ' Observe on the single directories.
  55:                      Observer = Directories.Subscribe(AddressOf outputDirectory)
  56:                      'Observer = Directories.Finally(Sub() MsgBox("Finish"))
  57:                  End If
  58:   
  59:              ElseIf FolderBrowseStyleComboBox.Text = "Tree" Then
  60:                  ' Observe the enumeratino of all directories, but buffered in groups
  61:                  ' of 1000 entries each second, and then observe that group on the winforms thread.
  62:   
  63:                  BufferedDirectories = Observable.
  64:                  Interval(TimeSpan.FromSeconds(1), Scheduler.ThreadPool).
  65:                  Zip(
  66:                  GetAllContents(FB.SelectedPath, SearchPatternTextBox.Text, FolderBrowseTypeComboBox.Text).
  67:                  ToObservable(Scheduler.ThreadPool).
  68:                  Buffer(1000),
  69:                  Function(a, b) b
  70:                  ).
  71:                  ObserveOn(SyncContext)
  72:   
  73:                  If Observer Is Nothing Then
  74:                      ' observe on the buffered directories.
  75:                      Observer = BufferedDirectories.Subscribe(AddressOf outputDirectories)
  76:                      'Dim Z As IList(Of String) = BufferedDirectories.Finally(Sub() MsgBox("Finish"))
  77:                  End If
  78:              End If
  79:              butStop.Enabled = True
  80:          End If
  81:      End Sub
  82:   
  83:      ' Clear out the running observer
  84:      Private Sub butStop_Click(sender As Object, e As EventArgs) Handles butStop.Click
  85:          If Observer IsNot Nothing Then
  86:              Observer.Dispose()
  87:              Observer = Nothing
  88:              butStop.Enabled = False
  89:              FolderBrowseStyleComboBox.Enabled = True
  90:              FolderBrowseTypeComboBox.Enabled = True
  91:              SearchPatternTextBox.Enabled = True
  92:          End If
  93:      End Sub
  94:   
  95:      ' We check to see if the handle is created because when
  96:      ' the form is disposing this may still be trying to observe.
  97:      Private Sub outputDirectory(path As String)
  98:          If TreeViewDirectories.IsHandleCreated Then
  99:              TreeViewDirectories.Nodes.Add(path)
 100:          End If
 101:      End Sub
 102:   
 103:      Private TreeNodes As New Dictionary(Of String, TreeNode)()
 104:      ' We check to see if the handle is created because when
 105:      ' the form is disposing this may still be trying to observe.
 106:      Private Sub outputDirectories(paths As IEnumerable(Of String))
 107:          If TreeViewDirectories.IsHandleCreated Then
 108:              Try
 109:                  TreeViewDirectories.BeginUpdate()
 110:                  For Each path__1 In paths
 111:                      Dim sb = New StringBuilder()
 112:                      Dim pieces = path__1.Split(Path.DirectorySeparatorChar)
 113:                      Dim parent As TreeNode = Nothing
 114:                      For i As Integer = 0 To pieces.Length - 1
 115:                          Dim child As TreeNode = Nothing
 116:                          sb.Append(pieces(i))
 117:                          sb.Append(Path.DirectorySeparatorChar)
 118:                          If Not TreeNodes.TryGetValue(sb.ToString(), child) Then
 119:                              If parent IsNot Nothing Then
 120:                                  child = parent.Nodes.Add(pieces(i))
 121:                              Else
 122:                                  child = TreeViewDirectories.Nodes.Add(pieces(i))
 123:                              End If
 124:                              TreeNodes(sb.ToString()) = child
 125:                          End If
 126:                          parent = child
 127:                      Next
 128:                  Next
 129:              Finally
 130:                  TreeViewDirectories.EndUpdate()
 131:              End Try
 132:          End If
 133:      End Sub
 134:   
 135:      Shared FileCount As Integer
 136:      Shared FolderCount As Integer
 137:      'This is another thread than form
 138:      Private Iterator Function GetAllContents(path As String, SearchPattern As String, SearchType As String) As IEnumerable(Of String)
 139:          If SearchType <> "FolderOnly" Then
 140:              Dim Files As String() = Nothing
 141:              Try
 142:                  Files = Directory.GetFiles(path, SearchPattern, SearchOption.TopDirectoryOnly)
 143:              Catch generatedExceptionName As IOException
 144:              Catch generatedExceptionName As UnauthorizedAccessException
 145:              End Try
 146:              If Files IsNot Nothing Then
 147:                  For Each One In Files
 148:                      FileCount += 1
 149:                      If FileCount Mod 10 = 0 Then UpdateFileLabel(FileCount.ToString)
 150:                      Yield One
 151:                  Next
 152:              End If
 153:          End If
 154:   
 155:          Dim Subdirs As String() = Nothing
 156:          Try
 157:              Subdirs = Directory.GetDirectories(path)
 158:          Catch generatedExceptionName As IOException
 159:          Catch generatedExceptionName As UnauthorizedAccessException
 160:          End Try
 161:          If Subdirs IsNot Nothing Then
 162:              For Each subdir In Subdirs
 163:                  Debug.Print(subdir.ToString)
 164:                  FolderCount += 1
 165:                  If FolderCount Mod 10 = 0 Then UpdateFolderLabel(FolderCount.ToString)
 166:                  Yield subdir
 167:                  For Each grandchild In GetAllContents(subdir, SearchPattern, SearchType)
 168:                      FolderCount += 1
 169:                      If FolderCount Mod 10 = 0 Then UpdateFolderLabel(FolderCount.ToString)
 170:                      Debug.Print(grandchild.ToString)
 171:                      Yield grandchild
 172:                  Next
 173:              Next
 174:          End If
 175:          Debug.Print("Finish " & path)
 176:      End Function
 177:   
 178:      Public Sub UpdateFolderLabel(ProgressTXT As String)
 179:          InvokeOnUiThreadIfRequired(Sub() FolderCountLabel.Text = ProgressTXT)
 180:          InvokeOnUiThreadIfRequired(Sub() StatusStrip1.Refresh())
 181:      End Sub
 182:   
 183:      Public Sub UpdateFileLabel(ProgressTXT As String)
 184:          InvokeOnUiThreadIfRequired(Sub() FileCountLabel.Text = ProgressTXT)
 185:          InvokeOnUiThreadIfRequired(Sub() StatusStrip1.Refresh())
 186:      End Sub
 187:   
 188:      Dim SelectedNode As TreeNode
 189:      Private Sub treeViewDirectories_AfterSelect(sender As Object, e As TreeViewEventArgs) Handles TreeViewDirectories.AfterSelect
 190:          If SelectedNode Is Nothing Then
 191:              SelectedNode = TreeViewDirectories.TopNode
 192:              TreeViewDirectories.SelectedNode = TreeViewDirectories.TopNode
 193:          Else
 194:              SelectedNode = TreeViewDirectories.SelectedNode
 195:          End If
 196:          TreeViewDirectories.SelectedNode.Expand()
 197:          Dim X As MainForm = ParentForm
 198:          X.SetNewFile(e.Node.FullPath)
 199:      End Sub
 200:   
 201:      Private Sub UpToolStripButton_Click(sender As Object, e As EventArgs) Handles UpToolStripButton.Click
 202:          If TreeViewDirectories.SelectedNode Is Nothing Then
 203:              SelectedNode = TreeViewDirectories.TopNode
 204:              TreeViewDirectories.SelectedNode = TreeViewDirectories.TopNode
 205:              TreeViewDirectories.SelectedNode.Expand()
 206:          End If
 207:          TreeViewDirectories.SelectedNode = TreeViewDirectories.SelectedNode.PrevVisibleNode
 208:      End Sub
 209:   
 210:      Private Sub DownToolStripButton_Click(sender As Object, e As EventArgs) Handles DownToolStripButton.Click
 211:          If TreeViewDirectories.SelectedNode Is Nothing Then
 212:              SelectedNode = TreeViewDirectories.TopNode
 213:              TreeViewDirectories.SelectedNode = TreeViewDirectories.TopNode
 214:              TreeViewDirectories.SelectedNode.Expand()
 215:          End If
 216:          TreeViewDirectories.SelectedNode = TreeViewDirectories.SelectedNode.NextVisibleNode
 217:      End Sub
 218:  End Class

This form working don't working in isolated environment, therefore it write selected file to main (MDI-parent) form in line 198. In MDI-parent form there is method to synchronize any other form of this application to selected file for processing.


   4:      Dim BF As BrowserForm
  ...   
  25:      Public Sub SetNewFile(FileName As String)
  26:          ToolStripStatusLabel.Text = FileName
  27:          Dim X = IO.Path.GetExtension(FileName)
  28:          If X <> "" Then
  29:              BF.BrowseNewFile(FileName)
  30:              EF.EditNewFile(FileName)
  31:          End If

And Below you can see a name of controls variables in browser form.




And without spell checking and context menu Browser form is so simple.


   1:  Imports System.ComponentModel
   2:   
   3:  Public Class BrowserForm
   4:   
   5:      Property HtmlPanel As TheArtOfDev.HtmlRenderer.WinForms.HtmlPanel
   6:      Dim HtmlTxt1 As String
   7:      Dim WorkingFileName As String
   8:      Dim WithEvents BGW1 As BackgroundWorker
   9:      Dim BGW1_Prm As New Object
  10:   
  11:      Public Sub BrowseNewFile(FileName As String)
  12:          WorkingFileName = FileName
  13:          BGW1 = New BackgroundWorker
  14:          BGW1_Prm = New With {FileName}
  15:          BGW1.RunWorkerAsync(BGW1_Prm)
  16:      End Sub
  17:   
  18:      Private Sub BrowserForm_Load(sender As Object, e As EventArgs) Handles Me.Load
  19:          HtmlPanel = New TheArtOfDev.HtmlRenderer.WinForms.HtmlPanel
  20:          HtmlPanel.BackColor = System.Drawing.SystemColors.Control
  21:          HtmlPanel.BorderStyle = BorderStyle.Fixed3D
  22:          HtmlPanel.Dock = DockStyle.Fill
  23:          ToolStripContainer1.ContentPanel.Controls.Add(HtmlPanel)
  24:      End Sub
  25:   
  26:      Private Sub RefrestToolStripButton_Click(sender As Object, e As EventArgs) Handles RefrestToolStripButton.Click
  27:          BrowseNewFile(WorkingFileName)
  28:      End Sub
  29:   
  30:      Private Sub BGW1_DoWork(sender As Object, e As DoWorkEventArgs) Handles BGW1.DoWork
  31:          HtmlTxt1 = My.Computer.FileSystem.ReadAllText(e.Argument.FileName)
  32:      End Sub
  33:   
  34:      Private Sub BGW1_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles BGW1.RunWorkerCompleted
  35:          HtmlPanel.Text = HtmlTxt1
  36:          HtmlPanel.Refresh()
  37:      End Sub
  38:  End Class

Also to full understanding package.config is very important - look for is below.


   1:  <?xml version="1.0" encoding="utf-8"?>
   2:  <packages>
   3:    <package id="HtmlRenderer.Core" version="1.5.0.5" targetFramework="net452" />
   4:    <package id="HtmlRenderer.WinForms" version="1.5.0.6" targetFramework="net452" />
   5:    <package id="NHunspell" version="1.2.5554.16953" targetFramework="net452" />
   6:    <package id="System.Reactive" version="4.2.0-preview.566" targetFramework="net48" />
   7:    <package id="System.Reactive.Linq" version="4.2.0-preview.566" targetFramework="net48" />
   8:    <package id="System.Runtime.CompilerServices.Unsafe" version="4.5.2" targetFramework="net48" />
   9:    <package id="System.Threading.Tasks.Extensions" version="4.5.2" targetFramework="net48" />
  10:    <package id="System.ValueTuple" version="4.5.0" targetFramework="net48" />
  11:  </packages>

I'm sorry, no time to more detail description.



Comments ( )
<00>  <01>  <02>  <03>  <04>  <05>  <06>  <07>  <08>  <09>  <10>  <11>  <12>  <13>  <14>  <15>  <16>  <17>  <18>  <19>  <20>  <21>  <22>  <23
Link to this page: //www.vb-net.com/SpellCkecker-FileSelector/index.htm
<SITEMAP>  <MVC>  <ASP>  <NET>  <DATA>  <KIOSK>  <FLEX>  <SQL>  <NOTES>  <LINUX>  <MONO>  <FREEWARE>  <DOCS>  <ENG>  <CHAT ME>  <ABOUT ME>  < THANKS ME>