Hightower Posted March 23, 2010 Posted March 23, 2010 I have a dynamic array of textboxes (lets say 3 for this example though). I want to iterate through each and set the backColor property. I'm trying: Dim value as TextBox For Each value In txtMain 'txtMain is the array of TextBoxes value.BackColor = My.Settings.frmMainBackColour Next I have checked my settings and a default BackColour value exists so this is the cause of the following error at run-time: Object reference not set to an instance of an object I think I've done this before (like yesterday haha) but my mind is on a go slow and I can't remember how I might have overcome it. Any ideas?
sister_annex Posted March 23, 2010 Posted March 23, 2010 If i think right shouldn't it be Dim value as New TextBox just a thought Mark
Hightower Posted March 23, 2010 Author Posted March 23, 2010 If i think right shouldn't it be Dim value as New TextBox just a thought Mark Didn't make a difference
sister_annex Posted March 23, 2010 Posted March 23, 2010 hmmm, do you have any more code so I put it in to context? Cheers
Jamo Posted March 23, 2010 Posted March 23, 2010 (edited) Shouldn't you use one of the containers in VB for that rather than an array? I believe arrays are fixed length in VB so if all of the values aren't populated you will see that error Generic Lists in VB.NET - ForEach, FindAll, and Sort Generic Methods That way you can grow and shrink the list as required. Dim listOfTextboxes As List(Of Textbox) listOfTextboxes.Add(textbox1); listOfTextboxes.Add(textbox2); listOfTextboxes.Add(textbox3); listOfTextboxes.Add(textbox4); Dim value As Textbox For Each value In listOfTextboxes value.etc etc Next Edited March 23, 2010 by Jamo
RinSewand Posted March 23, 2010 Posted March 23, 2010 The Closest thing to a VB6 control array in VB.NET - CodeProject That any good?
LosOjos Posted March 23, 2010 Posted March 23, 2010 It might be that you haven't specified 'Next value' Alternatively, try: Dim x as long For x=LBound(txtMain) to UBound(txtMain) txtMain(x).BackColor = My.Settings.frmMainBackColour Next x
Hightower Posted March 23, 2010 Author Posted March 23, 2010 It might be that you haven't specified 'Next value' Alternatively, try: Dim x as long For x=LBound(txtMain) to UBound(txtMain) txtMain(x).BackColor = My.Settings.frmMainBackColour Next x It wasn't the value bit. Trying the other now...
Hightower Posted March 23, 2010 Author Posted March 23, 2010 Dim x as long For x=LBound(txtMain) to UBound(txtMain) txtMain(x).BackColor = My.Settings.frmMainBackColour Next x Same error
LosOjos Posted March 23, 2010 Posted March 23, 2010 It wasn't the value bit. Trying the other now... Same error Hmmm I like a challenge, I'm gonna try and recreate this myself and see if I can solve it, I'll let you know if I come up with a solution... 1
Jamo Posted March 23, 2010 Posted March 23, 2010 How are you creating this dynamic array? As far as I know VB doesn't have the ability to have dynamic arrays with out using containers such as the one I suggested without keeping track of array bounds etc which gets very messy.
Hightower Posted March 23, 2010 Author Posted March 23, 2010 Dim txtMain(1) as TextBox Dim iNumTxt as Integer = 3 ReDim txtMain(iNumTxt) iNumTxt = 5 ReDim txtMain(iNumTxt) Then to create each text box I need: iNumTxt += 1 ReDim txtMain(iNumTxt) txtMain(variableHoldingNumberOfLatestAddedBox).Name = "GIVE IT A NAME" txtMain(...).Text = "GIVE IT SOME TEXT" txtMain(...).Properties = "ADD WHATEVER PROPERTIES YOU WANT HERE" Me.Controls.Add(txtMain) This method works great so far, with the exception being this little stop sign I've come across. Will be some way around it though.
Jamo Posted March 23, 2010 Posted March 23, 2010 (edited) The List example I gave just now does what you want just wrapped up in an STL container style format without the extra vars. Forget that last bit i just deleted I am thinking of C++ vectors! You need to use the List.Item(0) etc to access the items. Edited March 23, 2010 by Jamo VB is not C++..... :p
sister_annex Posted March 23, 2010 Posted March 23, 2010 Dim txtMain(1) as TextBox Dim iNumTxt as Integer = 3 ReDim txtMain(iNumTxt) iNumTxt = 5 ReDim txtMain(iNumTxt) Then to create each text box I need: iNumTxt += 1 ReDim txtMain(iNumTxt) txtMain(variableHoldingNumberOfLatestAddedBox).Name = "GIVE IT A NAME" txtMain(...).Text = "GIVE IT SOME TEXT" txtMain(...).Properties = "ADD WHATEVER PROPERTIES YOU WANT HERE" Me.Controls.Add(txtMain) This method works great so far, with the exception being this little stop sign I've come across. Will be some way around it though. why not, for x as integer = 0 to inumtxt 'or your maximum number dim t as new textbox with t .name = "name" .text = "text" .properties = "etc" end with me.controls.add(t) next i'm sure i have done it like that before Mark
Jamo Posted March 23, 2010 Posted March 23, 2010 We need to hold onto the references for later use in changing the textbox colour basically.
LosOjos Posted March 23, 2010 Posted March 23, 2010 (edited) I've just tested your code and I think the problem is with the line: value.BackColor = My.Settings.frmMainBackColour If you set it to a system constant color (e.g. 'Color.AliceBlue') then it works, so something seems to be wrong with the way you're accessing settings. If you're just setting their background colour to that of the main form, couldn't you just use this instead: If this routine is outside of the code for frmMain, it would be: value.BackColor = frmMain.BackColour If it's within the code for frmMain, you use instead: value.BackColor = Me.BackColour EDIT: Just tried adding a setting named the same as yours myself and using that worked fine, is the setting you're using set to type "System.Drawing.Color"? EDIT 2: Also noticed you're not creating new instances of TextBox when you're creating them, just before the line: txtMain(variableHoldingNumberOfLatestAddedBox).Name = "GIVE IT A NAME" try adding: txtMain(variableHoldingNumberOfLatestAddedBox) = New TextBox Edited March 23, 2010 by LosOjos
Hightower Posted March 23, 2010 Author Posted March 23, 2010 I've just tested your code and I think the problem is with the line: value.BackColor = My.Settings.frmMainBackColourIf you set it to a system constant color (e.g. 'Color.AliceBlue') then it works, so something seems to be wrong with the way you're accessing settings. If you're just setting their background colour to that of the main form, couldn't you just use this instead: Just tried this: Doesn't even work for me using a system colour such as value.BackColour = Color.Red However, I can do txtMain(0).BackColor = My.Settings.frmMainBackColour which sets the colour fine, so the problem seems to be lying with the value For Each loop. Just tried adding a setting named the same as yours myself and using that worked fine, is the setting you're using set to type "System.Drawing.Color"? Yes - System.Drawing.Color in the User scope with a default value of White. Also noticed you're not creating new instances of TextBox when you're creating them, just before the line: txtMain(variableHoldingNumberOfLatestAddedBox).Name = "GIVE IT A NAME"try adding: txtMain(variableHoldingNumberOfLatestAddedBox) = New TextBox I was already doing that - just forgot to put that line in the example above. I can set the background colour when I create the textbox i.e. txtMain(...).BackColor = My.Settings.frmMainBackColour Which works perfectly when the application loads or a new textbox is created, but I need to be able to iterate through the currently in use textboxes and changes their colours so the user doesn't have to restart the application for changes to take effect.
Hightower Posted March 23, 2010 Author Posted March 23, 2010 why not, for x as integer = 0 to inumtxt 'or your maximum number dim t as new textbox with t .name = "name" .text = "text" .properties = "etc" end with me.controls.add(t) next i'm sure i have done it like that before Mark That's just a shorthand way of doing what I posted up - and that's not the part I'm having trouble with. I just posted that part up because someone asked how I was created my TextBox array. Doing it that way has no advantages apart from it's a little easier on the eye.
Hightower Posted March 23, 2010 Author Posted March 23, 2010 The List example I gave just now does what you want just wrapped up in an STL container style format without the extra vars. Looking into that now pal....
LosOjos Posted March 23, 2010 Posted March 23, 2010 (edited) This should work the way you're doing it, only other thing I can see that could be causing the error is the way you are 'Redim'-ing the txtMain array, when it comes to adding new text boxes, are you using 'Redim Preserve'? If you're not, this may well be causing the problem as you're erasing the pointers to all previous text boxes each time you create a new one in the array... EDIT: Just to prove my point (lol), this code works and seems to be doing exactly what you intend to do (it's all within the code for 'Form1'): Public Class Form1 Dim txtMain() As TextBox Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load Dim x As Long For x = 0 To 5 ReDim Preserve txtMain(0 To x) txtMain(x) = New TextBox txtMain(x).Name = "txtDyn" & x.ToString txtMain(x).Location = New Point(5, x * 25) Me.Controls.Add(txtMain(x)) Next End Sub Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim x As TextBox For Each x In txtMain x.BackColor = My.Settings.frmMainBackColor Next End Sub End Class Edited March 23, 2010 by LosOjos
Hightower Posted March 23, 2010 Author Posted March 23, 2010 Here's my code (with all the irrelevant bits taken out). Can you try it on yours to see if it works, as the stuff you said works for you isn't working for me - so I wonder if my environment is setup differently: Imports System.IO Imports System.Drawing Public Class frmMain Dim iNumTabs As Integer = 0 ' Used to keep count of the number of tabs open Dim WithEvents TabControl1 As New TabControl ' This is the tab control that is defined at runtime Dim TabNo(iNumTabs) As TabPage ' And this is an array of tab pages which is redefined as and when needed Dim txtMain(iNumTabs) As TextBox ' One text box sits on one tab, so this is similar to the above array for tab pages Dim iIndex As Integer ' This keeps track of the current selected tab Private Sub frmMain_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load ' Set the tab control properties and stick it on the form TabControl1.Anchor = AnchorStyles.Bottom Or AnchorStyles.Left Or AnchorStyles.Right Or AnchorStyles.Top TabControl1.Size = New Size(590, 321) TabControl1.Location = New Point(0, 25) Me.Controls.Add(TabControl1) ' Add a right-click menu to the tab control (used for closing tabs etc) TabControl1.ContextMenuStrip = ContextMenuTabs ' Need at least one tabbed page so load this now createTabPage() ' Update the variable to hold the index of the last selected tab (or only tab in this case) iIndex = TabControl1.SelectedIndex End Sub Public Sub createTabPage() ' Additional tab so increase variable to keep track of this iNumTabs += 1 'ReDim the tab page array and textbox array to make room for the new tab page (preserving current tab pages & textboxes ReDim Preserve TabNo(0 To iNumTabs) ReDim Preserve txtMain(0 To iNumTabs) ' Create the new tab page and stick it on the form (into the only tab control) TabNo(iNumTabs - 1) = New TabPage TabNo(iNumTabs - 1).Name = "TabPage" & iNumTabs TabNo(iNumTabs - 1).Text = "Blank File" TabControl1.Controls.Add(TabNo(iNumTabs - 1)) ' Create the new textbox and add this to the tab page that we just added txtMain(iNumTabs - 1) = New TextBox txtMain(iNumTabs - 1).Name = "txtMain" txtMain(iNumTabs - 1).Dock = DockStyle.Fill txtMain(iNumTabs - 1).Multiline = True txtMain(iNumTabs - 1).ScrollBars = ScrollBars.Vertical txtMain(iNumTabs - 1).Font = New Font("Courier New", 10, FontStyle.Regular) txtMain(iNumTabs - 1).ForeColor = My.Settings.frmMainForeColour txtMain(iNumTabs - 1).BackColor = My.Settings.frmMainBackColour TabNo(iNumTabs - 1).Controls.Add(txtMain(iNumTabs - 1)) End Sub Private Sub SettingsToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SettingsToolStripMenuItem.Click ' Open the settings form, and if colour is returned as set... If frmSettings.ShowDialog() = DialogResult.OK Then Dim value As New TextBox ' Iterate through all currently opened tabs and update the colour For Each value In txtMain value.BackColor = My.Settings.frmMainBackColour Next End If End Sub End Class
LosOjos Posted March 23, 2010 Posted March 23, 2010 Here's my code (with all the irrelevant bits taken out). Can you try it on yours to see if it works, as the stuff you said works for you isn't working for me - so I wonder if my environment is setup differently: What is 'frmSettings' made up of? Where is 'ContextMenuTabs' decalred? I'll have to re-create those two to get it to work. At the moment, these are the errors I'm getting (should be solved once you answer my questions though): Error 1 Name 'ContextMenuTabs' is not declared. Error 2 Handles clause requires a WithEvents variable defined in the containing type or one of its base types. Error 3 Name 'frmSettings' is not declared.
LosOjos Posted March 23, 2010 Posted March 23, 2010 (edited) You know what, going through your code, you seem to be making the txtMain & TabNo arrays one bigger than they need to be, thus leaving a 'Null' object at the end, that might explain your error. Try replacing the 'createTabPage' sub with this code to see if it solves it: Public Sub createTabPage() ' Additional tab so increase variable to keep track of this iNumTabs += 1 'ReDim the tab page array and textbox array to make room for the new tab page (preserving current tab pages & textboxes ReDim Preserve TabNo(0 To iNumTabs) ReDim Preserve txtMain(0 To iNumTabs) ' Create the new tab page and stick it on the form (into the only tab control) TabNo(iNumTabs) = New TabPage TabNo(iNumTabs).Name = "TabPage" & iNumTabs TabNo(iNumTabs).Text = "Blank File" TabControl1.Controls.Add(TabNo(iNumTabs)) ' Create the new textbox and add this to the tab page that we just added txtMain(iNumTabs) = New TextBox txtMain(iNumTabs).Name = "txtMain" txtMain(iNumTabs).Dock = DockStyle.Fill txtMain(iNumTabs).Multiline = True txtMain(iNumTabs).ScrollBars = ScrollBars.Vertical txtMain(iNumTabs).Font = New Font("Courier New", 10, FontStyle.Regular) txtMain(iNumTabs).ForeColor = My.Settings.frmMainForeColour txtMain(iNumTabs).BackColor = My.Settings.frmMainBackColour TabNo(iNumTabs).Controls.Add(txtMain(iNumTabs)) End Sub And when you intialise iNumTabs, set it to -1 Edited March 23, 2010 by LosOjos 1
mac_shinobi Posted March 23, 2010 Posted March 23, 2010 (edited) could you not use the controls collection to loop through each one and change the colour something similiar to [color=blue][font=Courier New]Sub[/font][/color][font=Courier New] [color=black]Form1_Load[/color]([color=blue]ByVal[/color] [color=black]sender[/color] [color=blue]As[/color] Object, [color=blue]ByVal[/color] [color=black]e[/color] [color=blue]As[/color] [color=black]EventArgs[/color]) _[/font] [font=Courier New] [color=blue]Handles[/color] [color=blue]MyBase[/color].[color=black]Load[/color][/font] [b][font=Courier New] [color=blue]Dim[/color] [color=black]control[/color] [color=blue]As[/color] [color=black]Control[/color][/font][/b] [b][font=Courier New] [color=blue]For[/color] [color=blue]Each[/color] [color=black]control[/color] [color=blue]In[/color] [color=blue]Me[/color].[color=black]Controls[/color][/font][/b] If control="TextBox" Then [b][font=Courier New] [color=black]MessageBox[/color].[color=black]Show[/color]([color=black]control[/color].[color=black]Name[/color])[/font][/b] End If [b][font=Courier New] [color=blue]Next[/color][/font][/b] [color=blue][font=Courier New]End[/font][/color][font=Courier New] [color=blue]Sub[/color][/font] How do you use control collection on VB.NET? Obviously you would have to change MessageBox.Show(Control.Name) to control.BackColour = vbRed or whatever. Also not sure about the control name but you would need to find out the control name so that the if statement works Edited March 23, 2010 by mac_shinobi
Hightower Posted March 24, 2010 Author Posted March 24, 2010 What is 'frmSettings' made up of? Where is 'ContextMenuTabs' decalred? I'll have to re-create those two to get it to work. At the moment, these are the errors I'm getting (should be solved once you answer my questions though): Error 1 Name 'ContextMenuTabs' is not declared. Error 2 Handles clause requires a WithEvents variable defined in the containing type or one of its base types. Error 3 Name 'frmSettings' is not declared. 1) ContextMenuTabs is a simple context menu giving the tab pages right-click functionality. Should have taken that out as we don't need it for what I'm trying to achieve here - just delete it's references from your copy of the code 2) frmSettings it a very basic Windows form that has a colorDialog on it so the user can dynamically select the BackColor.
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now