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.
|