DatetimePicker and other Controls in MenuStrip - vb.net

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.

Related

Visual Basic How can I set the value of an variable when switching forms

Basically what the title says
I have several Buttons which redirect me to a 2nd form using me.Hide and Form2.show
However, what I would like is that when Button1 is clicked, x=1 in the recently opened form. When Button2 is clicked -> x=2, etc.
Does anyone know how to do this?
An alternative method is to pass a variable into the constructor of a form, such as:
Public Class Form2
Dim_value As Integer
Public Sub New(ByVal value As Integer)
_value = value
End Sub
End Class
Which you would call like this:
Dim f As New Form2(12345)
f.Show()
You can then use _value (or whatever you want to call it) throughout Form2.
The difference here is this is that your value cannot be changed by any other form once Form2 is instantiated; this may be an advantage or disadvantage depending on your requirements but it does keep things nicely separated and easier to maintain. You could also make _value a read-only property which will let others forms read the value but not set (change) it.
There are several ways you can do this, but for the sake of simplicity I suggest that you define and use a public method in Form2. Here's a small example which you can use for inspiration:
Public Class Form2
Private variableX As Integer = 0
Public Sub SetVariableX(value As Integer)
variableX = value
End Sub
End Class
and when you reveal Form2:
Form2.show
Form2.SetVariableX(9999)
Have fun.

Creating form setting in VB Programmatically

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

DataBinding - Toggle Enabled Based on Input

I'm using Visual Basic .NET developing a windows form application and I want to toggle the enabled property of a Button based on if there is anything in a TextBox. I attempted to setup the DataBinding using the following:
ButtonBack.DataBindings.Add("Enabled", Me.TextBoxValue, "TextLength")
This successfully disables the Button, but whenever anything is typed in the TextBox, the Button never gets enabled. I would much rather do this via DataBindings if possible as opposed to setting the Enabled property manually in the TextChanged or Validating event of the TextBox.
I usually implement this kind of custom property binding by "subclassing" the control that requires the "new" property, as in your case, TextBox needs an HasLength Boolean property (or whatever name you want to give it).
Here's MyTextBox.vb:
Public Class MyTextBox
Inherits TextBox
Public Event HasLengthChanged As EventHandler
Private _HasLength As Boolean
Public Property HasLength() As Boolean
Get
Return _HasLength
End Get
Set(ByVal value As Boolean)
If value <> _HasLength Then
_HasLength = value
OnHasLengthChanged()
End If
End Set
End Property
Public Sub New()
_HasLength = False
End Sub
Protected Sub OnHasLengthChanged()
RaiseEvent HasLengthChanged(Me, New EventArgs())
End Sub
Protected Overrides Sub OnTextChanged(e As EventArgs)
MyBase.OnTextChanged(e)
HasLength = Not (String.IsNullOrEmpty(Text))
End Sub
End Class
And here's Form1.vb:
Public Class Form1
Protected Overrides Sub OnLoad(e As EventArgs)
MyBase.OnLoad(e)
ButtonBack.DataBindings.Add("Enabled", Me.MyTextBox1, "HasLength", True, DataSourceUpdateMode.OnPropertyChanged)
End Sub
End Class
Of course, you need a Form with a MyTextBox instance and a regular Button instance.
With this method, as soon as the user types something in the textbox, the button becomes enabled, and as soon as the textbox becomes empty, the button is disabled. Please note that I used the DataSourceUpdateMode.OnPropertyChanged so that the update is done as you type, and not only when the textbox loses focus.
EDIT: I thought I'd add a bit of background about the PropertyNameChanged pattern in .NET.
There are different ways to let observers know that a property has changed on an object, and most of the time we use the INotifyPropertyChanged interface, but for controls, the recommended method is still to use the PropertyNameChanged pattern, which is recognized by .NET, and thus the Binding object can do its job and know when the desired property has changed.
INotifyPropertyChanged is recommended for data objects that participate in binding.
By the way, the PropertyNameChanged works in both Windows Forms and WPF.
As reference MSDN:
https://learn.microsoft.com/en-us/dotnet/framework/winforms/how-to-apply-the-propertynamechanged-pattern
EDIT 2: I'm a C# programmer, and I've done my best to apply the residual knowledge that I have of VB.NET. Any error is really the result of my being too rusty in VB. Sorry for any inconvenience, but I can assure you that the code runs just fine here.
As #LarsTech stated in his comment, you need to use a property of the TextBox Class that raises changed notifications. The Text property is the appropriate one to use.
Your request to do this strictly via the binding is possible, but it will still involve using an event handler. As such, I don't see much value in this approach over handling the TextBoxValue.TextChanged event.
One way of doing this is to use the Binding.Format Event to convert the string of the Text Property to a boolean based on if it contains any characters.
Dim b As Binding = ButtonBack.DataBindings.Add("Enabled", Me.TextBoxValue, "Text", True, DataSourceUpdateMode.OnPropertyChanged)
AddHandler b.Format, Sub(s As Object, args As ConvertEventArgs) args.Value = Not String.IsNullOrEmpty(CStr(args.Value))
Because the binding is two way, if your code changes the ButtonBack.Enabled property, it will send the string representation of the property back to TextBoxValue and its text will read either "True" or "False". This would not be a desirable consequence. To rectify this possibility, the Binding.Parse Event will need to be handled.
AddHandler b.Parse, Sub(s As Object, args As ConvertEventArgs) args.Value = Me.TextBoxValue.Text

Unable To Get Public Property To Work In Custom Class

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.

Get textbox value in user control

I'm anand. I have a problem about how to get text value in textbox in user control. I make a small application. I use Form1 as main form, and in the form I put one panel. In panel I will put custom user control that contain textbox. Now, I want to get the text on the textbox in user control and show it in the msgbox. Can anyone help me to fix this problem please?
As André Leal said in the comments. If you define a public property in your user control you will be able to access the value.
Public Property textboxValue as String
Get
Return MyTextBox.text
End Get
Set(value as String)
MyTextBox.text = value
End Set
End Property
Then you can access it using code like this.
YourUserControl.textboxValue
If you don't need to edit the value of the textbox you can make the property readonly as follows.
Public ReadOnly Property textboxValue as String
Get
Return MyTextBox.text
End Get
End Property