I have a form in vb.net with LOTS of text- and comboboxes. Now i do want to apply some settings to them, e.g. visibility, location and so on during runtime. The information on what to apply is complex and is stored in my database together with the name of the given item, e.g. name=textbox1, visibility=true, location x = bla, location y= bla and so on.
My question is: Is it somehow possible to use the string in the field "name" to adress the object in the code like this:
ConvertToFormObject(name).visible=visibility
so that i could apply the settings with a single loop rather than hardcoding the information in the database to all the items. Also the settings should be applied spontanously, when e.g. some event triggers were triggered.
Thanks!
You can index the Controls collection of the form by name to get the control with that Name value, e.g.
Dim cntrl As Control = Controls("TextBox1")
This assumes that all the controls of interest are on the form directly. If they are all in the same child container then use the Controls collection of that container. If they might be in different containers, e.g. a Panel and a GroupBox, then you can call Find, e.g.
Dim cntrl As Control = Controls.Find("TextBox1", True).First()
Note that Find returns a Control array, because the Name of each control in a container must be unique but multiple containers can each contain a control with the same Name. Assuming that you have used unique Name values form-wide, you just call First or Single or index the array with zero.
Related
I'm trying to wrap my head around array lists in vb.net. I am self teaching via the internet but can't seem to figure it all out. Some points i'm having trouble connecting the dots to:
How do i make the array list universal so it's not stuck in a subroutine and I can allow any sub to access the list.
Allowing the list to be added to or removed from from another control on the form.
Saving this array list so the program will populate the list box with it on startup.
Here is an image of the basic concept for the visual:
https://imgur.com/lBbopD8
Up to question 3, using a List(Of T) was the way to go. It may still be but certainly not completely and maybe not at all. Before the advent of the List(Of T), Microsoft recognised that storing Strings in a collection was the most common requirement so, to provide type-safety in that case, they provided the StringCollection class. You say that you want to persist your list of values between sessions so that probably means using My.Settings and it is actually possible to create a setting of type StringCollection.
I would suggest that you open the Settings page of the project properties and add a setting of type StringCollection. Once added, that list will be automatically loaded at startup and saved at shutdown, with no code required from you. You can access it anywhere in the app via My.Settings and you can call Add and Remove or index it or loop over it in exactly the same way as you would an ArrayList or List(Of String).
There is one small gotcha with a StringCollection in settings though. It will actually be Nothing by default. The trick to avoiding that is to edit its Value on the Settings page to add an item, commit that, then edit it again to remove the item. You'll see that, instead of the Value field being empty, it will then contain a snippet of XML. It's that that creates the StringCollection object in the settings file.
As I said, if you want to persist this list between sessions then I strongly recommend using settings this way. Just note that, in order to edit settings, they have to be User-scoped rather than Application-scoped. What that means is that each separate Windows user will have their own copy of the setting and thus their own value. If you only log into Windows with one account then it's of no consequence. If multiple Windows users use the app then it may be considered beneficial in most cases but may be a problem if you want universal settings that can be edited. If it's a problem, you will need to handle persistence yourself but be aware that a standard Windows user (as opposed to an admin) won't have access to write data everywhere, which is exactly why User-scoped settings work the way they do.
Also, while you must use a StringCollection for persistence in settings, you may or may not want to use the same collection in the rest of your code. You might access the collection directly all the time or you may choose to copy the collection to a List(Of String) at startup and then copy the data back at shutdown. Unless you want to avoid committing items until shutdown, I wouldn't bother with the extra collection.
So an important thing to know is that you can directly populate and edit the listbox without having an additional ArrayList. You would use the example code below as follows:
'addTb is the text box you had in the image; this will run on button press event
ListBox1.Items.Add(addTB.Text)
If you are looking to dump ArrayList data into the list box use something like this:
'creates new arraylist and adds items to it
Dim listStuff As ArrayList = New ArrayList
listStuff.Add("Hi")
listStuff.Add(2)
'makes listStuff the datasource for your list box
ListBox1.DataSource = listStuff
Finally, if you are wanting to loop through ArrayList items use something like this:
'remember to do count - 1 or you will receive error since index will be out of range
For i = 0 To listStuff.Count - 1
If listStuff.Item(i) = "" Then
'do stuff here
End If
Next
Hopefully that helps. Let me know if I need to be more clear since this is my first stack overflow answer :)
You are using a ListBox control to visualize a collection of presumably String values from a TextBox control. The ListBox exposes the visualized collection via the Items property.
How do i make the array list universal so it's not stuck in a subroutine and I can allow any sub to access the list.
Because the ListBox control resides on the Form, you can access the Items property through any access level in your Form's code.
Allowing the list to be added to or removed from from another control on the form.
From the Items property, you can use the Add method to add a single value, the AddRange method to add multiple values via an array or another ListBox collection, the Insert method to insert a value at a given index, the Remove method a specific item, and the RemoveAt method to remove an item at a given index.
So in your case, since you're presumably adding the value from the Text property of the TextBox to the ListBox, it is as simple as:
ListBox1.Items.Add(TextBox1.Text)
Saving this array list so the program will populate the list box with
it on startup.
You have a few options, but generally the idea is to is write each value in the Items property to its respective line at a given file when the application closes and then load each value back by reading each line from the same file. Another option is to use My.Settings, though I think with your level of expertise, it would probably be better to stick with the read/write to a file option so you don't have to worry about some pitfalls associated with this option. Here would be a quick example of reading/writing the items to a file:
'Write the items to the file
Dim items(ListBox1.Items.Count - 1) As String
ListBox1.Items.CopyTo(items, 0)
IO.File.WriteAllLines("file.txt", items)
'Read the items to the file
ListBox1.Items.AddRange(IO.File.ReadAllLines("file.txt"))
I have a custom text editor derived from RichTextBox where the user can drag an object into the box and it displays the object's name (amongst other, keyboard entered, text). I would like to treat this name as a single, uneditable, entity: the user can only delete the whole name and can't change anything on the inside.
I would also like the formatting to be completely isolated from the surroundings. Right now I insert it as a separate Run. Iff the user places the cursor at the end of the name, the new keyboard entered text has the name formatting which I don't want.
FYI, for anyone else trying to do something similar, I was able to do this by using an InlineUIContainer holding a TextBlock.
I have an desktop WPF application that shows values from different files, the objective being to compare those files. The values extracted from the files are displayed in a DataGrid, one column per file. The user can add or remove files at will, which means that the amount of columns displayed in the grid can change. Columns are created and removed from a ViewModel, and have complex content that requires the use of DataGridTemplateColumn instances.
The data source is basically a two dimentionnal array (something like ObservableCollection<ObservableCollection<CellViewModel>>).
To fill my cells I need a data template, but the problem is that the DataTemplate's data source will be the row. And if I want to display the correct value, I'll have to know the index of the current cell from the template, so I access the correct index in my row. In the end, I'd like to be able to have a binding in the template that looks like {Binding Path=[someIndex].DisplayText} (DisplayText being a property of my CellViewModel).
I hope I've been clear enough :)
So the question is : how do I read the correct index in my row from the template ? Or, is there some better way to handle this variable-sized templated columns list problem ?
Thanks
I have a DataTemplate(well two data templates) that I want to use as views for some
basic form viewmodels(that that contain a value and and boolean indicating whether I want to use the value).
I want to use the datatemplate(s) several times for separate form items. I think the right way to do this is to set it as the ContentControl's ContentTemplate (in that case it will have the same data context right?) but I also want to pass the label string and since the label string is part of the ui and doesn't change it seems wrong to put it in the viewmodel object. How do I give access of the label string to the DataTemplate instance?
Just like its name, a DataTemplate is used to template the Data... For example, if you have a class called MyItem which has a Name and Value and you want this shown in a specific way, you'll set a datatemplate for Item and use it whenever needed.
In your case, you're speaking about having very similar views, with only a minor change between them. This minor change (if I understood your question correctly) is not something that comes from the model or from the viewmodel but something which is entirely view-oriented (a different title for the page, for instance).
If you plan on using a different viewmodel for every view, and each viewmodel has a different purpose - I don't see a problem with adding a Title property to the VM and bind to that too (Remember, MVVM is a set of guidelines, not rules...)
If you still rather have it separated from the viewmodel, then you can use an Attached Property. Create an Attached Property called TemplateTitle, for instance, and have each contentcontrol in each view change it. The label, of course, will bind to that Attached Property.
I have large collection of statuses(bool) that are reached by key (address)
the visual should display each status as different control (for example checkboxes, buttons, radios , etc) - each control is provided with the address of the status it will display
for example
button1 <- status[55]
checkbox1 <- status[81]
..
etc
my question is if i put INotifyPropertyChanged on whole indexer(if i do it with indexer) - if one value changes does it update all the controls or only the changed one..
I want only one status change to update only one control - not all of them. Is there a way doing this?
It will update all, in Silverlight you could construct a notification that only updates one index. I cannot think of any solution which would let you keep that structure, if you map everything to objects with key and value you could internally notify of value changes...