Introduction
While working on the project of converting and upgrading Siccolo for Windows Mobile 5 to Siccolo for Windows Mobile 6 for Smartphones, I realized that Windows Mobile 6 for Smartphone edition is missing OpenFilDlg
and SaveFileAsDlg
controls. By default, a Smartphone does not include a File Explorer application and there are no common file dialog boxes available to the developer.
Some of the features of Siccolo include ability to browse and select SQL Script on mobile device, and be able to save SQL Script in a given folder on the mobile device.
This article shows how to create a form to allow select file for opening, or to "Save File As":
Code
Now, the code part. In my case, I wanted to create a form that:
- Looks and works like standard file explorer in Windows Mobile 6
- Allows to switch between "Open File" and "Save File As" dialog mode - allows to select a file to open, or to select a folder and enter a file name for saving
- Exposes
SelectedFileName
as a property
- Allows to "filter" files to display
To display folders and files on the mobile device, I'm using the TreeView
control. To allow one form to behave as "Open File Dialog" and "Save File As Dialog", I added text box (hidden/shown during run-time based on selection):
Public Enum DialogMode As Integer
OpenFile = 0
SaveFileAs = 1
End Enum
Private m_DialogMode As DialogMode = DialogMode.OpenFile
Public Property Mode() As DialogMode
Get
Return m_DialogMode
End Get
Set(ByVal value As DialogMode)
m_DialogMode = value
If m_DialogMode = DialogMode.SaveFileAs Then
txtFileName.Visible = True
lblFileName.Visible = True
trwFileExplorer.Height = _
trwFileExplorer.Height - txtFileName.Height - 10
End If
End Set
End Property
and to display such form:
...
...
Dim dlgOpenFile As New frmOpenFileDialogSP
dlgOpenFile.Filter = "*.sql"
dlgOpenFile.Mode = frmOpenFileDialogSP.DialogMode.OpenFile
If dlgOpenFile.ShowDialog() = Windows.Forms.DialogResult.OK Then
...
...
In the TreeView
, I wanted to display just "one level", and as soon as the user selects a folder, TreeView
will display contents (sub-folders and files) of the selected folder:
In order to populate TreeView
with sub folders and files for a given folder:
Private Sub AddSubFolders(ByVal ParentPath As String)
Try
Dim ParentFolder As New DirectoryInfo(stripExtraSlash(ParentPath))
Dim DirInfoComparer As DirectoryInfoComparer =
New DirectoryInfoComparer()
Dim DirList() As DirectoryInfo = ParentFolder.GetDirectories()
Array.Sort(DirList, DirInfoComparer)
Dim dirInfo As DirectoryInfo
For Each dirInfo In DirList Dim DirectoryNode As New TreeNode
DirectoryNode.Text = dirInfo.Name DirectoryNode.Tag = dirInfo.FullName
DirectoryNode.ImageIndex = 0 trwFileExplorer.Nodes.Add(DirectoryNode)
Next
Dim FileInfoComparer As FileInfoComparer = New FileInfoComparer()
If m_Filter = "" Then m_Filter = "*.*"
Dim FileList() As FileInfo = ParentFolder.GetFiles(m_Filter)
Array.Sort(FileList, FileInfoComparer)
Dim fileInfo As FileInfo
Dim AddFile As Boolean = True
For Each fileInfo In FileList Dim FileNode As New TreeNode
FileNode.Text = fileInfo.Name
FileNode.Tag = fileInfo.FullName
FileNode.ImageIndex = 1 FileNode.SelectedImageIndex = 1 trwFileExplorer.Nodes.Add(FileNode)
Next
Catch ex_add_subfolder As Exception
End Try
End Sub
In the above code:
- First, get a folder we're in:
Dim ParentFolder As New DirectoryInfo(stripExtraSlash(ParentPath))
, where stripExtraSlash()
function :
Private Function stripExtraSlash(ByVal str As String) As String
Dim path As String = str
If path.Length > 1 And (Mid(path, 1, 1) = "\") Then
path = Mid(path, 2, path.Length - 1)
End If
Return path
End Function
- Then, get sub-folders, using
ParentFolder.GetDirectories()
. But because I wanted to present a list of folders and files sorted, I had to add "custom" comparer for sorting:
...
<code>Dim DirInfoComparer As DirectoryInfoComparer =
New DirectoryInfoComparer()
Dim DirList() As DirectoryInfo = ParentFolder.GetDirectories()
Array.Sort(DirList, DirInfoComparer)
...
where DirectoryInfoComparer()
and FileInfoComparer()
:
Imports System.IO
Public Class DirectoryInfoComparer _
Implements System.Collections.IComparer
Public Function Compare(ByVal objDirInfo1 As Object, _
ByVal objDirInfo2 As Object) As Integer _
Implements IComparer.Compare
Dim DirInfo1 As System.IO.DirectoryInfo = _
CType(objDirInfo1, System.IO.DirectoryInfo)
Dim DirInfo2 As System.IO.DirectoryInfo = _
CType(objDirInfo2, System.IO.DirectoryInfo)
Return String.Compare(DirInfo1.Name, DirInfo2.Name, True)
End Function
End Class
Public Class FileInfoComparer Implements System.Collections.IComparer
Public Function Compare(ByVal objFileInfo1 As Object, _
ByVal objFileInfo2 As Object) As Integer _
Implements IComparer.Compare
Dim FileInfo1 As System.IO.FileInfo = _
CType(objFileInfo1, System.IO.FileInfo)
Dim FileInfo2 As System.IO.FileInfo = _
CType(objFileInfo2, System.IO.FileInfo)
Return String.Compare(FileInfo1.Name, FileInfo2.Name, True)
End Function
End Class
- Once folders are "sorted" in a better way, we can add them to the
TreeView
:
...
For Each dirInfo In DirList Dim DirectoryNode As New TreeNode
DirectoryNode.Text = dirInfo.Name DirectoryNode.Tag = dirInfo.FullName
DirectoryNode.ImageIndex = 0 trwFileExplorer.Nodes.Add(DirectoryNode)
Next
...
Notice, as a folder node is added to TreeView
, node tag contains full name of a direcory being added.
And files are the same way - get them with ParentFolder.GetFiles()
, sort them using FileInfoComparer()
, add them to TreeView
using Nodes.Add()
. We can also provide "filtering" with ParentFolder.GetFiles(searchPattern)
.
When the user selectes a folder (using "enter" key on smartphone), TreeView
is populated with contents of that folder:
Private Sub frmOpenFileDialogSP_KeyDown(ByVal sender As System.Object, _
ByVal e As System.Windows.Forms.KeyEventArgs) _
Handles MyBase.KeyDown
...
If (e.KeyCode = System.Windows.Forms.Keys.Enter) Then
If trwFileExplorer.SelectedNode Is Nothing Then
Exit Sub
End If
If trwFileExplorer.SelectedNode.ImageIndex <> 1 Then
<code>Dim Path As String = _
System.IO.Path.Combine(trwFileExplorer.Tag, _
trwFileExplorer.SelectedNode.FullPath)
trwFileExplorer.BeginUpdate()
trwFileExplorer.Nodes.Clear()
AddTopFolder(Path)
trwFileExplorer.EndUpdate()
Exit Sub
End If
...
...
End If
...
...
End Sub
Where AddTopFolder()
function:
Private Sub AddTopFolder(ByVal InitialPath As String)
Dim strPath As String = IIf(InitialPath = "", "\", InitialPath)
Try
Dim TopFolder As New DirectoryInfo(stripExtraSlash(strPath))
ChangeTopFolder(TopFolder)
mnuUp.Enabled = Not (TopFolder.Parent Is Nothing)
Catch ex As Exception
MessageBox.Show("Invalid Path [" & InitialPath & "]" & vbCrLf & _
"-----------------------------------" & vbCrLf & _
ex.Message & vbCrLf & _
"-----------------------------------", _
"Siccolo SP", _
MessageBoxButtons.OK, _
MessageBoxIcon.Exclamation, _
MessageBoxDefaultButton.Button1)
Me.DialogResult = Windows.Forms.DialogResult.Cancel
Me.Close()
End Try
AddSubFolders(strPath)
End Sub
And ChangeTopFolder()
:
Private Sub ChangeTopFolder(ByVal Folder As DirectoryInfo)
lblPath.Text = Folder.Name
<code>trwFileExplorer.Tag = Folder.FullName
End Sub
So, anytime the ParentFolder
is changed - TreeView
keeps directory name in Tag
property - to get the full path of a selected folder in TreeView
, we just need to combine Path.Combine(trwFileExplorer.Tag, trwFileExplorer.SelectedNode.FullPath)
.
Then, we just need to allow the user to go up one level (as in standard Windows Mobile File Explorer):
Private Sub mnuUp_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles mnuUp.Click
Try
Dim Path As String = trwFileExplorer.Tag
Dim ParentFolder As DirectoryInfo = New DirectoryInfo(Path)
If ParentFolder.Parent Is Nothing Then Exit Sub
Path = ParentFolder.Parent.FullName
trwFileExplorer.BeginUpdate()
trwFileExplorer.Nodes.Clear()
AddTopFolder(Path)
trwFileExplorer.EndUpdate()
Catch ex_go_up As Exception
End Try
End Sub
To "go up" - because TreeView.Tag
property contains the full directory path of the current folder, based on that we create New DirectoryInfo(Path)
, and by referencing ParentFolder.Parent
, we get full the directory path of "up" folder.
To handle "Save File As":
txtFileName
is shown:
...
If m_DialogMode = DialogMode.SaveFileAs Then
<codetxtFileName.Visible = True
lblFileName.Visible = True
trwFileExplorer.Height = _
trwFileExplorer.Height - txtFileName.Height - 10
End If
...
- and, to allow user "jump" from
TreeView
to text box txtFileName
, to enter a "Save File As" file name:
Private Sub frmOpenFileDialogSP_KeyDown(ByVal sender As System.Object, _
ByVal e As System.Windows.Forms.KeyEventArgs) _
Handles MyBase.KeyDown
<code>If (e.KeyCode = System.Windows.Forms.Keys.Left) Then
If m_DialogMode = DialogMode.SaveFileAs Then
txtFileName.Focus()
End If
End If
If (e.KeyCode = System.Windows.Forms.Keys.Right) Then
If m_DialogMode = DialogMode.SaveFileAs Then
txtFileName.Focus()
End If
End If
If (e.KeyCode = System.Windows.Forms.Keys.Enter) Then
If trwFileExplorer.SelectedNode Is Nothing Then
Exit Sub
End If
If trwFileExplorer.SelectedNode.ImageIndex <> 1 Then
Dim Path As String = _
System.IO.Path.Combine(trwFileExplorer.Tag, _
trwFileExplorer.SelectedNode.FullPath)
trwFileExplorer.BeginUpdate()
trwFileExplorer.Nodes.Clear()
AddTopFolder(Path)
trwFileExplorer.EndUpdate()
Exit Sub
End If
If m_DialogMode = DialogMode.OpenFile Then
m_FullPath = trwFileExplorer.Tag
m_SelectedFileName = trwFileExplorer.SelectedNode.Text
m_SelectedFullFileName = System.IO.Path.Combine_
(m_FullPath, m_SelectedFileName)
Me.DialogResult = Windows.Forms.DialogResult.OK
Me.Close()
Else
txtFileName.Focus()
End If
End If
End Sub
And finally, when the user "clicks" the enter key:
Private Sub frmOpenFileDialogSP_KeyDown(ByVal sender As System.Object, _
ByVal e As System.Windows.Forms.KeyEventArgs) Handles MyBase.KeyDown
...
If m_DialogMode = DialogMode.OpenFile Then
m_FullPath = trwFileExplorer.Tag
m_SelectedFileName = trwFileExplorer.SelectedNode.Text
m_SelectedFullFileName = System.IO.Path.Combine_
(m_FullPath, m_SelectedFileName)
Me.DialogResult = Windows.Forms.DialogResult.OK
Me.Close()
Else
txtFileName.Focus()
End If
...
end sub
Private Sub txtFileName_KeyDown(ByVal sender As Object, _
ByVal e As System.Windows.Forms.KeyEventArgs) _
Handles txtFileName.KeyDown
If (e.KeyCode = System.Windows.Forms.Keys.Enter) Then
If m_DialogMode = DialogMode.SaveFileAs Then
m_FullPath = trwFileExplorer.Tag
m_SelectedFileName = txtFileName.Text
m_SelectedFullFileName = System.IO.Path.Combine_
(m_FullPath, m_SelectedFileName)
Me.DialogResult = Windows.Forms.DialogResult.OK
Me.Close()
End If
End If
End Sub
The result:
More on this subject
Points of Interest
If you would like to read more on this story - please take a look at Siccolo - Free Mobile Management Tool For SQL Server and more articles at Siccolo Articles.