location of recent files list vb.net - vb.net

I am looking to add a recent files list to an application I am writing.
I was thinking of adding the recent files to an xml file.
Where should this file be stored?
And how should it be called from the code?
I would imagine the xml would be stored in the same folder that the application is installed in, but not everybody will install the application in the same directory.
Is there a way to code it in such a manner that it will always be stored in the same folder as the application will be installed in?
much thanks in advance!

Here is an example using My.Settings. It requires you to open the Settings page of the project properties and add a setting of type StringCollection named RecentFiles as well as a ToolStripMenuItem with the text "Recent".
Imports System.Collections.Specialized
Public Class Form1
Private Const MAX_RECENT_FILES As Integer = 10
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
LoadRecentFiles()
End Sub
Private Sub LoadRecentFiles()
Dim recentFiles = My.Settings.RecentFiles
'A StringCollection setting will be Nothing by default, unless you edit it in the Settings designer.
If recentFiles Is Nothing Then
My.Settings.RecentFiles = New StringCollection()
recentFiles = My.Settings.RecentFiles
End If
'Get rid of any existing menu items.
RecentToolStripMenuItem.DropDownItems.Clear()
'Add a menu item for each recent file.
If recentFiles.Count > 0 Then
RecentToolStripMenuItem.DropDownItems.AddRange(recentFiles.Cast(Of String)().
Select(Function(filePath) New ToolStripMenuItem(filePath,
Nothing,
AddressOf RecentFileMenuItems_Click)).
ToArray())
End If
End Sub
Private Sub UpdateRecentFiles(filePath As String)
Dim recentFiles = My.Settings.RecentFiles
'If the specified file is already in the list, remove it from its old position.
If recentFiles.Contains(filePath) Then
recentFiles.Remove(filePath)
End If
'Add the new file at the top of the list.
recentFiles.Insert(0, filePath)
'Trim the list if it is too long.
While recentFiles.Count > MAX_RECENT_FILES
recentFiles.RemoveAt(MAX_RECENT_FILES)
End While
LoadRecentFiles()
End Sub
Private Sub RecentFileMenuItems_Click(sender As Object, e As EventArgs)
Dim menuItem = DirectCast(sender, ToolStripMenuItem)
Dim filePath = menuItem.Text
'Open the file using filePath here.
End Sub
End Class
Note that the Load event handler includes a bit of code to allow for the fact that a setting of type StringCollection will be Nothing until you assign something to it. If you want to avoid having to do that in code, do the following.
After adding the setting, click the Value field and click the button with the ellipsis (...) to edit.
Add any text to the editor and click OK. Notice that some XML has been added that includes the item(s) you added.
Click the edit button (...) again and delete the added item(s). Notice that the XML remains but your item(s) is gone.
That XML code will cause a StringCollection object to be created when the settings are first loaded, so there's no need for you to create one in code.
EDIT:
I tested that by adding the following code:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Using dialogue As New OpenFileDialog
If dialogue.ShowDialog() = DialogResult.OK Then
UpdateRecentFiles(dialogue.FileName)
End If
End Using
End Sub
I was able to add ten files to the list via that Button and then they started dropping off the end of the list as I added more. If I re-added one that was already in the list, it moved to the top. If I closed the app and ran it again, the list persisted.

Related

Why Is A FilePath Item With ~$ Added To ListBox

I am adding file paths from a folder to a List Box which are then opened as text in a Rich Text Box. I have used the same syntax as the code below for achieving the same purpose in another List Box and it works just fine. But, in the current example, I have two files in the default MyProjects folder (i.e. default folder is created by my app), but when I add the file paths from the folder as items to the List Box, I get a third item with ~$ in the file path? This item is obviously some kind of repetition of the first file path in the list? The two files in the default folder are also created by my app so, if this is a file access issue, I don't understand why I wouldn't have access to a file created by my app? Can anyone give me a clue what's happening here?
What I have Tried:
I have tried debugging to check where the extra file path is coming from. As far as I can tell, it is being created when I add the file paths to the List Box? i.e. commenting out the code for adding the items to the List Box stops all items being added, but doesn't tell me where this extra item is coming from?
The "Extra Item" Issue:
System.Windows.Forms.ListBox+ObjectCollectionC:\Users\username\Documents\MySolution\MyProjects\RTFdoc.rtf
C:\Users\username\Documents\MySolution\MyProjects\Testdoc.rtf
C:\Users\username\Documents\MySolution\MyProjects~$Fdoc.rtf
The Code:
lbxName.Items.AddRange(Directory.GetFiles("C:\Users\" + username + "\Documents\MySolution\MyProjects"))
lbxName.SelectedIndex = 0
Code For Loading:
For Each item In lbxName.SelectedItems
RTB.LoadFile(lbxName.SelectedItem, RichTextBoxStreamType.RichText)
Next
I cannot reproduce the error in the following code.
Private Sub FillListBox()
ListBox1.Items.AddRange(Directory.GetFiles("C:\Users\" & username & "\Documents\MySolution\MyProjects"))
ListBox1.SelectedIndex = 0
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
FillListBox()
End Sub
Please read the comments in the following code.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
For Each item In ListBox1.SelectedItems
'The following will overwrite the contents of the RichTextBox on each iteration
'This overload of LoadFile will only handle .rtf files
RichTextBox1.LoadFile(item.ToString)
Next
End Sub
I suggest you set the SelectionMode property to One in the designer and do the following.
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
RichTextBox1.LoadFile(ListBox1.SelectedItem.ToString)
End Sub
Try to use as follows:
Directory.GetFiles("C:\Users\" & username & "\Documents\MySolution\MyProjects").Where(Function(f)
Return New IO.FileInfo(f).Attributes & IO.FileAttributes.Hidden & IO.FileAttributes.System = 0

.NET Delete actual files from listbox

This code is intended to delete the actual files from the system when it is selected from the system:
Dim file As String()
file = System.IO.Directory.GetFiles("C:\Users\User\Desktop", "lalala.txt", IO.SearchOption.AllDirectories)
If ListBox1.SelectedIndex = -1 Then
MsgBox("No files selected")
Else
System.IO.File.Delete(ListBox1.Items(ListBox1.SelectedIndex).ToString())
ListBox1.Items.RemoveAt(ListBox1.SelectedIndex)
End If
However, only the items in the listbox are deleted. The actual file still exists. I am unsure where I should put the file into the Delete function.
I have referred to this but it has not helped me.
________UPDATE________
I have discovered where it went wrong: it is because only the file name is added to the listbox:
ListBox1.Items.Add(Path.GetFileName(fileFound))
Instead of Path.GetFullPath.
Anyhow, can I delete the file with GetFileName only?
The problem, as you realised, is that the filename only is not enough information to delete a file. You need the whole path to the file as well. So you need some way of storing the whole path but only showing the filename. This is also important because there might be two (or more) files with same name in separate directories.
A ListBox can have its Datasource property set to show items from "an object that implements the IList or IListSource interfaces, such as a DataSet or an Array."
Then you set the DisplayMember and ValueMember properties to tell it what to display and what to give as the value.
For example, I made up a class named "FileItem" which has properties for the full filename and for whatever you want to display it as, filled a list with instances of "FileItem", and told ListBox1 to display it:
Imports System.IO
Public Class Form1
Class FileItem
Property FullName As String
Property DisplayedName As String
Public Sub New(filename As String)
Me.FullName = filename
Me.DisplayedName = Path.GetFileNameWithoutExtension(filename)
End Sub
End Class
Private Sub PopulateDeletionList(dir As String, filter As String)
Dim files = Directory.EnumerateFiles(dir, filter, SearchOption.AllDirectories)
Dim fileNames = files.Select(Function(s) New FileItem(s)).ToList()
Dim bs As New BindingSource With {.DataSource = fileNames}
ListBox1.DataSource = bs
ListBox1.DisplayMember = "DisplayedName"
ListBox1.ValueMember = "FullName"
End Sub
Private Sub ListBox1_Click(sender As Object, e As EventArgs) Handles ListBox1.Click
Dim lb = DirectCast(sender, ListBox)
Dim sel = lb.SelectedIndex
If sel >= 0 Then
Dim fileToDelete = CStr(lb.SelectedValue)
Dim choice = MessageBox.Show("Do you really want to delete " & fileToDelete, "Confirm file delete", MessageBoxButtons.YesNo, MessageBoxIcon.Question)
If choice = DialogResult.Yes Then
Try
File.Delete(fileToDelete)
lb.DataSource.RemoveAt(sel)
Catch ex As Exception
MessageBox.Show("Could not delete " & fileToDelete & " because " & ex.Message)
End Try
End If
End If
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
PopulateDeletionList("C:\temp", "*.txt")
End Sub
End Class
Edited I had forgotten to delete the item from the ListBox. To do that, it needs to be tied to the DataSource through a BindingSource.
Extra feature Seeing as there could be more than one file with the same name, you might want to add a tooltip to the listbox items so that you can see which directory it is in. See how to add tooltips on winform list box items for an implementation which needs only minor adjustments to work, such as:
Dim toolTip As ToolTip = New ToolTip()
' ...
Private Sub ListBox1_MouseMove(sender As Object, e As MouseEventArgs) Handles ListBox1.MouseMove
Dim lb = DirectCast(sender, ListBox)
Dim index As Integer = lb.IndexFromPoint(e.Location)
If (index >= 0 AndAlso index < ListBox1.Items.Count) Then
Dim desiredTooltip = DirectCast(lb.Items(index), FileItem).FullName
If (toolTip.GetToolTip(lb) <> desiredTooltip) Then
toolTip.SetToolTip(lb, desiredTooltip)
End If
End If
End Sub
The most simple (and reliable) solution would be to create a custom data type and add that to the ListBox instead.
By overriding the ToString() method you can make it display only the file name, while the back-end object still contains the full path.
Public Structure FileEntry
Public FullPath As String 'A variable holding the full path to the file.
'Overriding the ToString() method, making it only return the file name.
Public Overrides Function ToString() As String
Return System.IO.Path.GetFileName(Me.FullPath)
End Function
Public Sub New(ByVal Path As String)
Me.FullPath = Path
End Sub
End Structure
Now whenever you want to add paths to the ListBox you've got to add a new instance of the FileEntry structure, instead of a regular string:
ListBox1.Items.Add(New FileEntry(fileFound))
And to delete you just cast the currently selected item into a FileEntry, and then pass its FullPath onto the File.Delete() method.
Dim Entry As FileEntry = DirectCast(ListBox1.Items(ListBox1.SelectedIndex), FileEntry)
System.IO.File.Delete(Entry.FullPath)
NOTE: For this to work every item in the list box must be a FileEntry.
Online test: https://dotnetfiddle.net/x2FuV3 (pardon the formatting, DotNetFiddle doesn't work very well on a cellphone)
Documentation:
How to: Declare a Structure (Visual Basic) - Microsoft Docs
Overriding the Object.ToString() method - MSDN
You can use Path.Combine.
Since you are going to search in C:\Users\User\Desktop, you can do this to delete:
System.IO.File.Delete(Path.COmbine("C:\Users\User\Desktop",ListBox1.Items(ListBox1.SelectedIndex).ToString())
Here, "C:\Users\User\Desktop" and the selected index's text will be combined to make a single path.
Edit:
I get it, you want to show the file name onlyy in the textbox but want to delete the file from the system too but can't do it, right?
Well you can do this:
Put two listbox and while you add a file to a listbox1, put it's path to the listbox2 whose visibility will be False, meaning it won't be shown in the runtime.
DOing this, while an item is selected in the listbox1, use the path.combine to make a path by adding the filename & path from the list with same index number.
Something like this:
System.IO.File.Delete(path.combine(ListBox1.Items(ListBox1.SelectedIndex).ToString(), ListBox2.Items(ListBox1.SelectedIndex).ToString())

Visual Basic Form. How to let users save text file where they want

Private Sub Button7_Click(sender As Object, e As EventArgs) Handles Button7.Click
Dim CurrentDir As String = Environment.CurrentDirectory
Dim OutputFile2 As String = IO.Path.Combine(CurrentDir, "input.txt")
IO.File.WriteAllLines(OutputFile2, Result1.Lines)
End Sub
Right now, I have coding that saves a text file in the current directory. However, I want to have a browse button for users so that they can pick where this text file is saved. How do I proceed this?
I was trying it by my self and I'm having a trouble with using save file dialog. If you can teach me how to use a save file dialog or anyway to write save browse button, I would very appreciate it!
The documentation for the SaveFileDialog object contains an example.
Here is a tutorial on how to implement SaveFileDialog using Toolbox in Visual Studio like you mentioned. The code sample is in C# but it can be easily converted to VB.
Link: www.dotnetperls.com/savefiledialog
Private Sub button1_Click(sender As Object, e As EventArgs)
' When user clicks button, show the dialog.
saveFileDialog1.ShowDialog()
End Sub
Private Sub saveFileDialog1_FileOk(sender As Object, e As CancelEventArgs)
' Get file name.
Dim name As String = saveFileDialog1.FileName
' Write to the file name selected.
' ... You can write the text from a TextBox instead of a string literal.
File.WriteAllText(name, "test")
End Sub

Reference text box value in another form vb.net

I know this has probably been asked 1000 times but I can't get my head around it
I have a text box on a form called 'Settings' that stores a file path and I need to reference that file path in a form called 'Main
I know this should be simple but just cannot get it to work!
Any simple advice
Thanks
As below i need the Dim zMailbox to refer to a textbox value on a separate form (Settings)
Public Class Main
Dim zMailbox As String = "C:\Dropbox\User\Lynx\In\"
Private Sub Main_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim lynxin As New IO.DirectoryInfo(zMailbox)
lstPlanned.Items.Clear()
For Each txtfi In lynxin.GetFiles("*.txt")
lstPlanned.Items.Add(IO.Path.GetFileNameWithoutExtension(txtfi.Name))
Next
End Sub
You should be using something like My.Settings
To do so, you right-click on your project and then click Properties. On the left side, you have a tab called "Settings". You can create a setting there and give it a default value. Ex : MyPath.
Then on your Settings form, you set your value into My.Settings.MyPath.
My.Settings.MyPath = TextboxPath.Text.Trim()
So when you want to access it anywhere in your application after, you can just use :
My.Settings.MyPath

Transfer data from one listview to another when data been double click

I have 2 ListView setup.
Listview1 need to pass the data to listview2 when any of the data is double click by user.
How can I archive this? I am using vb 2008.
here is the image :
This is crude and simple, but it will give you a starting point. Note that there are any number of ways to approach this problem, and you will want to figure out any validation and such as required by your application. The biggest hurdle appears to be grabbing a reference to the item which is the target of the double click (as important, making sure that if the user double-clicks in an empty area of the ListView Control, that the last selected item is not added by mistake.
Hope this helps:
Public Class Form1
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Me.ListView1.FullRowSelect = True
Me.ListView2.FullRowSelect = True
End Sub
Private Sub AddItemToSecondList(ByVal item As ListViewItem)
' NOTE: We separate this part into its own method so that
' items can be added to the second list by other means
' (such as an "Add to Purchase" button)
' ALSO NOTE: Depending on your requirements, you may want to
' add a check in your code here or elsewhere to prevent
' adding an item more than once.
Me.ListView2.Items.Add(item.Clone())
End Sub
Private Sub ListView1_MouseDoubleClick(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles ListView1.MouseDoubleClick
' Use the HitTest method to grab a reference to the item which was
' double-clicked. Note that if the user double-clicks in an empty
' area of the list, the HitTestInfo.Item will be Nothing (which is what
' what we would want to happen):
Dim info As ListViewHitTestInfo = Me.ListView1.HitTest(e.X, e.Y)
'Get a reference to the item:
Dim item As ListViewItem = info.Item
' Make sure an item was the trget of the double-click:
If Not item Is Nothing Then
Me.AddItemToSecondList(item)
End If
End Sub
End Class