Display members and Value members - vb.net

Hi I am new to VB platform, Can any one help me to understand the last few lines of code, here I highlight with bold at last, which is not understand or confusing to me. What does that Display member and value number do?
.. cmbcust is the combobox...
Where customer table are having following field.
**Customer_sname** **Customer_code** **Customer_fname**
nokia 1 nokia corp.
samsung 2 samsung corp.
sony 3 sony corp.
Micromax 4 Micromax India corp.
passing custval is nokia, samsung, sony
Public Function customfunc(ByVal custval As String) As DataSet
Try
Dim strSQL As String = "select * from customer where cust_sname in (" & custval & ")"
If Conn.State = ConnectionState.Open Then Conn.Close()
Conn.Open()
Dim Adap As New SqlDataAdapter(strSQL, Conn)
Dim Ds As New DataSet
Adap.Fill(Ds, "customer")
ReadINICustomers = Ds
Catch EXP As Exception
MsgBox("Error Connecting to Server :" & EXP.Message, MsgBoxStyle.Critical)
End Try
End Function
Public Sub Fillcustomer()
Dim Lstcust() As String
Dim Lstcust1 As String
Lstcust1 = ""
Lstcust1 = custINIval
Dim Ds As New DataSet
Ds = objData.ReadINICustomers(Lstcust1)
cmbcust.DataSource = Ds.Tables("customer")
cmbcust.DisplayMember = Ds.Tables("customer").Columns.Item("cust_sname").ToString().Trim()
cmbcust.ValueMember = Ds.Tables("customer").Columns.Item("cust_code").ToString().Trim()
End Sub
cmbcust.DisplayMember =
Ds.Tables("customer").Columns.Item("cust_sname").ToString().Trim()
cmbcust.ValueMember = Ds.Tables("customer").Columns.Item("cust_code").ToString().Trim()

When working in any of the .NET languages, such as VB.NET, the MSDN is your friend. It is the official resource for documentation regarding the languages and all of the types in the .NET Framework. In this case, you are asking about a couple of properties on the ComboBox control. The first thing you should do, then, is to search the MSDN for the ComboBox class. If you do so, you will find this article. It lists all of the members of the class and has a separate article explaining each one. If you scroll down through the list of properties, you will find links to articles for the DisplayMember property and the ValueMember property.
As those articles describe, the ComboBox control can contain any type of objects in its list of items. If you put something simple like a list of strings into the ComboBox, then its obviously easy for it to determine what to display in the list and what to return for its current value. However, when you place complex custom objects in the ComboBox, it's a more difficult proposition.
By default, it will display whatever the ToString method returns for each of the objects in its list. However, by setting the DisplayMember property, you can instruct it to use a particular member (such as a Property or Function) of the objects in the list instead of the ToString method. You do so by setting the DisplayMember property to the string name of the objects' member. It then uses reflection to find the member by that name in each of the objects and retrieve its value.
The ValueMember is very similar, but rather than controlling what gets displayed, it controls what gets returned by the SelectedValue property. By default, the SelectedValue property simply returns the entire object that was selected in the list. However, by setting the ValueMember, you can instruct it to just return the value of one particular member from the object rather than the whole thing.

Related

Is Databinding Textboxes in VB.net with a WHERE clause possible?

Is there a way to add databindings including a WHERE clause to sort which rows in the table get bound to which text boxes?
Serialnametxtbx.DataBinding.Add(New System.Windows.Forms.Binding("Text", Me.CoatingKitsBindingSource, "Serial_Number", True, DataSourceUpdateMode.OnValidation, nullValue As Object, formatString As String)
I'm not sure what one should use in the nullValue As Object location and the formatString As String location?
In the below code I have added a WHERE statement as to what I would like to sort this by but I am not sure where to implement it.
Serialnametxtbx.DataBinding.Add(New System.Windows.Forms.Binding("Text", Me.CoatingKitsBindingSource, "Serial_Number WHERE [Description] LIKE '%Banana%'", True, DataSourceUpdateMode.OnValidation, nullValue As Object, formatString As String)
Any suggestions? :)
The scenario here is there are 7 items to which need to be assigned as a group to say Kit #1. Each of these Items have similarities, Description, Unit Number, Serial Number,Make,Model,Last Calibration, Next Calibration, Calibration Company, Status and Condition. For each of the 7 Items there is different information that the user has input into each of these ten text boxes when they have added the piece of equipment. So I need to bind the piece of equipment's information to individual groups of text boxes on a form for that kit number.
So there are 10 text boxes for each piece of equipment in a kit and there are 7 pieces of equipment in a kit meaning 70 text boxes to the form. In the table there are the 10 columns for each piece and I would like to bind them as they differentiate by their description.
To select the kit number the user would like to edit I used a binding source filter on a combobox:
Me.Coating_KitsTableAdapter.FillBy(MacroQualityDataSet.Coating_Kits)
Me.CoatingKitsBindingSource.Filter = ("Unit_Number LIKE '%" & selectcktxtbx.Text & "%'")
And populated the list items in it with a dataset which is created when the form loads:
Dim ds As New DataSet
Dim cs As String = My.Settings.MacroQualityConnectionString
Dim sql As String = "SELECT DISTINCT Coating_Kits.Unit_Number FROM Coating_Kits"
Dim connection As New SqlConnection(cs)
Dim da As New SqlDataAdapter(sql, connection)
connection.Open()
da.Fill(ds, "Coating_Kits")
connection.Close()
selectcktxtbx.DataSource = ds.Tables(0)
selectcktxtbx.DisplayMember = "Unit_Number"
Can I maybe do a databinding off this dataset? I'm totally lost as usual.. :(
Use the Filter property of the BindingSource; the two mystery parameters to the Binding constructor are irrelevant (they represent DBNull replacements and display formatting strings respectively). Untested:
CoatingKitsBindingSource.Filter = "[Description] LIKE '%Banana%'"
Note also that you'll need multiple binding sources if you need different filters, or one control filtered and one not.

Need Suggestions For AutoSuggest For VB.NET ComboBox

To provide some context, I have a combobox that the user interacts with to select an insurance company. Unfortunately they don't require just the name; sometimes insurance companies have the same name, and the only way to distinguish between them is to use their address (eg a Medicare office in North Carolina vs. a Medicare office in South Carolina). What I've currently done is use the combobox's DrawItem event to draw a tooltip next to the ComboBox when the dropdown list is displayed. The list itself displays the insurance company names, but the tooltip will display the address of the currently selected company. The combobox is set to DropDownList, so it's impossible for them to pick anything but what's in the list.
Well, now I'm being told to change this. The users are no longer content to have to click the combobox or hit the arrow keys. They want comboboxes that they can type in and have an autosuggest list appear as they type. That's all well and good but this is where I'm running into a wall. My cute little scheme of using a tooltip can't work in that situation because the autosuggest list is a completely separate control. DrawItem doesn't touch it, and I can't find a way to custom draw the autosuggest list. The other problem is that autosuggest doesn't do duplicate entries, so even though I have two different insurance companies only one will appear in the list simply because they share the same name.
The only other idea I've had so far is to somehow scroll the dropdown list to the appropriate item upon the user pressing a key. But I can't figure out how to set the highlighted item in the dropdown list without setting selectedindex. If I use selectedindex, it goes ahead and replaces the text.
Does anyone have any suggestions for how to proceed? Am I on the right track, or do am I trying too hard and need to do something else entirely?
You could use a text field where the user types in their text, and narrow the selection in the dropbox down based on that. To get around the same-name-but-different-company problem, you could list the address of the company after the name in a parenthesis. If the user types in a name that is invalid, put up an error/warning icon next to the text field.
To update the selection at runtime, you can add an event listener to the text field and query the current text to decide whether it is a valid prefix, or not.
We do something similar at the company I'm at. To accomplish it, we utilize a web service through AJAX.
Essentially, you modify a standard textbox with an AJAX AutoCompleteExtender (ACE). This ace references a webservice (which I'll illustrate) that goes and gets the info the customer types in on the fly. It's pretty cool once it's up and running.
Here's an example:
.ascx
<asp:TextBox ID="txtInsuranceCompany" runat="server" TabIndex="520"
AutoComplete="Off"AutoCompleteType="Disabled" CssClass="asbSearch" Width="350px"></asp:TextBox>
<ajax:AutoCompleteExtender ID="aceInsuranceCompany" runat="server" CompletionSetCount="20"
MinimumPrefixLength="0" OnClientShown="resetPosition" ServiceMethod="LookupData"
ServicePath="~/WebLookUpService.asmx" TargetControlID="txtInsuranceCompany" UseContextKey="true">
</ajax:AutoCompleteExtender>
Something subtle is that you have to be sure you set the context key for your autocomplete extender, as well as create some functionality within your webservice to load your values (again, I'll illustrate).
.vb code-behind
Dim yourhardcodedlist As New List(Of String)
yourhardcodedlist.Add("Progressive")
yourhardcodedlist.Add("State Farm")
yourhardcodedlist.Add("USAA")
WebLookUpService.AddLookupValues(txtInsuranceCompany.ID, yourhardcodedlist.ToArray)
aceInsuranceCompany.ContextKey = public_var0 & ":" & public_var1 & ":" & txtInsuranceCompany.ID
Note that the "public_var0" "and public_var1" aren't mandatory. This is just illustrating how you could pass more information to your web service without actually passing it as a parameter (i.e. a colon-delimitted list, that you're web service function can parse out for use in a SQL statement or something).
Now for the webservice...(.asmx)
<WebService(Namespace:="http://tempuri.org/")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<System.Web.Script.Services.ScriptService()> _
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Public Class WebLookUpService
Inherits System.Web.Services.WebService
<System.Web.Services.WebMethod(), System.Web.Script.Services.ScriptMethod()> _
Public Function LookupData(ByVal prefixText As String, ByVal count As Integer, ByVal contextKey As String) As String()
'Construct SQL statement to pull from database
'parsing the context key as necessary to construct your SQL statement (if necessary)
'Dim somethingForSql As String = contextKey.Split(":")
Dim suggestions As List(Of String) = New List(Of String)
Try
Using cnADO As SqlConnection = New SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings("PublicSafetyServer").ToString)
cnADO.Open()
Dim dt As DataTable = New DataTable
Dim da As New SqlDataAdapter
da.SelectCommand = New SqlCommand("<YourSQLStatement>")
da.Fill(dt)
Dim endRow As Integer = dt.Rows.Count
If endRow > count Then
endRow = count
End If
For i As Integer = 0 To endRow - 1
Dim des As String = dt.Rows(i).Item(field)
Dim val As String = dt.Rows(i).Item(field)
suggestions.Add(AjaxControlToolkit.AutoCompleteExtender.CreateAutoCompleteItem(des, val))
Next
End Using
Catch ex As Exception
'Throw Error
End Try
suggestions.Sort()
If suggestions.Count = 0 Then
suggestions.Add(AjaxControlToolkit.AutoCompleteExtender.CreateAutoCompleteItem(noneFound, ""))
End If
Return suggestions.ToArray()
End Function
What's cool is that you can add values deliberately through 'yourhardcodedlist' that will combine with any values you pull via the web-service. This way, you can add values directly if you can't add values to the database.

Listbox Control Item - Multiple Names (and/or variables)?

I have a lot of data that's coming from a database and being adding to a listbox. The data that's coming from the database is a unique ID, and a name.
Is there any way I can make the item contain both the ID and name? I know I can append it, that's not what I'm looking to do. I need a way to be able to either get the ID, or get the name, while displaying them both.
I have gotten as far as creating a class:
Class Item
Property ID as Integer
Property Name as String
Sub New(ID as Integer, Name as String)
Me.ID = ID
Me.Name = Name
End Sub
Overrides Function ToString() as String
Return Name
End Function
End Class
That looks like it should do the trick, but I'm having trouble getting the ID, instead of the name. To put it simply, I wish I could do this: listbox1.selecteditem(id) to get the id, or listbox1.selecteditem(name) to get the name.
Any ideas on how to implement this?
You can bind to a List(Of Item) like this:
Dim ItemList = New List(Of Item)
' Fill the list with appropiate values.'
listbox1.DataSource = ItemList
listbox1.DisplayMember = "Name"
listbox1.ValueMember = "ID"
Then listbox1.SelectedValue holds the ID and you can access the name like this:
DirectCast(listbox1.SelectedItem, Item).Name
If you want to show both the ID and the Name, then I suggest you add a property to be the displayed value in the Itemclass:
Public ReadOnly Property DisplayedValue() as String
Get
Return Me.Name & " (" & Me.ID.ToString & ")"
End Get
End Property
Then when binding the list make
listbox1.DisplayMember = "DisplayedValue"
Update:
Based on your comments below I'd say my solution still works. However with this methodology the items must be added to the list and then the list bound to the object. The items can not be added individually and directly to the list box (as you would be separating data from presentation I don't see that as a problem).
To show a message box with the selected item then you just need to do:
MessageBox.Show(DirectCast(listbox1.SelectedItem, Item).ID.ToString))
I think you'll have to write a helper method to do this. If you're using VB 3.5 or newer (part of VS2008 and newer) you can write an extension method so that you can at least get nice syntax. You could write one such that it looked like:
listbox1.SelectByID(123)
listbox1.SelectByName("hello")
In the methods you'd have some search algorithm that went through the items and found the right one.

How do I update a single table of a DataSet using a TableAdapter, without hard-coding the table name?

This seems like a really basic thing that I'm doing, yet I'm tearing my hair out trying to make it work.
My situation is this: I have a project which contains a large number of lookup tables, and I have all of these lookup tables represented in a single typed DataSet, which contains TableAdapters for each lookup. I've designed an editor for these lookup tables, which should allow editing of one of these at a time. My front-end is written in VB and WinForms, the back-end is a SOAP web service; I can successfully pass the changes to the DataSet back to the web service, but can't find a way to use a TableAdapter to update the single table that has been changed.
What I'm trying to do is instantiate the appropriate TableAdapter for the updated DataTable by sending the name of the table back to the web service along with the DataSet, then referring to the TableAdapter with a dynamic name. The normal way to instantiate a TableAdapter is this:
Dim ta As New dsLookupsTableAdapters.tlkpMyTableTableAdapter
What I'd like to do is this, but of course it doesn't work:
strTableName = "tlkpMyTable"
Dim ta As New dsLookupsTableAdapters(strTableName & "TableAdapter")
Is there any way to achieve this, or am I taking the wrong approach altogether? My other alternative is to write separate code for each table, which I'd prefer to avoid!
You can use Activator to create an instance of your TableAdapter from its string name, just like you want:
object adapter = Activator.CreateInstance(Type.GetType("My.Namespace.MyDataSetTableAdapters." + myTable.Name + "TableAdapter"));
Then, because TableAdapters don't have a common interface, you should use reflection to call its Update method:
adapter.GetType().GetMethod("Update").Invoke(adapter, null);
http://msdn.microsoft.com/en-us/library/system.type.getmethod.aspx
This is from memory, but roughly close enough. You can also use GetProperty to get the connection property and set it as required.
Not sure I 100% understand, do you have a single DataTable in your DataSet, or one DataTable per lookup table?
Anyway, perhaps you could you this approach to filter by lookup table?
It's pretty easy to create types at runtime given the (string) type name.
Here's a self-contained VB class which illustrates one way to do it: use System.Activator.CreateInstance to create instances of types using a string representation of the type name. Then you can cast it to a DataAdapter base class and use it like any other DataAdapter.
Public Class dsLookupsTableAdapters
Public Function CreateInstance(ByVal strName As String) As Object
CreateInstance = Nothing
For Each a As System.Reflection.Assembly In System.AppDomain.CurrentDomain.GetAssemblies()
Try
Dim strAssemblyName As String() = a.FullName.Split(New Char() {","c})
Dim strNameTemp As String = strAssemblyName(0) & "." & strName
Dim instance As Object = System.Activator.CreateInstance(a.FullName, strNameTemp)
If instance IsNot Nothing Then
Dim handle As System.Runtime.Remoting.ObjectHandle
handle = CType(instance, System.Runtime.Remoting.ObjectHandle)
Dim o As Object = handle.Unwrap()
CreateInstance = o
Exit For
End If
Catch ex As System.Exception
Continue For ' ignore exception, means type isn't there
End Try
Next
End Function
Public Class tlkpMyTableTableAdapter
Inherits System.Data.Common.DataAdapter
End Class
Public Sub Test()
' define type name. note that, in this sample, tlkpMyTableTableAdapter is a nested
' class and dsLookupsTableAdapters is the containing class, hence the "+". If, however,
' dsLookupsTableAdapters is a namespace, replace the "+" with a "."
Dim typeName As String = "dsLookupsTableAdapters+tlkpMyTableTableAdapter"
Dim adapter As System.Data.Common.DataAdapter
Dim o As Object = CreateInstance(typeName)
adapter = CType(o, System.Data.Common.DataAdapter)
End Sub
End Class
If you are using VB.Net 2008, then use the tableadaptermanager (http://msdn.microsoft.com/en-us/library/bb384426.aspx). I think this would be much easier to code against :)
Wade

ComboBox DataBinding DisplayMember and LINQ queries

Update
I decided to iterate through the Data.DataTable and trimmed the values there.
Utilizing SirDemon's post, I have updated the code a little bit:
Sub test(ByVal path As String)
Dim oData As GSDataObject = GetDataObj(path)
EmptyComboBoxes()
Dim oDT As New Data.DataTable
Try
Dim t = From r In oData.GetTable(String.Format("SELECT * FROM {0}gsobj\paths ORDER BY keyid", AddBS(path))) Select r
If t.Count > 0 Then
oDT = t.CopyToDataTable
For Each dr As Data.DataRow In oDT.Rows
dr.Item("key_code") = dr.Item("key_code").ToString.Trim
dr.Item("descript") = dr.Item("descript").ToString.Trim
Next
dataPathComboBox.DataSource = oDT
dataPathComboBox.DisplayMember = "descript"
dataPathComboBox.ValueMember = "key_code"
dataPathComboBox.SelectedIndex = 0
dataPathComboBox.Enabled = True
End If
Catch ex As Exception
End Try
End Sub
This works almost as I need it to, the data is originally from a foxpro table, so the strings it returns are <value> plus (<Field>.maxlength-<value>.length) of trailing whitespace characters. For example, a field with a 12 character length has a value of bob. When I query the database, I get "bob_________", where _ is a space.
I have tried a couple of different things to get rid of the whitespace such as:
dataPathComboBox.DisplayMember.Trim()
dataPathComboBox.DisplayMember = "descript".Trim.
But nothing has worked yet. Other than iterating through the Data.DataTable or creating a custom CopyToDataTable method, is there any way I can trim the values? Perhaps it can be done in-line with the LINQ query?
Here is the code I have so far, I have no problem querying the database and getting the information, but I cannot figure out how to display the proper text in the ComboBox list. I always get System.Data.DataRow :
Try
Dim t = From r In oData.GetTable("SELECT * FROM ../gsobj/paths ORDER BY keyid") _
Select r
dataPathComboBox.DataSource = t.ToList
dataPathComboBox.SelectedIndex = 0
'dataPathComboBox.DisplayMember = t.ToList.First.Item("descript")
dataPathComboBox.Enabled = True
Catch ex As Exception
Stop
End Try
I know that on the DisplayMember line the .First.Item() part is wrong, I just wanted to show what row I am trying to designate as the DisplayMember.
I'm pretty sure your code tries to set an entire DataRow to a property that is simply the name of the Field (in a strongly type class) or a Column (in a DataTable).
dataPathComboBox.DisplayMember = "descript"
Should work if the DataTable contains a retrieved column of that name.
Also, I'd suggest setting your SelectedIndex only AFTER you've done the DataBinding and you know you actually have items, otherwise SelectedIndex = 0 may throw an exception.
EDIT: Trimming the name of the bound column will trim just that, not the actual bound value string. You either have to go through all the items after they've been bound and do something like:
dataPathComboBox.Item[i].Text = dataPathComboBox.Item[i].Text.Trim()
For each one of the items. Not sure what ComboBox control you're using, so the item collection name might be something else.
Another solution is doing that for each item when it is bound if the ComboBox control exposes an onItemDataBound event of some kind.
There are plenty of other ways to do this, depending on what the control itself offers and what you choose to do.
DisplayMember is intended to indicate the name of the property holding the value to be displayed.
In your case, I'm not sure what the syntax will by since you seem to be using a DataSet, but that should be
... DisplayMember="Item['descript']" ...
in Xaml, unless you need to switch that at runtime in which case you can do it in code with
dataPathComboBox.DisplayMember = "Item['descript']"
Again, not 100% sure on the syntax. If you are using a strongly typed DataSet it's even easier since you should have a "descript" property on your row, but given hat your error indicates "System.DataRow" and not a custom type, I guess you are not.
Because I can't figure out the underlying type of the datasource you are using I suggest you to change commented string to
dataPathComboBox.DisplayMember = t.ElementType.GetProperties.GetValue(0).Name
and try to determine correct index (initially it is zero) in practice.