Rewriting the Settings in Windows Forms - vb.net

I have set the name of my Form text in the application settings and I need to rewrite it. Is it possible as it is showing me that it is only a readonly.
I know that we can simply change it by using me.text=""
But I have a problem in my application as I have the below code where On every time the form loads it is erasing the text.
Protected Overrides Sub OnLayout(ByVal e As System.Windows.Forms.LayoutEventArgs)
MyBase.OnLayout(e)
'Me.Text = CStr(Val(Me.Text) + 1)
FillList()
MyBase.OnLayout(e)
If FontColor.Items.Count = 0 Then
FontColor.Items.AddRange(Known_Color)
FontColor.MaxDropDownItems = 20
End If
MyBase.OnLayout(e)
If OutlineColor.Items.Count = 0 Then
OutlineColor.Items.AddRange(Known_Color)
OutlineColor.MaxDropDownItems = 20
End If
MyBase.OnLayout(e)
If BorderColor.Items.Count = 0 Then
BorderColor.Items.AddRange(Known_Color)
BorderColor.MaxDropDownItems = 20
End If
MyBase.OnLayout(e)
If BackgroundColor.Items.Count = 0 Then
BackgroundColor.Items.AddRange(Known_Color)
BackgroundColor.MaxDropDownItems = 20
End If
End Sub
Is there any workaround to do this?

MyBase.OnLayout(e)
most probably this is where your mistake is.
You are setting the text and then you are calling the base class OnLayout event which is probably causing the text to get back to default value. If you want to change something do it after you call the case class event handler.
If you are just trying to change the text of the form why not just use Form_Load event handler without calling the base event handler.

To answer your question about your Form Text in your application settings being readonly. Look at this MSDN Page.
From above Link:
There are two types of application settings, based on scope:
Application-scoped settings can be used for information such as a URL for a Web service or a database connection string. These values
are associated with the application. Therefore, users cannot change
them at run time.
User-scoped settings can be used for information such as persisting the last position of a form or a font preference. Users can change
these values at run time.
You can change the type of a setting by using the Scope property.
In short if your application setting is application scoped you can not it change at runtime, you have to use a user scoped setting or roll your own storage.
Edit: to add to #Bojan 's answer. The OnLayout event will be fired during the InitializeComponent() method and everytime you resize the form or change the size of a control. I would personally move your initialization to the Form_Load event or to New().
i.e.
Public Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
Me.Text = "Hello World"
End Sub

Related

Pass value from form to button text vb.net

I am learning vb.net and I'm having issues searching for what I need. I want to create a button that is "re-usable" throughout my application without needing to write code for each instance. So, what I would like to start with is take a variable in a form, example, public integer value and when this value changes I want to write to the text of a button. I know I can easily do this by writing code in the form btn_xxx.text = variable, but what if I have several buttons and each button looks at the same variable? Currently what I do is create a component which inherits a button and have a timer that on tick will look at the variable and write to the text. I'm sure there is a better way. Can anyone point me in the right direction? I know part of my problem is I don't know the nomenclature on what things are called, so hopefully I asked my question without too much confusion.
I saw this, https://www.daniweb.com/programming/software-development/threads/124842/detect-variable-change, but I don't see how to adapt that to my situation.
Here is what I have:
Private WithEvents Active_Alarm As New Nav_Active_Alarm
Then inside of a sub that calculates the count:
Active_Alarm.Count = CInt(dt_Active_Alarms.Rows.Count)
The user control:
Public Class Nav_Active_Alarm
Private mActive_Alarm_Count As Integer
Public Event Active_Alarm_Count_Changed(ByVal mvalue As Integer)
Public Property Count() As Integer
Get
Count = mActive_Alarm_Count
End Get
Set(ByVal value As Integer)
mActive_Alarm_Count = value
If Not Me.DesignMode Then
RaiseEvent Active_Alarm_Count_Changed(mActive_Alarm_Count)
test()
End If
End Set
End Property
Private Sub test()
If Not Me.DesignMode Then
If mActive_Alarm_Count = 0 Then
Me.btn_Goto_Active_Alarm.Image = My.Resources.Alarm_Clock_Static
'console or msgbox will work but updating the image will not
Else
Me.btn_Goto_Active_Alarm.Image = My.Resources.Alarm_Clock_Animation
'console or msgbox will work but updating the image will not
End If
End If
End Sub
End Class
If I write to console or add a msgbox I will see the event working. But, the image will not change. If I call the test sub from a timer it will work. Why won't the button update (by the way, I did try refresh and update in the code)?
Observer pattern is what you probably looking for.
This is quick and dirty.
Create a class to hold the variable value. Add a method that adds a button instance to a list.
Then a button that needs to know about the variable calls the register method.
When the value of the variable changes, it iterates through the list of buttons and sets the Text property of each one.
You might have jumped in a bit too deep too quick here. Google Custom data binding in .net, there's loads of built in stuff you can use. Though do it yourself is a good exercise.
A simple method to do this might be:
Create a form level list to hold the buttons you are interested in
Add the buttons you are interested in, into the list (maybe in form load or some other place where you have initialization code)
Create a private property in your form with a backing variable to hold the value you want to have applied to the buttons. In the setter portion spin through the list and set each buttons text.
Dim lstButtons As New List(Of Button)
Sub SetupButtons()
'call from form load or other init code
lstButtons.Add(btnPopulate)
lstButtons.Add(btnPopulate)
End Sub
Private _buttonText As String
Private Property ButtonText As String
Get
Return _buttonText
End Get
Set(value As String)
_buttonText = value
For Each b As Button In lstButtons
b.Text = value
Next
End Set
End Property
When you set the property - which now acts as your variable - it will update all of your textboxes for you.
I realize you mentioned without having to write code - but something has to tie things together. Even if you used the observer pattern (which is an elegant solution for this - so props to those who suggested it) you'd probably end up creating a class to hold the property and have that class implement the INotifyPropertyChanged from System.ComponentModel, and then you'd also have to have each button have a databinding for its text property to the property in the object of your class. There isn't really a way (that I can think of) to get around having to write some code for each form you do this in (though the class part you'd only have to write once of course).

VB.NET Call Sub of another form

I know, that there are many questions related to this, but still I cannot find a workable solution.
Usually, it would work like this: A form creates an instance of another form in it's container like this:
Dim PolInstIn As New SubForm1
Private Sub LoadDetail()
PolInstIn.TopLevel = False
PolInstIn.Name = "Sub From"
PolInstIn.FormBorderStyle = Windows.Forms.FormBorderStyle.None
PolInstIn.Dock = DockStyle.Fill
Me.GroupBox6.Controls.Add(PolInstIn)
PolInstIn.Show()
End Sub
Then it's easy to call a Public Sub from the sub form like this:
Call PolInstIn.MyPublicSubInSubForm1()
However, this doesn't work for me in this case. When I run MyPublicSubInSubForm1() it doesn't throw any error, but does no action. If I write a value to SubForm1 textbox and read it back, it reads, but I don't see it on the screen, so I suspect it is written to some other accidental instance.
I suspect it is because my parent form is also an instance of an form created in very similar way like SubForm1. Basically the ParentForm is a form loaded into tabPage and SubForm1 is a module loaded into ParentForm. It can exist in many copies (tabs).
Could you point to any simple solutions?
Regards,
Libor
I see this question got a lot of views, so here is an answer.
1) No visual response of child form (only results) - this could have happened if I created more then 1 instances of the form. The example is just an example, but if one use it (accidentally) this way, it may result in new definition of a child form every time (and consequent symptoms like the ones described). In practice, I split form loading from loading data into to the form (done by a public sub in that form).
2) If you want also a back reference (to i.e. parent grid form), define a Public ParentFormGrid as GridName (note ParentForm is a reserved name) and on loading a child form, set
PollInstIn.ParentFormGrid = Me
This way you can alway asccess the parent form, i.e. reload the grid when you save changes on a line edited in child form.
make Private Sub LoadDetail() to a public :
Public Sub LoadDetail()
It work on my project. Hopely its what you want
Dim PolInstIn As New SubForm1
Private Sub LoadDetail()
PolInstIn.Name = "Sub From"
PolInstIn.Show()
PolInstIn.TopLevel = False
PolInstIn.FormBorderStyle = Windows.Forms.FormBorderStyle.None
PolInstIn.Dock = DockStyle.Fill
PolInstIn.Update()
PolInstIn.Refresh()
Me.GroupBox6.Controls.Add(PolInstIn)
End Sub

Control's Enabled appearance at design time?

I defined a custom button class, which sets background color when button is enabled/disabled.
Enabled appearance at runtime (A):
Disabled appearance at runtime (B):
Design time appearance is always (A), regardless of the value of Enabled property.
I would like my control to appear in designer exactly the way it would appear at run time. Is it possible and, if so, how can do it?
Here is what I tried (only relevant parts of the code):
Public Class StyledButton : Inherits Button
Private p_fEnabled As Boolean
<DefaultValue(True)>
Public Shadows Property Enabled As Boolean
Get
Return p_fEnabled
End Get
Set(value As Boolean)
p_fEnabled = value
MyBase.Enabled = value
UpdateVisualStyle()
End Set
End Property
Private Sub UpdateVisualStyle()
If Me.Enabled Then
'set enabled appearance
Else
'set disabled appearance
End If
End Sub
End Class
I'll explain why it behaves this way. A control behaves a lot at design time as it does at runtime. It provides the strong WYSIWYG support in the Winforms designer. But certain properties are very awkward at design time, you would not actually want the Visible property to take effect for example. Pretty important that the control remains visible even though you set Visible to False in the Properties Window.
This is a core role of the designer for a control. It intercepts these kind of difficult properties and emulates them. Showing the intended value in the property grid but not actually passing them on to the control's property setter.
The Enabled property fits this category. If it weren't intercepted then the control couldn't be selected anymore. Other ones are ContextMenu, AllowDrop, Location for UserControl and Form, etcetera. Your Shadows replacement doesn't fool the designer, it uses Reflection to find properties by name. So your property doesn't have any effect, your property setter simply never gets called.
You can only truly get this by overriding OnPaint() for the control so you can display a different color at design time. And a custom designer to poke it. A significant hang-up however is that it isn't simple to replace the renderer for the button, the one that implements the OnPaint() method. Microsoft decided to make the renderers internal, you can't override them.
Way too much trouble, I recommend you pass this up.
The shadowed property does work as designed at runtime, just not in the IDE. You would not want to loose controls which are Visible = False, and you would want to drill into Button events even when Enabled = False. Since the IDE has no intention of drawing a disabled control, there is no reason for it to invoke Invalidate when you change the property.
Since it works at runtime, trick it in the designer to use another property which looks like the original:
<Browsable(False), DebuggerBrowsable(DebuggerBrowsableState.Never),
EditorBrowsable(False)>
Public Shadows Property Enabled As Boolean
Get
Return neoEnabled
End Get
Set(value As Boolean)
neoEnabled = value
End Set
End Property
A new property, with the right name for the IDE.
<DisplayName("Enabled")>
Public Property neoEnabled As Boolean
Get
Return p_fEnabled
End Get
Set(value As Boolean)
p_fEnabled = value
UpdateVisualStyle()
MyBase.Enabled = p_fEnabled
End Set
End Property
Sadly, both Enabled and neoEnabled will be offered by Intellisense in code, but since they both do the same thing, its not a big deal. test code:
Private Sub UpdateVisualStyle()
If p_fEnabled Then
' other interesting stuff
MyBase.BackColor = Color.Lime
Else
MyBase.BackColor = Color.LightGray
End If
MyBase.Invalidate()
End Sub
You have probably wrestled with it more that I, and come up with a cleaner implementation.
This persists the BackColor associated with neoEnabled state:
'
'StyledButton1
'
Me.StyledButton1.BackColor = System.Drawing.Color.LightGray
Me.StyledButton1.Enabled = False
Me.StyledButton1.neoEnabled = False
versus
Me.StyledButton1.BackColor = System.Drawing.Color.Lime
Me.StyledButton1.Enabled = False
Me.StyledButton1.neoEnabled = True

How to access to the properties of an UserControl from code side?

make my own UserControl and I can aggregate new TabPages to a TabControl and then, inside of then TabPage, I add my own UserControl using the following code.
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim TabX As New Windows.Forms.TabPage("Tab " & TabCount.ToString) '(ConfiguracionTabPage)
Dim MyControl As New ClientesEmpresa
MyControl.Name = "Control" & TabCount.ToString
If ClientesTabControl.TabPages.Count = 10 Then
ClientesTabControl.TabPages.RemoveAt(9)
End If
TabX.Controls.Add(MyControl)
TabX.Name = "Tab" & TabCount.ToString
TabX.Text = "Tab" & TabCount.ToString
MyControl.TitularLbl.Text = "Coca Cola"
Me.ClientesTabControl.TabPages.Insert(0, TabX)
Me.ClientesTabControl.SelectedIndex = 0
TabCount += 1
End Sub
My user control have several Labels, TextBox and TabPages(inside of a TabControl).
Now I want to change some properties dynamically from the source code, but I don't know how to access them.
The most similar theme that I found is this How to Acces of an User control in c#, but, as the title says, is in C#, how I can do it in VB.NET?
Sorry, I just notice that the Enter key post the comment. :(
Thanks for your feedback, I understand what are you saying but I missing something in the middle.
When I create the control in running time in the above code I can access easily to the properties of the created object, in this case my UserControl, but I don't understand how to reach the properties of a particular instance of that control from outside of Button_Click; ie. another button_click event(second button)
I was thinking to use something like
Dim ControlList As Windows.Forms.Control() = Me.ClientesTabControl.TabPages(0).Controls.Find("ModeloLbl", True)
or
ClientesTabControl.TabPages(0).Controls.OfType(Of AlarmasVehiculo)()
But I'm stuck here.
------------------------------------- 3th post ---------------
Thanks Steve, I was resolved using "Control.Find" and a For Each but your solution is easier.
There's any way to get the name of the selected tab or I must to create an Array when I create the New TabPage?, the idea is to update the text of the controls inside of the selected tab only when is selected by the user or every 5 seconds but just the in selected one.
Thanks.
To borrow M4N's answer from the C# question, and translate it to VB:
Cleanest way is to expose the desired properties as properties of your usercontrol, e.g:
Public Class MyUserControl
' expose the Text of the richtext control (read-only)
Public ReadOnly Property TextOfRichTextBox As String
Get
Return richTextBox.Text
End Get
End Property
' expose the Checked Property of a checkbox (read/write)
Public Property CheckBoxProperty As Boolean
Get
Return checkBox.Checked
End Get
Set (value As Boolean)
checkBox.Checked = value
End Set
End Property
'...
End Class
In this way you can control which properties you want to expose and whether they should be read/write or read-only. (of course you should use better names for the properties, depending on their meaning).
Another advantage of this approach is that it hides the internal implementation of your user control. Should you ever want to exchange your richtext control with a different one, you won't break the callers/users of your control.
To answer your second question, if you need to access your dynamically created controls, you can do so easily using their names, for instance:
Dim c As ClientesEmpresa= CType(Me.ClientesTabControl.TabPages("Tab1").Controls("Control1"), ClientesEmpresa)
c.CheckBoxProperty = True

Properties not passing to from in VB.NET custom control

I have a custom VB.NET control that I created that is working correctly in one program but not in another. The control has one button and one form. The form displays some data based on the settings in the control.
This is the use in both test projects:
With Me.MyControl1
'.Connection = gConn
.Server = "servername"
.DBName = "dbname"
.TableName = "table"
.FieldString = "list of fields"
.ReturnColumn = 0
.AllowMultiSelect = True
End With
This is how I am passing the settings to my form.
...this form is a part of the control
Public Sub New(ByVal cmsl As MyCustomControl)
' This call is required by the Windows Form Designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
Me.Connection = cmsl.Connection
Me.ConnectionString = cmsl.ConnectionString
Me.Server = cmsl.Server
Me.DBname = cmsl.DBName
Me.TableName = cmsl.TableName
Me.FieldString = cmsl.FieldString
Me.FilterString = cmsl.FilterString
Me.AllowMultiSelect = cmsl.AllowMultiSelect
Me.AutoPopulate = cmsl.AutoPopulate
Me.ReturnColumn = cmsl.ReturnColumn
Me.SelectTop = cmsl.SelectTop
End Sub
In TestProject1 - the control is working as expected
In TestProject2 - the control is not sending any of the settings I set to the form
My control works fine when I debug with the UserControl TestContainer.
I am using VB.NET on VS2005.
This is all done on the same machine. Why would this work in one project and not another?
Seems like a reference error. please show us how the UserControl is integrated. The problem must come from there.
And are you talking about a custom control, or a UserControl ? (Not the same thing for me)
Try some breakpoints in the props, and also, try checking the references :). You might be working with a second usercontrol overlapping on the first one or something like that :).
In winforms the Designer sometimes goes weird.