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
Related
I have a Window-Form 'caller' in vb.net containing a datagridview with a small overview table of certain objects, each with its own ID in the first column. Now, if a row is double clicked, i want to show a dialog 'edit', where one can edit many details of that row which i do not want in the overview table.
My approach is as follows: In the caller form i wrote this to call 'edit':
Private Sub dgdata_dbclick(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellMouseEventArgs) Handles dg_data.CellMouseDoubleClick
Dim f_edit As New edit
f_edit.ShowDialog(Me)
End Sub
That works fine.
However, in the called Form "edit" i need to check, which ID was selected and load this data from the database to edit it. I can access some data from the calling form 'caller' using e.g.
MsgBox(CType(Me.Owner, caller).Text)
to show the window title of 'caller'. However, i want to extract the currently selected ID in the datagridview or at least some variabhle containing it. In the caller form, this could be easily done by evaluating
dg_data.Item(0, selectedRow).Value.ToString
but i cannot access any relevant information in 'caller'. I have a public class with some global variables there but i cannot access them as well.
Probably my strategy to solve this problem is not the most clever approach? Basically, i want to open a very detailed edit window when someone clicks on a line in an overviewtable but simultaniously blocking the rest of the application as long as the edit window is open.
Thanks!
The idea is to pass the data to the second form. When you create an instance of the second form (my class is called Form2, yours is called edit) with the New keyword the Sub New is called on Form2.
Private Sub OpenEditDialog()
Dim f_edit As New Form2(32) '32 is the number you retrieve from your DataGridView
f_edit.ShowDialog(Me)
f_edit.Dispose()
End Sub
You pass the ID to Form2 and set a variable at Form level. You can then use the variable anywhere in Form2.
Public Class Form2
Private ID As Long
Public Sub New(SelectedID As Long)
InitializeComponent()
ID = SelectedID
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
MessageBox.Show(ID.ToString)
End Sub
End Class
You need to call InitializeComponent() so the controls will show up.
How do you usually get data into objects? You set a property or pass an argument to a method or constructor? Why should this be any different? Decide which you want to use and then write that code in your form. If it's required data, I would suggest a constructor. Just write this code in your form:
Public Sub New
and hit Enter. That will generate a little extra code automatically. You can then add a field to store the value, a parameter to the constructor and then assign the parameter to the field inside.
Thank you for pointing me to the correct route.
I solved it like this (which works fine and which is hopefully acceptable):
In the calling form:
Private Sub dgdata_dbclick(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellMouseEventArgs) Handles dg_data.CellMouseDoubleClick
Dim selectedRow As Integer = dg_data.CurrentCell.RowIndex
Dim f_edit As New edit
f_edit.edit(dg_data.Item(0, selectedRow).Value.ToString)
f_edit.ShowDialog(Me)
f_edit.Dispose()
End Sub
In the called form:
Public Sub edit(ByVal id As Long) 'Handles MyBase.Load
'Enter commands to prepare your form
End Sub
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.
Form Name comes from a variable. I would like to open Form from variable value.
In VBA load("UserFormName") will show the form. But I don't know how to do it in VB.Net.
Ok, of course one would want to be able to open a form by string name.
When you create a vb.net winforms project, then all forms are available as a "base" static class.
You often see a LOT of code thus simply use the base form class.
If I need to display say form2, then I really don't need to create a instance of that form (unless you want to have multiple instances of that form. So a truckload of code will simply launch + use the "base static" class of that form.
eg:
Form2.Show()
I don't consider this all that bad of a practice, since what do you think the project settings to "set" the startup form in the project settings does?
It simply sets the built in instance of "mainForm" = to your startup form and it does NOT create new instance.
So, now that we all can agree for 15+ years anyone who has set the startup form in their project is NOT creating a NEW instance of that form, but in fact using the base class instance. This is really a programming choice.
So, code to display (show) the base static instance of a form by string name will look like this:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim strForm As String = "Form1"
ShowFormByName(strForm)
End Sub
Public Sub ShowFormByName(strFormName As String)
System.Reflection.Assembly.GetExecutingAssembly().CreateInstance(ProductName & "." & strFormName).show()
End Sub
Private Function FormByName(strFormName As String) As Form
Return System.Reflection.Assembly.GetExecutingAssembly().CreateInstance(ProductName & "." & strFormName)
End Function
However, above includes a helper sub that will simply "show" that built in instance of the forms.
And above also includes a function to return class type of the form, since for sure a good many developers prefer to first create a instance of the form, and then "show()" it.
So, often we do want multiple instances, or we just perfer the codeing approach of creating a new instance of the form object.
So, we use the 2nd helper function to return a form object of the type we passed by string.
So, to display 3 instances of form1, but the FIRST instance being the base class, then two more but brand new instances of that form, we have this code:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim strForm As String = "Form1"
ShowFormByName(strForm)
Dim f1 As Form = FormByName(strForm)
Dim f2 As Form = FormByName(strForm)
f1.Show()
f2.Show()
End Sub
So the above code snip shows how to display the built in base class form without having to create a instance of that form.
However, the next two forms we load are "new" instances of that form as "string".
So the helper sub, and helper function will give you both choices as to which preference floats your boat.
Dim form = System.Reflection.Assembly.GetExecutingAssembly().CreateInstance(Application.ProductName & "." & MySubForm)
Dim frm As New Form
frm = form
frm.MdiParent = AFrmMainScreen
frm.WindowState = FormWindowState.Maximized
frm.Show()
I prefer to use Reflection.Assembly.GetEntryAssembly because I use several different projects in one solution. This allows me to put this code in a different project(dll) that has a usercontrol that I can then reuse across multiple solutions. You also don't need to know the "Namespace" for the form as long as it is in the startup project.
The code below gets the form type from the exported types from the entry assembly and then uses Activator.CreateInstance to create a new instance of the form. Then I return that form in the function.
Public Function GetForm(ByVal objectName As String) As Form
Try
Dim frmType = Reflection.Assembly.GetEntryAssembly.GetExportedTypes.FirstOrDefault(Function(x) x.Name = objectName)
Dim returnForm = TryCast(Activator.CreateInstance(frmType), Form)
Return TryCast(returnForm, Form)
Catch ex As Exception
Return Nothing
End Try
End Function
To use the above function:
Dim MyForm = GetForm(FormLocation)
If MyForm IsNot Nothing Then
MyForm.ShowDialog()
'You can do any form manipulation from here.
Else
MessageBox.Show($"{FormLocation} was not found.")
End If
I'm trying to develop a search window that allows a user to fill in criteria, then click the search button. When the search button is clicked the results are returned in a DataGridView. When a result in the DataGridView is clicked, I'd like to pass the row number to another form that is already open.
I understand I can pass the result by creating a new instance of the form. I pass variables to my Search Window using the following method:
Private Sub SearchButton_Click(sender As Object, e As EventArgs) Handles SearchButton.Click
Dim ST = New Search_Tool(DGV_Ongoing.DataSource, AgencyOptions, EthnicityOptions, EmploymentTypeOptions, EmploymentStatusOptions,
CategoryOptions, OutcomeOptions)
ST.Show()
End Sub
however I cannot call the form I want to pass the row value to because it is already open (its the main form). Is there a way to handle this? I'm struggling to find any information that doesn't call the form to open it whilst passing the data.
I can't reference Main_form.Main_DGV.CurrentCell as Visual Studio says it requires an Object Reference in order to do so.
Thanks in advance!
I'd recommend an event in your Search_Tool form that is raised when the user has found what they're looking for.
The main form is subscribed to that and can then access its datagrid.
Class Search_Tool
Inherits Form
Public Event SearchResultFound(resultId As Integer)
Private Sub OnUserClickedARowOrPressedAButtonOrWhatever()
RaiseEvent SearchResultFound(currentRow.Id)
End Sub
End Class
And in the main form.
Private Sub SearchButton_Click(sender As Object, e As EventArgs) Handles SearchButton.Click
Dim ST = New Search_Tool(DGV_Ongoing.DataSource, AgencyOptions, EthnicityOptions, EmploymentTypeOptions, EmploymentStatusOptions,
CategoryOptions, OutcomeOptions)
AddHandler ST.SearchResultFound, Sub(result As Integer)
'handle your result id here.
MessageBox.Show("User selected row " & result)
End Sub
ST.Show()
End Sub
The advantage of this is that the SearchForm doesn't need to know what it's being used by. It's just there to give results which will make it easier to reuse later.
I got a problem in my vb Project, as from subject its clear that I have a problem in specifying many reports in one report viewer in one form.
It's difficult to create many forms and adding report viewer in each form.
I have more than 100 reports.rdlc and want to show it in one report viewer by choosing multiple options in combobox or different criterias.
If you want the same form window to appear each time you change report in your combobox, just create a new instance of that form every time you go to generate the .rdlc report.
Button1 Click
When you click this button, it will create two reports. One report will be generated from the method YourFirstReport() and the other from YourSecondReport(). Both using the same ReportViewer1 control from the same form using a new instance of rv.
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
'Create instance "rv" of your report viewer form
Dim rv As New frmReportViewer
rv.YourFirstReport()
rv = New frmReportViewer
rv.YourSecondReport()
End Sub
rv.YourFirstReport()
Public Sub YourFirstReport()
ReportViewer1.LocalReport.ReportEmbeddedResource = "YourProject.YourFirstReportName"
'...
'And so on..
End Sub
rv.YourSecondReport()
Public Sub YourSecondReport()
ReportViewer1.LocalReport.ReportEmbeddedResource = "YourProject.YourSecondReportName"
'...
'And so on..
End Sub
Take my example here, the square in red has a button that generates my frmReportViewer every time I click on it. The green circles demonstrate my reports that pop up. Both these report utilize the same form.
You can create a single ReportViewer and set his property at runtime:
path to rldc file: .LocalReport.ReportPath
report datasources: .LocalReport.DataSources
report parameters: .LocalReport.SetParameters
other property: for example .LocalReport.EnableExternalImages
Then you can .RefreshReport().
Just as tezzo said,
ReportViewer1.LocalReport.DataSources.Clear()
ReportViewer1.LocalReport.ReportPath = "Report2.rdlc"
ReportViewer1.LocalReport.DataSources.Add(New Microsoft.Reporting.WebForms.ReportDataSource("DataSet1", CType(d1, DataTable)))
ReportViewer1.LocalReport.SetParameters(New Microsoft.Reporting.WebForms.ReportParameter("ReportCriteria", criteria))
ReportViewer1.LocalReport.SetParameters(New Microsoft.Reporting.WebForms.ReportParameter("FileDate", fileDateString))
ReportViewer1.Visible = True
ReportViewer1.DataBind()
Changing the localreport reportpath to a different reportname is all you really need.