ObjectListView adding items to it - vb.net

I am a bit lost and I would like to add some items to a Fast ObjectListView. what I have is not working, and I cant seem to find anything online with vb.net samples
Dim LvItm As BrightIdeasSoftware.OLVListItem = lstMain.Items.Add("title")
With LvItm
.SubItems.Add("name")
.SubItems.Add("last")
.SubItems.Add("phone")
.SubItems.Add("address")
.EnsureVisible()
End With

ObjectListView works completely different from normal ListView, usually you dont add individual items.
In short:
- create columns
- set aspect names of created columns to property names of your objects
- point objectlistview to list of objects
See example below:
Imports BrightIdeasSoftware
Public Class Person
Public Property name As String
Public Property last As String
Public Property phone As String
Public Property address As String
End Class
Dim LvItm As New Person With {.name = "John",
.last = "Smith",
.phone = "555-69997-44",
.address = "Main Str. 1"}
Dim LvLst As New List(Of Person)
LvLst.Add(LvItm)
ObjectListView1.View = View.Details
ObjectListView1.Columns.Add(New OLVColumn With {.Text = "Name",
.AspectName = "name"})
ObjectListView1.Columns.Add(New OLVColumn With {.Text = "Last Name",
.AspectName = "last"})
ObjectListView1.Columns.Add(New OLVColumn With {.Text = "Phone",
.AspectName = "phone"})
ObjectListView1.Columns.Add(New OLVColumn With {.Text = "Address",
.AspectName = "address"})
ObjectListView1.SetObjects(LvLst)
With everything set-up you can add items to the list or manipulate in any way,
hitting ObjectListView1.SetObjects(LvLst) again to refresh view.
You can also add items to ObjectListView directly:
Dim p As New Person
p.name = "Steve"
p.last = "Wilson"
p.phone = "777-888-9987"
p.address = "First Str. 1"
ObjectListView1.AddObject(p)
Remember that items added directly were not added to your List(Of Person)

Related

Difference between two Lamba Expressions in LINQ

I am trying to understand the difference between these two Lambda Expressions within LINQ Join method.
The two lines I do not understand are those starting with Function(aaa) ... and Function(bbb) ....
Why do I have explicitly name the field Name in the second example for both aaa and bbbwhile in the first one it works without it?
On the other hand in the first example bbb.Owner points to Owner field of Pet but it does not tell that Name field of the Person shall be used to make the join.
First example (comes from .Net Framework documentation with variable names changed):
Structure Person
Public Name As String
Public SecondName As String
End Structure
Structure Pet
Public Name As String
Public Owner As Person
End Structure
Dim magnus As New Person With {.Name = "Hedlund, Magnus"}
Dim terry As New Person With {.Name = "Adams, Terry"}
Dim charlotte As New Person With {.Name = "Weiss, Charlotte"}
Dim barley As New Pet With {.Name = "Barley", .Owner = terry}
Dim boots As New Pet With {.Name = "Boots", .Owner = terry}
Dim whiskers As New Pet With {.Name = "Whiskers", .Owner = charlotte}
Dim daisy As New Pet With {.Name = "Daisy", .Owner = magnus}
Dim people As New List(Of Person)(New Person() {magnus, terry, charlotte})
Dim pets As New List(Of Pet)(New Pet() {barley, boots, whiskers, daisy})
Dim query = people.Join(pets,
Function(aaa) aaa,
Function(bbb) bbb.Owner,
Function(ccc, ddd) _
New With {.OwnerName1 = ccc.Name, .Pet1 = ddd.Name})
Second example (my code)
Structure MyObject
Public Name As String
Public Value As Integer
End Structure
Dim Test1 As New List(Of MyObject) From {
New MyObject With {.Name = "a", .Value = 1},
New MyObject With {.Name = "b", .Value = 2},
New MyObject With {.Name = "c", .Value = 3}
}
Dim Test2 As New List(Of MyObject) From {
New MyObject With {.Name = "a", .Value = 11},
New MyObject With {.Name = "b", .Value = 22},
New MyObject With {.Name = "c", .Value = 33}
}
Dim Joined = Test1.Join(Test2,
Function(aaa) aaa.Name,
Function(bbb) bbb.Name,
Function(ccc, ddd) New With {
.Name1 = ccc.Name,
.Value1 = ccc.Value,
.Value2 = ddd.Value})
IF you look at the documentation, you'll see that the first function is the selector for the outer sequence and the second is the selector for the inner sequence.
The value form the inner and outer selectors must have the same type (TKey) and will be compared using the default comparer for that type (there's an overload that allows you to pass a comparer).
The third function is the result selector that receives a TOuter and a TInner instances that match according to the selected keys and returns a TResult value.
So, in the first example TKey is Person. outerSelector and innerSelector must return a Person, thus aaa and bbb.
On the second example you chose to compare the Name field and not the entire MyObject structure.

Windows Form App Changing the data in a data grid view based on a Combo box selection

Sorry I'm relativley new to Visual and learning for school but I can't work out how to change the data displayed in a Data Grid View based on a selection in a combo box.
Any help would be much appreciated
Here is one example with LINQ and List(Of Producer)(_allProducers) assigned to DataSource of the DataGridView (grdProducers) and ComboBox(cmbProducers)
Class Producer
Public Property ID As Integer
Public Property NAME As String
Public Property COMPANY_ID As Integer
End Class
Private _allProducers As List(Of Producer) = New List(Of Producer)
Fill _allProducers List:
_allProducers = {
New Producer() With {.ID = 1, .NAME = "John", .COMPANY_ID = 2},
New Producer() With {.ID = 2, .NAME = "Sam", .COMPANY_ID = 3},
New Producer() With {.ID = 3, .NAME = "Smith", .COMPANY_ID = 2},
New Producer() With {.ID = 4, .NAME = "Dan", .COMPANY_ID = 1}
}.ToList()
Init ComboBox:
cmbProducers.DropDownStyle = ComboBoxStyle.DropDown
cmbProducers.DataSource = _allProducers
cmbProducers.DisplayMember = "NAME" 'value to display in combo
cmbProducers.ValueMember = "COMPANY_ID" 'value to return
Now you can set SelectedIndexChanged event on the cmbProducers ComboBox. This event occurs when the SelectedIndex property has changed.
Private Sub cmbProducers_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cmbProducers.SelectedIndexChanged
if (IsNumeric(cmbProducers.SelectedValue)) Then 'check for numeric values
grdProducers.DataSource = _allProducers.Where(Function(p) p.COMPANY_ID = cmbProducers.SelectedValue).ToList()
EndIf
End Sub
In this case _allProducers List will be filtered and will return all objects which COMPANY_ID is equal to the value selected in the ComboBox.
I hope this can help you.

VB.net Objectlistview filtering column by range of numbers

I have an objectlistview with a column of numbers ranging from -3000 to 10000. I need to apply a filter for anything less than 2000 (this should include all the negative numbers as well). I've read the examples and help (http://objectlistview.sourceforge.net/cs/filtering.html#filtering-label) but it's in C# and I'm working with VB.net. I can normally figure the conversion out but this one is stumping me.
I have another piece of code that uses a function instead of a delegate (when applying an image) but I couldn't get it to work in this filtering instance. I also tried using a regex but I just feel that since I'm dealing with numbers I should do it without regex.
Can someone please show me a custom filtering example with number ranges in VB.net to help me get over this?
Thanks!
Here is an example I threw together:
When you click "Apply Filter", it should only show Mary Swanson and Jiminy Cricket (both under a height of 30).
Here is the code I used to create the olv
Private Sub Button3_Click_1(sender As Object, e As EventArgs) Handles Button3.Click
Dim LvLst As New List(Of Person)
Dim LvItm As New Person With {.FirstName = "Joe",
.LastName = "Blow",
.Glasses = "Y",
.Height = "75",
.HeightBar = "75"}
LvLst.Add(LvItm)
Dim LvItm2 As New Person With {.FirstName = "Mary",
.LastName = "Swanson",
.Glasses = "N",
.Height = "25",
.HeightBar = "25"}
LvLst.Add(LvItm2)
Dim LvItm3 As New Person With {.FirstName = "Mike",
.LastName = "Tyson",
.Glasses = "N",
.Height = "125",
.HeightBar = "125"}
LvLst.Add(LvItm3)
Dim LvItm4 As New Person With {.FirstName = "Jiminy",
.LastName = "Cricket",
.Glasses = "Y",
.Height = "-9",
.HeightBar = "-9"}
LvLst.Add(LvItm4)
ObjectListView3.View = View.Details
Dim myImages = New ImageList
myImages.Images.Add(My.Resources.Hipster_Glasses_icon)
myImages.Images.Add(My.Resources.Button_important_icon)
ObjectListView3.SmallImageList = myImages
ObjectListView3.UseCellFormatEvents = True
ObjectListView3.OwnerDraw = True
Col_Glasses.ImageGetter = Function(x As Object) As Integer
Dim casted As Person = DirectCast(x, Person)
If casted.Glasses = "Y" Then
Return 0
Else
Return 1
End If
End Function
Col_Height.Renderer = New BarRenderer(0, 100, Pens.Black, Brushes.Gold)
'Set no data message
ObjectListView3.EmptyListMsg = "No Data Found"
ObjectListView3.EmptyListMsgFont = New Font("Tahoma", 18)
'Allows you to type and search inside the olv
ObjectListView3.IsSearchOnSortColumn = True
ObjectListView3.SetObjects(LvLst)
End Sub
And this is the code behind the filter button that I need help on
Private Sub Button1_Click_1(sender As Object, e As EventArgs) Handles Button1.Click
ObjectListView3.ModelFilter = Function(x As Object) As ModelFilter
Dim casted As Person = DirectCast(x, Person)
If casted.Height <= CInt(HeightFilter.Text) Then
Return x
End If
End Function
End Sub
Person Class
Public Class Person
Public Property FirstName As String
Public Property LastName As String
Public Property Glasses As String
Public Property Height As Integer
Public Property HeightBar As Integer
End Class
The error says that IModelFilter is not a delegate type. I don't know what i should be returning from the function?? Do you see the imagegetter I used for the glasses column? I was trying to use the same approach but I've never used it for a IModelFilter. Thanks for the help!
Set the filter to a new ModelFilter. x is the object being passed into the function, cast it to your Personclass, then filter by height. The filter basically returns True (to keep it) or False (to filter it out) as it processes each Person.
ObjectListView3.ModelFilter = New BrightIdeasSoftware.ModelFilter(Function(x) CType(x, Person).Height <= CInt(Me.HeightFilter.Text))

How to bind the selected member of a ComboBox?

I have a ComboBox that is populated with objects of type ProfileName
Private Class ProfileName
Public Property Name As String
Public Property File As String
Public Property ProductVersion As String
End Class
These items are created added to the combo box after a deserialising a bunch of files and copying some of the values from the resulting objects:
pcb.DisplayMember = "Name"
For Each F As FileInfo In ProfileFiles
Dim Reader As StreamReader = F.OpenText()
Dim Serialize As Serializer = New Serializer()
Dim SerializedData As String = Reader.ReadToEnd()
Dim P As Profile = Serialize.DesearializeObject(Of Profile)(SerializedData)
If P.Type = Profile.ProfileType.Product Then
Dim PN As ProfileName = New ProfileName()
PN.File = F.Name
PN.ProductVersion = P.ProductVersion
PN.Name = P.ProductName & " - " & P.ProductVersion
pcb.Items.Add(PN)
End If
Reader.Close()
Next
Then if a user opens one of these files, the file will be again deserialised resulting in a Profile object with a 'ProductName' property that should match one of the items already on the ComboBox items list, so I'd like for the ComboBox to show that as the selected item.
i.e.
-On form load the ComboBox is populated with all possible product names.
-When a profile file is opened the product that the profile uses is automatically selected in the ComboBox.
I've been playing with
ProductComboBox.DataBindings.Add("SelectedValue", CurrentProfile, "ProductName")
and permutations thereof, but can't seem to get it right.
You cant mix and match - put objects into the items collection and use the data binding methods/elements. Databinding basics:
Public Class Profile
Public Property Name As String
Public Property File As String
Public Property ProductVersion As String
Public Overrides Function ToString() As String
Return String.Format("{0} ({1})", Name, ProductVersion)
End Function
End Class
The ToString() controls what will be displayed when you cant specify the property to display. Note, these should be properties becaus mere Fields will be treated differently.
Then a container for them. This will be the DataSource for the cbo.
Private Profiles As List(Of Profile)
...
' create instance of list and populate from where ever:
Profiles = New List(Of Profile)
Profiles.Add(New Profile With {.Name = "Default", .File = "foo",
.ProductVersion = "1.0"})
Profiles.Add(New Profile With {.Name = "Ziggy", .File = "bat",
.ProductVersion = "1.9.8"})
Profiles.Add(New Profile With {.Name = "Zoey", .File = "bar",
.ProductVersion = "1.4.1"})
Rather than putting the Profile objects into the Items collection, bind the control to the List:
cboP.DataSource = Profiles
cboP.DisplayMember = "Name"
If you omit the property to display, ToString() will be shown (or WindowsApp1.Profile if you did not override it). Note: When using a DataSource you no longer add or delete from the control's Items collection - it will yell at you. Instead manage the underlying source, your List(Of Profile) in this case.
To change the selection, for example to the one for "Ziggy":
Dim n As Int32 = Profiles.FindIndex(Function(f) f.Name = "Ziggy")
If n > -1 Then
cboP.SelectedIndex = n
End If
You can also set SelectedItem after you find the Profile instead, but I tend to use index. Even though the list is a new actor, serializing the entire thing is easy:
' serializing the List acts on all the profiles in it
Dim json = JsonConvert.SerializeObject(Profiles)
File.WriteAllText("C:\Temp\Profiles.json", json)
Read it back:
json = File.ReadAllText("C:\Temp\Profiles.json")
Dim newPs = JsonConvert.DeserializeObject(Of List(Of Profile))(json)
Its a bit simpler than looping thru a set of files. List(of T) has a full set of methods and extensions to remove, sort, find etc so you should gain functionality over the items collection or array.
Alternatively, you could keep the one file per structure, but add the deserialized Profile objects to a List(of Profile) rather than the Items collection.

Add object to listbox and use different string representations depending on the listbox?

I have a coupple of listboxes with the same object type in all of them, the problem i have is that i dont want the object displayed with the same ToString() method in all of the listboxes. Is there a way to solve this?
At the moment im adding strings to the listboxes and then i use the selected string to search a list of objects for the correct one but i dont like that solution at all.
Suppose to have a class for Employees like this one:
Public Class Employee
Public Property ID As Integer
Public Property FirstText As String
Public Property SecondText As String
' and go on with other properties
....
End Class
Now when you populate your listboxes, you set the DisplayMember and ValueMember of your listboxes to two different property of Employee
Dim myList As ArrayList = New ArrayList()
myList.Add(New Employee() With {.ID = 1, .FirstText = "John Doe", .SecondText = "Doe John"})
myList.Add(New Employee() With {.ID = 2, .FirstText = "Mark Ross", .SecondText = "Ross Mark"})
ListBox1.DataSource = myList
ListBox2.DataSource = myList
ListBox1.ValueMember = "ID"
ListBox1.DisplayMember = "FirstText"
ListBox2.ValueMember = "ID"
ListBox2.DisplayMember = "SecondText"