Btn.PostBackUrl / Nested with DropDownList INSIDE a Datalist - vb.net

in VB.net I have a DATALIST in which, among others I have a DropDL CTRL which is Bound with LINQ something like this:
Public Sub DLCategorias_ItemDataBound(sender As Object, e As System.Web.UI.WebControls.DataListItemEventArgs) Handles DLCategorias.ItemDataBound
If e.Item.ItemType = ListItemType.AlternatingItem Or e.Item.ItemType = ListItemType.Item Then
Dim DC As New MyDataContext
Dim cat = (From c In FF.ProductosCategorias Select c Where c.idCategoria = (CTypeDLCategorias.DataKeys(e.Item.ItemIndex), Integer))).Single
Dim thisId As Integer = cat.idCategoria
Dim subcat = From d In dc.ProductosSubCategorias Where d.idCategoria = thisId Select d.idSubCategoria, d.NombreSubCategoria
Dim ddlSubCat As DropDownList = CType(e.Item.FindControl("ddlSubCat"), DropDownList)
Dim BTNVER As Button = CType(e.Item.FindControl("BtnVerSubCat"), Button)
ddlSubCat.DataTextField = "NombreSubCategoria"
ddlSubCat.DataValueField = "idSubCategoria"
ddlSubCat.DataSource = subcat
ddlSubCat.DataBind()
ddlSubCat.AutoPostBack = True
BTNVER.PostBackUrl = "SubCat.aspx?idSubCategoria=" & ddlSubCat.SelectedValue.ToString
What I am trying to achieve is that IF ddlSubCat has its value changed (cause some user selected another SubCat to see) the POSTBACK get working fine.
What it does (up to here) is getting the FIRST value of DDLSubCat (first index of DDL)
I need to SOMEHOW "refresh" (but can't) de DATABOUND or whatever for the Button Works fine.
Tried everything, did ONCLICK (but the ddlSubCat does not appear in codebehing since its in DL)
Tried to EVAL in Design view... BUT CAN'T!

SOLVED !
Thanks to som other answer from Tim Schmelter, I realice that I could be handled by Codebehind
in the BTN click event like this:
Protected Sub BtnVerSubCat_Click(sender As Object, e As EventArgs)
Dim container = DirectCast(DirectCast(sender, Control).NamingContainer, DataListItem)
Dim idSubCat = DirectCast(container.FindControl("ddlSubCat"), DropDownList)
Dim Xid As String = idSubCat.SelectedValue
Response.Redirect("SubCat.aspx?idSubCatgoria=" & Xid)
End Sub
Thanks anyway

Related

Read data from dynamically created text-box

I'm trying to collect data after creating dynamic text-box with vb.net
Private Sub btn_OK_lines_number_Click(sender As Object, e As EventArgs)
Handles btn_OK_lines_number.Click
Dim i As Integer
Dim x As Integer
Dim Z As Integer
Z = 150
If IsNumeric(txt_lines_number.Text) Then
Int32.TryParse(txt_lines_number.Text, x)
For i = 1 To x
Dim newTB As New TextBox
Dim newLB As New Label
newLB.Name = "lbl_workstation_number_line" & i
newLB.Text = "Nbr Work Station in Line" & i
newLB.Size = New Size(190, 20)
newLB.ForeColor = Color.White
newLB.Font = New Font("consolas", 12, FontStyle.Regular, GraphicsUnit.Pixel)
newLB.Location = New Point(20, Z + i * 30)
newTB.Name = "Textbox" & i
newTB.Size = New Size(170, 20)
newTB.Location = New Point(200, Z + i * 30)
Me.Controls.Add(newTB)
Me.Controls.Add(newLB)
Next
i = i + 1
Else
MessageBox.Show("please enter a number")
txt_lines_number.Text = ""
End If
End Sub
Let's say you just have one row, and only create one TextBox. You set the name here:
newTB.Name = "Textbox" & i
where the resulting TextBox is named Textbox1. The problem is you can't just reference the identifier Textbox1 directly in your code, as you do with txt_lines_number. You can't even reference it as a member of the class (Me.Textbox1). This name didn't exist at compile time, and so it's not an identifier you can use, and it's not a member of the class at all. There was never a matching Dim statement for that name.
What you can do, though, is look again in the Controls collection where you added the TextBox to the form:
Me.Controls("Textbox1")
or
Me.Controls("Textbox1").Text
You may also need to cast the value to a TextBox:
Dim box As TextBox = DirectCast(Me.Controls("Textbox1"), TextBox)
MessageBox.Show(box.Text)
Remember that case matters here.
Further saving this in a DB is out of scope for one question. There are as many ways to do that as there are programmers in the world. You should make your own attempt first, and come back here with a new question when you run into specific problems.
Thank you,
this is my attempt and it is done !
Dim userInput As TextBox = Form1.Controls.Item("TextBox" & i.ToString)
mycommand.Parameters.AddWithValue("#workstation", userInput.Text)
:D
Because you creating dynamic amount of input controls, right tool for the job will be DataGridView control.
Create a class to represent your data
Public Class LineInfo
Public Property Number As Integer
Public Property WorkStationNumber As Integer
End Class
Create `DataGridView in the form designer.
Private Sub btn_OK_lines_number_Click(sender As Object, e As EventArgs) Handles btn_OK_lines_number.Click
Dim linesAmount As Integer
If Integer.TryParse(txt_lines_number.Text, linesAmount) = False Then
MessageBox.Show("please enter a number")
txt_lines_number.Text = ""
Exit Sub
End If
' Create class instance for every line
Dim lines =
Enumerable.Range(1, linesAmount)
.Select(Function(i) New LineInfo With { .Number = i })
.ToList()
'Set lines as DataSource to the DataGridView
Me.DataGridView1.DataSource = lines
End Sub
DataGridView will display all lines and provide input fields to update work station numbers.
You can access updated lines later by casting DataSource back to the List
Dim lines = DirectCast(Me.DataGridView1.DataSource, List(Of LineInfo))
' Now you can access all data and save it to the database
Dim parameters =
lines.Select(Function(line)
Return new SqlParameter With
{
.ParameterName = $"#workstation{line.Number}",
.SqlDbType = SqlDbType.Int,
.Value = line.WorkStationNumber
}
End Function)
.ToList()
myCommand.Parameters.AddRange(parameters)
You can freely change style, font colors of different columns in the datagridview.

How to do this effect in VB? It works in Python

how can i fix this problem, in line with ">>" , in python it works, how does it work in vb
Public Class frmCafeOrder
Public ingredients = {{"Apple", 10.0},
{"Lettuce", 12.5},
{"Tomato", 8.5},
{"Ham", 20.0},
{"Tuna", 18.5},
{"Grain Wheet", 8.0},
{"Honey Oat", 10.5}}
Public priceControls = {{chkApple, lblApplePrice},
{chkLettuce, lblLettucePrice},
{chkTomato, lblTomatoPrice},
{chkHam, lblHamPrice},
{chkTuna, lblTunaPrice},
{rbGrainWheet, lblGrainWheetPrice},
{rbHoneyOat, lblHoneyOatPrice}}
Private Sub frmCafeOrder_Load(sender As Object, e As EventArgs) Handles MyBase.Load
init()
For i As Integer = 0 To ingredients.GetLength(0)
Dim ingredient = ingredients(i, 0)
>>Dim controls = priceControls(i)
Dim price = ingredients(i, 1)
>>priceControls = controls(i)
>>priceControls = String.Format("HK$ {0}", price)
Next
End Sub
End Class
First, you are trying to use a 2D array without specifying the other dimension.
You specify these perfectly:
Dim ingredient = ingredients(i, 0)
Dim price = ingredients(i, 1)
but are failing to do that with this:
Dim controls = priceControls(i) 'notice it's missing the second dimension
Secondly.... this... whatever this is...
Dim controls = priceControls(i)
priceControls = controls(i)
You are setting controls to priceControls and then trying to set it to itself, but with an added (i), where on earth did the (i) in controls come from?
and then for a little added confusion.
priceControls = controls(i)
priceControls = String.Format("HK$ {0}", price)
why set it to one thing when you are just going to set it to another?
What I am guessing you are trying to do is this:
Go through the list of ingredients in Ingredients()
Populate the right lbl.text field with the corresponding price
For i As Integer = 0 To ingredients.GetLength(0)
Dim ingredient as String = ingredients(i, 0)
Dim price as String = ingredients(i, 1)
Dim lbl as Label = DirectCast(priceControls(i, 1), Label)
lbl.text = String.Format("HK$ {0}", price)
Next
You haven't really specified the problem directly or what you are looking to do, so this is really just my guess at both.

Access a panel from another form with increment variable name

Public Sub StatusLoad(ByVal id As String)
''Dim F As New Apps
''Dim W As Panel = DirectCast(F.Controls(id), Panel)
Dim count As Long = 0
Dim strQueryStat As String = "SELECT * FROM sample_db.ronda WHERE id = '" + id + "'"
Dim SqlCmdStat As New MySqlCommand(strQueryStat, dbCon)
Reader = SqlCmdStat.ExecuteReader
While Reader.Read
count = count + 1
MsgBox("id" & count)
Dim status_db = Reader.GetString("status")
If status_db = 0 Then
Apps.id.BackColor = Color.Green '<------
MsgBox("Green")
Else
Apps.BackColor = Color.Red
MsgBox("Red")
End If
End While
End Sub
I want to use 'id' variable that get from other form to find the panel name from the other form. the above code is in a class. the panel that i want to access is at another form.
at the other for i send "con.StatusLoad(id)". the name of panel is id1 , id2 , id3 ...... the error is at the arrow
Private Sub app_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
con.ManageConnection(False)
For index As Integer = 1 To 2
Dim id As String = "id" & index
con.StatusLoad(id)
Next index
End Sub
Each control, including forms, has a Controls property that contains a collection of child controls. You can index that collection by ordinal or name, e.g.
For i = 1 To 5
Dim pnl = Me.Controls("Panel" & i)
'...
Next
Note that you'll be getting a Control reference back, so you can only use it to access members of the Control class. If you want to access members of a specific type of control then you must cast as that type.
Controls is a public member so it can be accessed from outside the form but probably shouldn't be. The same "rules" apply as would always apply to making changes to controls on a form, i.e. best practice dictates that it's done inside that form only.

List view sort arrow vb.net

i am trying to draw sort arrows on list view column header along with the default visual styles
so far i have got this
Private Sub List_DrawColumnHeader(sender As Object, e As DrawListViewColumnHeaderEventArgs) Handles List.DrawColumnHeader
e.DrawDefault = True
If e.ColumnIndex = selectedIndex Then
e.Graphics.DrawImage(ImageList1.Images(1), CType(e.Bounds.Left + e.Bounds.Width / 2, Single) - 5, -2)
End If
End Sub
but the visual style is drawn over the arrow somehow
so i figured i could try this :
Private Sub List_DrawColumnHeader(sender As Object, e As DrawListViewColumnHeaderEventArgs) Handles List.DrawColumnHeader
e.DrawDefault = True
If lastDrawn.ColumnIndex = selectedIndex Then
e.Graphics.DrawImage(ImageList1.Images(1), CType(lastDrawn.Bounds.Left + lastDrawn.Bounds.Width / 2, Single) - 5, -2)
End If
lastDrawn=e
End Sub
and it draws the arrow when the next corresponding column is being drawn
but with this i cant get it to draw for the last column
Screenshots:
In order to use the .NET build in solution for showing a custom icon for a list view column header you need to:
create an ImageList
add three images (up / down arrow and empty) to it
bind the image list to the ListView control
bind to the ColumnClick event of the ListView control
when sorting the columns set the ImageKey property of the currently sorted column depending on the sorting direction
This example class (a simple form) shows how to set the images correctly not using custom drawing for the ListView header columns.
It does not implement any sort! (how to implement a ListViewSorter is shown in this MSDN article)
You need to implement a custom ListView-Sorter class and retrieve the image or the image key from it, after a column is sorted.
Public Class SimpleForm
Inherits Form
Private sortItems = New ImageList()
Dim lv As ListView = New ListView()
Dim so = System.Windows.Forms.SortOrder.Ascending
Public Sub New()
' create columns, items and ListView
Dim columns = New List(Of ColumnHeader)
Dim c1 = New ColumnHeader()
c1.Name = "c1"
c1.Text = "Name"
Dim c2 = New ColumnHeader()
c2.Name = "c2"
c2.Text = "Type"
columns.Add(c1)
columns.Add(c2)
Dim items = New List(Of ListViewItem)
Dim i1 = New ListViewItem("Terminator")
i1.SubItems.Add("T1000")
Dim i2 = New ListViewItem("Terminator")
i2.SubItems.Add("T10")
Dim i3 = New ListViewItem("J.C.")
i3.SubItems.Add("Human")
items.Add(i1)
items.Add(i2)
items.Add(i3)
' init and bind column click
lv.Columns.AddRange(columns.ToArray())
lv.Items.AddRange(items.ToArray())
lv.SmallImageList = sortItems
lv.View = View.Details
lv.Dock = DockStyle.Fill
Controls.Add(lv)
AddHandler lv.ColumnClick, AddressOf clickEventHandler
' init images list
sortItems.TransparentColor = System.Drawing.Color.Transparent
sortItems.Images.Add("up", Image.FromFile("d:\temp\32\arrow_up.gif"))
sortItems.Images.Add("down", Image.FromFile("d:\temp\32\arrow_down.gif"))
sortItems.Images.Add("empty", Image.FromFile("d:\temp\32\check.gif"))
End Sub
Private Sub clickEventHandler(ByVal o As Object, ByVal e As ColumnClickEventArgs)
' Implement a custom ListViewItemSorter and fetch the icon from it!
' Set the ListViewItemSorter property to a new ListViewItemComparer
' object. Setting this property immediately sorts the
' ListView using the ListViewItemComparer object.
' THIS CODE SHOWS ONLY HOW TO SET THE SORT ICON!
For i As Integer = 0 To lv.Columns.Count - 1
If (i = e.Column) Then
Select Case (so)
Case System.Windows.Forms.SortOrder.Ascending
lv.Columns(i).ImageKey = "up"
so = System.Windows.Forms.SortOrder.Descending
Case System.Windows.Forms.SortOrder.Descending
lv.Columns(i).ImageKey = "down"
so = System.Windows.Forms.SortOrder.Ascending
Case Else
lv.Columns(i).ImageKey = "empty"
so = System.Windows.Forms.SortOrder.None
End Select
Else
lv.Columns(i).ImageKey = "empty"
End If
Next i
End Sub
End Class
The output looks like this:

DataGridView not Refreshing/Updating/Reloading Data. After Child form closes

This is a VB.NET, Winforms App. I have a datagridview on "Form1" that uses a databinding.datasource which is an Entity Framework table. I fill the datagridview with the below function on Form1:
Sub PM_UnitViewGrid()
Try
_form1.UnitsBindingSource.DataSource = db.units.Where(Function(f) f.propertyId = _form1.CurrentPropertyId).OrderBy(Function(F) F.unitNumber)
_form1.UnitDataGridView.DataSource = _form1.UnitsBindingSource.DataSource
Dim iCount As Integer = _form1.UnitDataGridView.RowCount
For x As Integer = 0 To iCount - 1
If Not IsNothing(_form1.UnitDataGridView.Rows(x).Cells(4).Value) Then
Dim tid As Integer = _form1.UnitDataGridView.Rows(x).Cells(4).Value
Dim _ten As tenant = db.tenants.Single(Function(f) f.Occupantid = tid)
_form1.UnitDataGridView.Rows(x).Cells(1).Value = _ten.first_name + ", " + _ten.last_name
Else
Dim btnColumn As DataGridViewButtonCell = CType(_form1.UnitDataGridView.Rows(x).Cells(1), DataGridViewButtonCell)
btnColumn.Style.BackColor = Color.Green
_form1.UnitDataGridView.Rows(x).Cells(1).Value = "VACANT"
End If
Next
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
Return
End Sub
This works great and also assigns the needed values to an unbound column. The problem is that the cells(1) is a button. Which when clicked takes the user to another form as a new dialog window. The function for which is below. However, once the changes are made in that form I need for the datagridview to refresh the data that its using from the database and show the correct data. As it stands right now the values are not updating on the datagridview unless the app is completely exited and restarted. Nothing I have found seems to work and Refresh and Update only redraw the control. I need the underlying datasource to refresh and then the datagridview once the child form is exited.. This has had me stumped for a good 36 hours now and I am lost as to why nothing I am trying is working. ANY and all help would be greatly appreciated.
The sub that loads the child form based on the cells(1) button clicked is as follows:
Private Sub UnitDataGridView_CellContentClick(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles UnitDataGridView.CellContentClick
UnitDataGridView.CommitEdit(DataGridViewDataErrorContexts.CurrentCellChange)
Dim y As DataGridViewCellEventArgs = e
Dim Tid As Integer = Nothing
If e.ColumnIndex = 1 Then
If Not e.RowIndex = -1 Then
If Not IsNothing(UnitDataGridView.Rows(e.RowIndex).Cells(4).Value) Then
currentTenent = UnitDataGridView.Rows(e.RowIndex).Cells(4).Value
TenentIdentification = currentTenent
If Not IsNothing(e) Then
If Not IsNothing(UnitDataGridView.Rows(e.RowIndex).Cells(4).Value) Then
Tid = UnitDataGridView.Rows(e.RowIndex).Cells(4).Value
Dim _ten As tenant = db.tenants.Single(Function(f) f.Occupantid = Tid) 'tenant is a table entity
TenantViewSubs.tenId = _ten.Occupantid
Dim t As New TenantView
t.tenId = tid
t.ShowDialog()
End If
End If
PropertyManagSubs.PM_UnitViewGrid() 'This is the function that is above that fills the datagridview
Else
Dim uTview As New UnassignedTenants
uTview.selectedProperty = selectedProperty 'selectedProperty is Integer
uTview.ShowDialog()
PropertyManagSubs.PM_UnitViewGrid() 'This is the function that is above that fills the datagridview
End If
End If
End If
End Sub
I tried each of the following code blocks after the t.ShowDialog() line with no change at all.
UnitDataGridView.Refresh()
.
UnitsBindingSource.Dispose()
UnitsBindingSource.DataSource = db.units.Where(Function(f) f.propertyId = selectedProperty).OrderBy(Function(f) f.unitNumber)
UnitDataGridView.DataSource = UnitsBindingSource.DataSource
.
UnitsBindingSource.DataSource = nothing
unitsBindingSource.DataSource = db.units.Where(Function(f) f.propertyId = selectedProperty).OrderBy(Function(f) f.unitNumber)
UnitDataGridView.DataSource = UnitsBindingSource.DataSource
I finally fixed this on my own.. It was in the way I passed my db context to the databinding..
I simply wrote the below sub:
Private Sub UpdateValues()
Dim context As New storageEntities 'storageEntities is an Entity
Dim query = context.units.Where(Function(F) F.propertyId = selectedProperty).OrderBy(Function(f) f.unitNumber)
UnitDataGridView.DataSource = query
End Sub
Then anytime a child form updated data I simply call
UpdateValues()
After the dialog box closes.
This may help someone else with the same problems so that is why I am posting it.