Dynamically create and access RadioButtonLists from code-behind - vb.net

My problem is: I have a stripped down default.aspx page. Aside from a element, almost ALL the functionality has to be in the code-behind in aspx.vb.
The program retreives information from a database and compares this to another list of tables, number of both lists can vary.
So I need to "bind" a dynamic number of RadioButtonLists to the asp:table element controls, and I need to create a dynamic number of ListItems to each RadioButtonList created. Later, I need to be able to access the selected value of each in order to decide future functions in the database.
An example of the code is like this:
aspx file:
<asp:table ID="table1" runat="server">
aspx.vb file (code-behind):
Sub createHtmlTables()
For i = 0 To productIndex.Count - 1
''//create a RadioButtonList for each i
Dim row As New TableRow
Dim cell As New TableCell
For k = 0 To productTypeAmountIndex.Count - 1
''//create a ListItem(radiobutton)
''//for each k and include it in the RadioButtonList
''//assign a value (for example name) of the product as
''//the ListItems ID to retreive it later
Next
''//add the RadioButtonList to cell.controls etc
Table1.Rows.Add(row)
Next
End Sub
Sub addToDb()
For i = 0 To productIndex.Count - 1
''//get the RadioButtonList for each i
''//and return the value of the selected radiobutton
''//within the list to a variable
Next
End Sub
Sorry if this is long and confusing, but as I can't even form my questions right yet, I tried to include as much information as possible. Basically I just need an example of how and which methods to use to get all that working.
Update:
Everyone keeps telling me that going for tables to begin with was a mistake, but some place I found claimed that you can't customize datagrid looks as easily as you can with tables. I guess I'll start the whole thing from scratch then.
Thing is that the UI should be as graphically pleasing as possible, with the tables I can do all sorts of neat things such as colouring the cells according to the information inside etc.
Anyway, thanks but not what I was looking for but I'll try to remake the thing with datagrid / gridview and see what happens. Might take a few days before I learn enough of them to use them and get back here.

Rather than a table, you'll have better luck with a true server control like gridview or datagrid, or repeater. Then you can just wire up the datasource property on your control.
For all dynamic controls, remember that you have to recreate them every time you do a postback. This may sound odd, but the trick is the every request to the server, including postbacks, uses a different instance of your page class. When that request/postback finishes the page instance used for that request is destroyed. The only things left active are the session and the cache.

This is my .aspx code.
<asp:Table ID="Questions" runat="server">
</asp:Table>
<asp:Button ID="SaveButton" runat="server" Text="Save" />
This is my code behind file code.
I have added dynamic drop-down list.
On save button click, I am retrieving selected value.
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim NewRow As New TableRow
Dim NewCell As New TableCell
Dim rblOptions As New RadioButtonList
rblOptions.ID = "Option1"
rblOptions.Items.Add(New System.Web.UI.WebControls.ListItem("1", "1"))
rblOptions.Items.Add(New System.Web.UI.WebControls.ListItem("2", "2"))
rblOptions.Items.Add(New System.Web.UI.WebControls.ListItem("3", "3"))
NewCell.Controls.Add(rblOptions)
NewRow.Cells.Add(NewCell)
'Questions is a table
Questions.Rows.Add(NewRow)
End Sub
Protected Sub SaveButton_Click(sender As Object, e As EventArgs) Handles SaveButton.Click
If Page.IsValid Then
Dim rbl As RadioButtonList = DirectCast(Questions.FindControl("Option1"), RadioButtonList)
If rbl.SelectedValue.ToString = "ExpectedValue" Then
End If
End If
End Sub

Related

Limiting my result set in VB

So I can fill the combobox I have going in Visual Studio just how I want with ALL results with the following:
Dim pnum As New List(Of String)
For Each polnumber As InsuredDataSet.Claims_InsuredRow In Me.InsuredDataSet.Claims_Insured
pnum.Add(polnumber.Policy_Number)
Next
pnum.Reverse()
Me.Policy_NumberComboBox.DataSource = pnum
Awesome. Now I want to limit the pnum by taking what was input/selected from Insured_NameTextBox on the form and only returning the Policy_Number with a matching Insured_Name. I figure this can be performed with an If statement, but everything I try (stringcompare, InsuredName_TextBox = Me.InsuredDataSet.ClaimsInsured, etc.) either doesn't limit the results OR limits the results entirely so nothing shows up. Any idea where to put the If statement and what should be compared?
UPDATE:
I think there is some confusion so I'm including the entire load sub below:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'TODO: This line of code loads data into the 'IncidentsDataSet.Claims_Incidents' table. You can move, or remove it, as needed.
Me.Claims_IncidentsTableAdapter.Fill(Me.IncidentsDataSet.Claims_Incidents)
'TODO: This line of code loads data into the 'InsuredDataSet.Claims_Insured' table. You can move, or remove it, as needed.
Me.Claims_InsuredTableAdapter.Fill(Me.InsuredDataSet.Claims_Insured)
'textbox autocomplete mode
Dim Iname As New AutoCompleteStringCollection()
For Each insname As InsuredDataSet.Claims_InsuredRow In Me.InsuredDataSet.Claims_Insured
Iname.Add(insname.Insured_Name)
Next
Me.Insured_NameTextBox.AutoCompleteCustomSource = Iname
'combobox autocomplete code (now sorting by last included!)
Dim pnum As New List(Of String)
For Each polnumber As InsuredDataSet.Claims_InsuredRow In Me.InsuredDataSet.Claims_Insured
pnum.Add(polnumber.Policy_Number)
Next
pnum.Reverse()
Me.Policy_NumberComboBox.DataSource = pnum
End Sub
Try something like this:
Me.Policy_NumberComboBox.DataSource = InsuredDataSet.Claims_Insured.Where(Function(r) r.Insured_Name = Insured_NameTextBox.Text).Select(Function(r) r.Policy_Number).Reverse()
We're getting closer. Based on the update to your question, you're running this code when the form loads. However, at the point where the form loads, your textbox will always be empty. What do you do when the value in the textbox changes, to re-filter your data?
This is C#
Me.InsuredDataSet.Claims_Insured.Where(x => x.Insured_Name == Insured_NameTextBox.Text);

Creating a new instance of an existing control? (a bit more complicated than it sounds)

I know that if I want to dynamically create a new instance of an existing form, I can simply do this...
Dim NewForm As New ExistingForm
... and a new instance of all of the controls from ExistingForm will be available in NewForm.
But what if I want to create a new instance of an existing control that's inside a separate existing form?
More specifically, let's say I have 2 forms - FormA and FormB. Inside FormB is an existing panel (we'll call it ExistingPanel). And inside ExistingPanel are several buttons, text boxes, etc., arranged exactly how I want them.
OK, so... inside a button's click event in FormA, I want to do something like this (it doesn't work, obviously, but should give you a good idea as to what I'm trying to accomplish)...
Dim NewExistingPanel As New FormB.ExistingPanel
And then I want NewExistingPanel to contain new instances all of the individual controls from ExistingPanel (so that I can dynamically manipulate each one individually).
So basically, my program will need to create several NewExistingPanels at runtime. And I will need to access each one (and all of its child controls) individually, after they have been created.
How can I accomplish this? I've been experimenting with this for several hours with no luck so far, so figured I'd break down and ask the real professionals :)
When you create a new user control, you could use a dictionary with the tag value as key and the control name as value. Then you can access the control directly by using the IndexOfKey method.
Dim NewForm2 As New Form2
Dim ControlIndex As New Dictionary(Of String, String)
For I = 0 To 2
Dim NewPanel As New WindowsControlLibrary2.MyCustomPanel
NewPanel.Name = "Panel-" + I.ToString
NewPanel.Location = New Point(0 + (NewPanel.Size.Width * I), 0)
NewPanel.Tag = "MyTagValue" + I.ToString
ControlIndex.Add(NewPanel.Tag, NewPanel.Name)
NewForm2.Controls.Add(NewPanel)
NewForm2.Update()
Next
NewForm2.Show()
Dim CurrentPanel As WindowsControlLibrary2.MyCustomPanel =NewForm2.Controls(NewForm2.Controls.IndexOfKey(ControlIndex("MyTagValue1")))
To add control such as panel with textboxes ang button in it ..
In your project - Add > Usercontrol -->
in this part you can make panel with textboxes and button as you want
name it as "myPanel" and save it as "myPanel.vb" --> or whatever you want
In your form and the button named button1 you can add to your button1_click event :
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim mypanel1 As New MyPanel
mypanel1.Location = New Point(0, 0)
Controls.Add(mypanel1)
mypanel1.TextBox1.Text = "Hi, Im new"
End Sub
And you will get your panel at runtime ...
And you will get the textbox1.text fill with "Hi, I'm new" ...
You could create a user control that lays out your sub-controls the way you want them, then create new instances of that. Add New > User Control in the solution menu, then build, and your controls should be ready to drag into the designer at the top of the Toolbox or to instantiate in code like any other control.
To expand on my comment:
Private somePanels As New Dictionary(Of String, YourUserControl)
Then you can just add them as follows:
Dim c As New YourUserControl()
…
Me.Controls.Add(c)
somePanels.Add("SomeTag", c) ' Instead of using Tag; if your tags are numbers, use a List instead of a Dictionary
And access them as:
Dim c = somePanels("SomeTag")

vb.net - click on listview subitem and open window

I'm not sure if this is possible after doing a bunch of googling, but hopefully it is. I have an application that pulls a list of information from a MySQL database and populates a listview (Unfortunately, I can't change to a datagrid at this time.) What I'm tasked to do is make it so that when clicking on a certain column, a window will open and, based on the ID of the row that was clicked on, retrieve another set of results from the same database.
The list view is created as such:
Do While result.Read()
Dim siteid = (result.Item("idsite").ToString())
Dim sitename = (result.Item("name").ToString())
Dim last_import_date = (result.Item("import_finished").ToString())
Dim last_import_file = (result.Item("file_name").ToString())
Dim last_line = (result.Item("last_line").ToString())
Dim status = (result.Item("status").ToString())
Dim lv As ListViewItem = ListView1.Items.Add(siteid)
lv.SubItems.Add(sitename)
lv.SubItems.Add(last_import_date)
lv.SubItems.Add(last_import_file)
lv.SubItems.Add(last_line)
lv.SubItems.Add(status)
Loop
So preferably I'd like to click on "Last_import_file" and have that open the window. I've tried a bunch of ItemClicked type commands, but haven't had much luck.
Is what I'm attempting possible? I don't need any special text formatting, just want to register the click and pop open the dialog.
Thanks!
Yes it is possible. To do this in a Listview it is a bit more complicated than a DataGridView. You'll need to make use of the ListViewHitTestInfo class. Using the MouseDown Event of your listview, use this code:
Private Sub ListView1_MouseDown(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles ListView1.MouseDown
Dim info As ListViewHitTestInfo = ListView1.HitTest(e.X, e.Y)
MsgBox(info.Location.ToString())
If Not IsNothing(info.SubItem) Then
'info will contain the information of the clicked listview column. You can then go through it's subitems for more information, if any.
End If
End Sub

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

DataGridView losing initial state specified at design time

When I try to change the datasource of my DataGridView, I am loosing the order of the columns and their type(checkboxes,comboboxes) that i specified at design time.
It's like changing the datasource is generating again the datagridview, why ? and How can I change the datasource without losing these information ?
Please if you know give me help
Thanks in advance
On form load i do something like
Private Sub frmGrid_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim Path as string
Path="C:\......Myfile.xml"
Dim oData as dataset
oData = New DataSet
oData.ReadXml(Path)
oData.AcceptChanges()
DataGridView1.DataSource = oData
DataGridView1.DataMember = oData.Tables(0).TableName
end sub
Till now everything is fine the design mode is preserved.
Then I have in my interface I have a button to save the content of my Grid to an excel file (it's an xml, formatted for excel)
Then i want to import this, on a button action, so i do the following
Private Sub Button13_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button13.Click
Dim MyDs As DataSet
MyDs = New DataSet
Dim InputFileStream As New System.IO.FileStream(Path, System.IO.FileMode.Open)
MyDs = ImportExcelXML(InputFileStream, True, True)
MyDs.ReadXml(Path)
MyDs.AcceptChanges()
DataGridView1.DataSource = MyDs
DataGridView1.DataMember = MyDs.Tables(0).TableName
end sub
Probabily you have set up GenerateColums property to "True"
That means the GridView will generate the columns(name and number of them) againts the data sorce.
If the data source (in you case data table) are different it will come up a different grid.
If the datasource are different you can design the layout of your gridView but after that you have to manually bind the data to the columns as you wish.You can do that into
RowDataBound event.
The datatable you are trying to assign to the DataGridView1.DataSource is structured different from the way you defined the DataGridView at design time. Put a break point in your code right before you reassign the new DataTable to the DataSource and see what is different in the structure. It is most likely that you either have more or less DataColumns in place, or the columns could be in a different order. They might even be named different. If at design time you set your DataGridViewColumn's DataProperty to a specific name, than then name needs to be exact.
You'll just have to check it at that breakpoint and see what the differences are.
I found a solution, your hints helped me to look on the right direction to find a solution !
What i was doing was on form load
MaGrille.DataSource = oData
MaGrille.DataMember = oData.Tables(0).TableName
Then in the button click I do :
MaGrille.DataSource = MyDs
MaGrille.DataMember = MyDs.Tables(0).TableName
The problem is that the grid is rebuild and i loose the formatting, column order etc..
After many tests, I understood that It wasn't working because the names of datatables are differents ! I don't understand why, but it was the error as it seems.
I had the following values
oData.Tables(0) = "DECLARATION"
MyDs.Tables(0) = "Sheet1"
So I noticed that if I rename MyDs.Tables(0) by "DECLARATION" instead of "Sheet1", and i click on the button, this time I don't loose formatting, neither orders ...
This inspired me to find the SOLUTION :
After many tries, I realized that if instead of doing on form load
MaGrille.DataSource = oData
MaGrille.DataMember = oData.Tables(0).TableName
and on button click :
MaGrille.DataSource = MyDs
MaGrille.DataMember = MyDs.Tables(0).TableName
I do :
on form load
MaGrille.DataSource = oData.Tables(0)
and on button click
MaGrille.DataSource = MyDs.Tables(0)
All works fine even if the oData.Tables(0).TableName is different from MyDs.Tables(0).TableName !!
I found the solution Now, but still can't understand the WHY If anyone get an explication, please let me know.
Thanks to all again