I have created a custom Class to which mimics a Textbox control but allows me to embed a button within this control. Everything works fine normally.
However my problem is that I am trying to setup a Public Property that allows me to turn this button visible or not (well create it actually), but I cannot seem to work out why my property never gets set to True - meaning that since I've implemented this piece of code, my button is no longer drawn anymore.
I have the following code:
Public Class CustomTextbox
Inherits TextBox
Private m_EnableSearch As Boolean
Private search_btn As Button
Public Sub New()
' This call is required by the designer.
Initialize()
End Sub
Private Sub Initialize()
search_btn = Nothing
'Draw the buttons
If EnableSearchButton = True Then CreateSearchButton() '<== This never equals True
End Sub
Private Sub CreateSearchButton()
search_btn = New Button()
...
...
End Sub
<Category("Appearance")> _
<Description("Enables the search button")> _
Public Property EnableSearchButton() As Boolean
Get
Return Me.m_EnableSearch
End Get
Set(value As Boolean)
Me.m_EnableSearch = value
Me.Invalidate()
End Set
End Property
End Class
If I take out the check for EnableSeachButton = True and just change it to CreateSearchButton, the button appears as expected. However, even though I can see and change the EnableSearchButton property in the design view, it never seems to equal true when I step through the code.
Any help appreciated, thanks!
Your question is a little confusing. Does EnableSearchButton actually ADD a button to the control or is it meant to toggle the Enabled state of said button? To get the button to respond to the Property and toggle the enabled state, you need to set the button's state:
Public Property EnableSearchButton() As Boolean
Get
Return Me.m_EnableSearch
End Get
Set(value As Boolean)
Me.m_EnableSearch = value
' to create the button when the prop is set:
If Value AndAlso search_btn IsNot Nothing Then
' create button
End If
If Value = False Then
' destroy button
End If
Me.Invalidate()
End Set
End Property
Since you appear to be creating the button at runtime, you will have to add a check for cases when it is nothing. Since the constructor only runs once and when created, there is no need to test the state of EnableSearchButton, just create it always.
If your Enabled property actually means something like AddButton to this TB, then just pass a Boolean in the ctor:
Public Sub New(boolAddButton As Boolean)
If boolAddButton Then CreateSearchButton()
End Sub
The way you have it, the backing field m_EnableSearch will always be true when the control is created. Any prop setting you do in the IDE happens after the control is created which is the only place you have it set up to create the button.
Related
My question is how to create a new form setting in vb.net language to save data Programmatically.
For example when i click button it will create the setting which it,s name is the text of the textbox1.
is this possible and how.
And is there any functions which can save data when program is closed?
You can do that through the form designer.
Go to the ApplicationSettings / PropertyBinding and click the ... button.
Then assign a New setting to the Text property by clicking here:
.Net takes care of making the settings save automatically when the program exits. If you want to force it to save, just call My.Settings.Save()
You can create your own settings-class which inherits ApplicationSettingsBase:
Imports System.Configuration
Public Class MyUserSettings
Inherits ApplicationSettingsBase
<UserScopedSetting()> _
<DefaultSettingValue("white")> _
Public Property BackgroundColor() As Color
Get
BackgroundColor = Me("BackgroundColor")
End Get
Set(ByVal value As Color)
Me("BackgroundColor") = value
End Set
End Property
End Class
Save the settings:
Dim Mus As New MyUserSettings
Mus.BackgroundColor = Color.AliceBlue
Mus.Save()
Load the settings:
Dim Mus As New MyUserSettings
MessageBox.Show(Mus.BackgroundColor.ToString)
Source: MSDN
One of the way in VBA is a standard functions to save setting to Registry:
Call SaveSetting(appName, Section, Key, Value)
Value = GetSetting(appName, Section, Key)
Just put them in form constructor and form destructor:
Private Sub UserForm_Initialize()
...
end sub
Private Sub UserForm_Terminate()
...
end sub
So I am building a form based application, and I am running into an issue with passing data between forms. I have a combo box that, based on selection, triggers a new form to open with several buttons to pick from. Once you select a button, the form closes, but I can't get the selection to be carried over to the original form.
basic idea of the code is like this
Public Class frmMain
Public intStore As integer
Private Sub cboSample_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cboSample.SelectedIndexChanged
Dim selection as Integer
selection = cboSample.SelectedIndex
If selection = -1 Then
Else
Select Case selection
Case 0
frmOne.Show()
Case 1
frmTwo.Show()
End Select
End If
End Sub
End Class
Here is a sample of the second form code
Public Class frmOne
Public storage As varStorage
Private Sub btn_Clicked(sender As Object, e As EventArgs) Handles btn.Clicked
storage = New varStorage With {.datastore = 1}
Me.Close()
End Sub
End Class
frmTwo is pretty much the same but handles more options
The Class I created looks like this
Public Class varStorage
Public _dataStore As Integer
Public Property dataStore() As Integer
Get
Return _dataStore
End Get
Set (value As Integer)
_dataStore = value
End Set
End Property
End Class
as I said, the issue comes from the point of the form being called, and the form closing, the variable data is not being saved. I am almost certain I am missing some code somewhere, but not sure where. any help would be greatly appreciated.
Rather than using Show() to open another form, using ShowDialog() will open the form modally. The form will behave like a MessageBox. It will wait for you to respond to, and close, this form before returning to your main form. We can obtain a value from this modal-form, safe in the knowledge that the form has been closed (and so the value we have obtained will not be changed).
The other way is to make a Public Property of the form. then you can create Get and Set methods to have access to your form objects
Public Class yourFormClass
Public Property Note As String
Get
Return txtNote.Text
End Get
Set(value As String)
End Set
End Property
End Class
and Then you can use it like
dialog = New yourFormClass()
someOtherTextbox.Text = dialog.Note
I know I can add a DateTimePicker to my MenuStrip with the following lines
Dim dp = New ToolStripControlHost(New DateTimePicker)
MenuStrip1.Items.Add(dp)
But I can't figure out how to add a DateTimePicker to the MenuStrip at designtime. What's the trick behind it? I have been trying and searching for like an hour and I am about to give up even though I know there has to be a way!
TL;DR
How do I add a DateTimePicker to my MenuStrip at design-time?
Alternatively we can add it to a ToolStrip instead.
You are close to a solution in using the ToolStripControlHost, but you will need to derive from that class as shown in the linked-to example. The frustrating thing with that example is that it does not decorate the derived class with the System.Windows.Forms.Design.ToolStripItemDesignerAvailabilityAttribute to make it available on the design surface.
The following is a minimalist implementation to get a working example. You may need to override the automatic sizing to suit your needs/wants for the control. The implementation overrides the Text property to prevent designer from assigning invalid text to the underlying DateTimerPicker control.
<System.Windows.Forms.Design.ToolStripItemDesignerAvailability(
System.Windows.Forms.Design.ToolStripItemDesignerAvailability.ToolStrip _
Or System.Windows.Forms.Design.ToolStripItemDesignerAvailability.StatusStrip _
Or System.Windows.Forms.Design.ToolStripItemDesignerAvailability.MenuStrip)> _
Public Class TSDatePicker : Inherits ToolStripControlHost
Public Sub New()
MyBase.New(New System.Windows.Forms.DateTimePicker())
End Sub
Public ReadOnly Property ExposedControl() As DateTimePicker
Get
Return CType(Control, DateTimePicker)
End Get
End Property
<Browsable(False), EditorBrowsable(EditorBrowsableState.Advanced), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)>
Public Overrides Property Text As String
Get
Return ExposedControl.Text
End Get
Set(value As String)
' verify valid date
Dim dt As DateTime
If DateTime.TryParse(value, dt) Then
ExposedControl.Text = value
End If
End Set
End Property
End Class
Was going to add as a comment but I trust it justifies an answer.
The only way I have succeeded in this is to add one at design time (to the form) and set Visible to False and use the menu item to set Visible to True (may also need to set the position and/or bring it to the front).
You do need to manually handle setting Visible to False again.
I have a set of controls on my form and i want to enable/disable some of them. what is the best way?
Hint: I don't want to change all controls available in my form.
If your meaning from "enable/disable" is "preventing user from changing them", then you can do this:
THE_NAME_OF_CONTROL.Enabled = False 'Disable a control with THE_NAME_OF_CONTROL Name
And
THE_NAME_OF_CONTROL.Enabled = True 'Enable a control with THE_NAME_OF_CONTROL Name
Or you can put all of your controls in a "Group Box" and disable/enable whole group box.
If you want change controls outside of form, then create a public property or method which do it, instead of making controls public
Public Class MyForm
Inherits Form
Private _MyCheckBoxControl As CheckBox
Private _MyTextBoxControl As TextBox
Private _IsGroupOfControlsEnabled As Boolean
Public Property IsGroupOfControlsEnabled As Boolean
Get
Return _IsGroupOfControlsEnabled As Boolean
End Get
Set (value As Boolean)
_IsGroupOfControlsEnabled = value
'Update controls
_MyCheckBoxControl.Enabled = _IsGroupOfControlsEnabled
_MyTextBoxControl.Enabled = _IsGroupOfControlsEnabled
End Set
End Class
Currently in VB.NET I have two public subs like so:
Public Sub addmember1()
'Stuff
End Sub
Public Sub furtherinfo1()
'suff
End Sub
I haven't included the code where "'stuff" is as it is very long and is exactly the same in each sub, however the underlying the principle remains the same.
A certain sub is ran depending on a boolean value. like so...
If add_member = True Then
addmember1()
ElseIf add_member = False Then
furtherinfo1()
End If
How would I use one function to carry out the same procedure as above? (my current solution works but involves repeating the same section of code twice )
I tried the following however was unsuccessful
Public Function forms(ByVal frm As Windows.Forms.Form)
'stuff
End Function
and then run the function like so... (addmember and furtherinfo are the two forms I am working with)
If add_member = True Then
forms(addmember)
ElseIf add_member = False Then
forms(furtherinfo)
End If
here is the paste bin of all the code for context it's in modual and I want to use it for writing information to a word document. Lines 20-71, 76-128, 160-164 is what I am on about.
http://pastebin.com/xWD0RBuh
You can pass the form object to a Sub() in a module as below
Module Printing
Dim StrToAdd As String
Sub MySub(ByVal frm As Form)
'The first line is your code
StrToAdd = "Firstname: " & addmember.txtName.Text
'Change it to as below using frm.Controls("controlname").Text
StrToAdd = "Firstname: " & frm.Controls("txtName").Text
End Sub
End Module
After looking at your code at http://pastebin.com/xWD0RBuh it seems you have a global module with multiple sub routines. Each sub routine has references to controls (such as text boxes) on a form instance. This means each global module sub routine needs to have access to this form instance.
You have only copied in part of the application - the global module, but you have not copied in the form definition. I presume you have a form called addmember, but I don't see it in the example - aside from references in the global module.
Not sure how you use the sub routines - probably a click of a button. If it were me, I would create a class object with properties that hold the data to pass around - one property for each control on the form you want to print. On the click of the button, I would create an instance of the class and copy the values from the form controls into the class properties. I would then pass the instance of the class to the sub routines, and I would alter the sub routines to refer to an instance of the class instead of an instance of a form. That would provide a level abstraction between the form (UI) and the behavior (the sub routines that print). I may even go "crazy" and use an interface.
Does your code compile as-is?
The Problem is that your two Forms are two different classes. Even though you named your controls
the same, you can't just access them simply by frm.txtUsername.
What you could do is iterate through all controls of each form und find them by name:
Public Sub DoStuff(frm As Form)
Dim txtUsername As TextBox = GetControlByName(frm, "txtUsername")
txtUsername.Text = "Hello World"
End Sub
Private Function GetControlByName(container As Control, name As String) As Control
Dim retVal As Control = Nothing
If Not TryGetControlByName(container, name, retVal) Then Throw New ApplicationException("control not found")
Return retVal
End Function
Private Function TryGetControlByName(container As Control, name As String, ByRef ctl As Control) As Boolean
For Each item As Control In container.Controls
If item.Name = name Then
ctl = item
Return True
End If
'If item is a Container (like GroupBox, Panel) check its children
If TryGetControlByName(item, name, ctl) Then Return True
Next
Return False
End Function
If you want to get really fancy you could define a Class with the common Controls and fill them via a little
bit of reflection magic. Though this might be overkill:
Public Sub DoStuff2(frm As Form)
Dim wrapper As New CommonForm(frm)
wrapper.txtUsername.Text = "Hello Wolrd"
End Sub
Public Class CommonForm
Public Property txtUsername As TextBox
Public Property txtFoo As TextBox
Public Property txtBar As TextBox
'Add more Controls here...
Public Sub New(frm As Form)
For Each item In Me.GetType().GetProperties()
Dim value = GetControlByName(frm, item.Name)
item.SetValue(Me, value, Nothing)
Next
End Sub
Private Function GetControlByName(container As Control, name As String) As Control
Dim retVal As Control = Nothing
If Not TryGetControlByName(container, name, retVal) Then Throw New ApplicationException("control not found")
Return retVal
End Function
Private Function TryGetControlByName(container As Control, name As String, ByRef ctl As Control) As Boolean
For Each item As Control In container.Controls
If item.Name = name Then
ctl = item
Return True
End If
'If item is a Container (like GroupBox, Panel) check its children
If TryGetControlByName(item, name, ctl) Then Return True
Next
Return False
End Function
End Class