I have a VB.NET Windows Form with FlowLayoutPanel that will contain one or more text boxes. I would like to bind the collection of textboxes to a row(s) from a table in a SQL 2005 database using a dataset. As an example, I have a OrdersTable and an OrderItems table in the Parent-Child relationship. When adding new order items to a new order, I would like to add a new textbox control as the user adds items in the FlowLayoutPanel. A blank or empty textbox will signal the last items for that order. In addition, if a users navigates to an existing order, the FlowLayoutPanel would need to add the child rows as textboxes in the same order they were keyed.
My first approach was to just try and get user interface behavior (never mind the databinding yet) to work by adding a new textbox and naming it based on the current count of the control collection in the container:
Dim newTextBox As New TextBox
' the next line will throw an error at runtime...not sure why.
newTextBox.Name = "txtOrderItem" & sampleFlowLayoutPanel.Container.Components.Count
I have a command button that calls addOrderItem(). However, the above code throws and error becase the object is Nothing. I'm not sure why the object would be nothing since it contains at least one textbox when the program is launched.
Yes, that fixed the issue with counting the controls. However, the larger question of databinding was the focus of my question. The more I search and read up on complex databinding, the more I belive you can not directly bind a collection control to a dataset.
I'm open for suggestions on where to look for a solution. Below is what I have so far.
PrivateSub main_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
sampleFlowLayoutPanel.FlowDirection = FlowDirection.TopDown
addOrderItem()End Sub Private Sub addOrderItem() Dim tbOrderItem As New TextBox
tbOrderItem.Width = 150AddHandler tbOrderItem.GotFocus, New eventhandler(AddressOf Me.tb_GotFocus) AddHandler tbOrderItem.LostFocus, New eventhandler(AddressOf Me.tb_LostFocus)
tbOrderItem.Focus()End Sub Private Sub tb_GotFocus(ByVal sender As Object, ByVal e As EventArgs) Dim o As TextBox
o =CType(sender, TextBox)
o.BackColor = System.Drawing.Color.FromArgb _
(CType(CType(255, Byte), Integer), _ CType(CType(255, Byte), Integer), _ CType(CType(192, Byte), Integer)) End Sub Private Sub tb_LostFocus(ByVal sender As Object, ByVal e As EventArgs) Dim o As TextBox
o =CType(sender, TextBox)
o.BackColor = Color.WhiteIf o.Text.Length > 0 Then
addOrderItem()Else Me.sampleFlowLayoutPanel.Controls.Remove(o) End If End Sub Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
I guess that started out as a user requirement. That is to say that I'm replacing a legacy application that (in the past) presented the user with a CICS green screen that provided 10 blank fields that contained OrderItems. If the user had to enter 11 items, they would fill the 10 blank fields and request a new screen with 10 more blank fields. Once they keyed the eleventh item, they would return to the previous screen and continue to key additional fields. In the Windows version, I'm combining the old "green screens" into a Windows UI. Since the average number of actual order items is only 1 or 2, I didn't want to waste screen space with 10 blank fields or emulate the way the older mainframe application worked. Instead, I wanted to dynamically add as many blank fields as there are order items for that record without changing the relative location of the other fields. In most high speed data entry applications, you really need to have the same data entry fields in the same place each and every time. Hence the lame attempt as coded above. The other fly in the soup is that some fields are so tightly related, they need to be treated as a group and I need that same ability to present the user with as many "groups" of related fields as needed.
I'll take a peek at how much control I have over the layout of the datagrid like field spacing, the ability to scroll the datagrid, and if it will meet the requirements then I'll use that instead of trying to build a user control.
Iterate over your text boxes and add a Binding instance to each via TextBox.DataBindings.Add
I did something similar to your needs when a client wanted 'form' based editing as opposed to table based editing. I iterateted over the DataColumn's in the data source (DataTable) and added captions and controls (text boxes etc) based on information gathered from each DataColumn.
You don't need the extra blank fields - when you add a new row to the underlying data source the binding will clear out your bound controls.
You navigate the source by adjusting CurrencyManager.Position, and again, the binding will automatically populate your bound controls.
You can optionally handle parsing, formatting events on the Binding class to fine tune your data display.