I'm looking to bind a specific element of a list.
Public Class itemCATIA
Property l As New List(Of itemCATIAProperties) 'the list
Sub New(d)
For Each item As Parameter In pCATIA.UserRefProperties
Dim myP As New itemCATIAProperties(item.Name,
item.ValueAsString)
l.Add(myP) 'the list
Next
end sub
end class
Public Class itemCATIAProperties
Property Name As String
Property Value As String
Sub New(item As String, _value As String)
Dim s() As String = Strings.Split(item, "\")
Name = s(UBound(s))
Value = _value
End Sub
End Class
and below my tests to bind the correct value inside a dynamically created column :
Private Sub Window_Loaded(sender As Object, e As RoutedEventArgs)
Dim c As New DataGridTextColumn
c.Header = "MASS"
c.Binding = New Binding("l[Name='MASS'].Value") 'does not work
c.Binding = New Binding("l[0].Value") 'does not return the good index of my list l. i want index=c.header
MaDataGrid.Columns.Add(c)
End Sub
Is there a method to retrieve the value whose index is the column header ?
Thanks a lot :)
Well i resolved with something not very beautiful.. if someone get a best solution, i take :)
i replaced in the sub new() :
Dim l_ As New List(Of itemCATIAProperties)
For Each item As Parameter In pCATIA.UserRefProperties
Dim myP As New itemCATIAProperties(item.Name, item.ValueAsString)
l_.Add(myP)
Next
For i = 1 To 30
l.Add(Nothing)
Next
For Each item In l_
Select Case item.Name
Case "MATERIAL"
l(0) = item
Case "OBSERVATIONS"
l(1) = item
Case "LENGTH"
l(2) = item
Case "LENGTH"
l(3) = item
Case "THICKNESS/DIAMETER"
l(5) = item
Case "MASS"
l(5) = item
Case "SUPPLIER"
l(6) = item
Case "REF"
l(7) = item
Case "TTS"
l(8) = item
Case "SYM"
l(9) = item
Case "NomPuls_Marquage"
l(10) = item
Case "NomPuls_Traitement"
l(11) = item
Case "NomPuls_Protection"
l(12) = item
Case "NomPuls_Dim_Brutes"
l(13) = item
Case "NomPuls_Masse"
l(14) = item
Case "NomPuls_Matiere"
l(15) = item
Case "NomPuls_Designation"
l(16) = item
Case "NomPuls_Indice"
l(17) = item
Case "NomPuls_Planche"
l(18) = item
Case "DETAIL NUMBER"
l(19) = item
Case "STOCK SIZE"
l(20) = item
End Select
Next
Related
eg A "Label" the value is stored in "Caption" whilst a Textboxes uses "Value" Please...
...but elegantly
I know I could use and "if then" statement ... but I see it getting messy pretty quick.
Dim propValue(2, 2) As String
propValue(0, 1) = "SomeInfo"
propValue(1, 1) = "lblReference"
propValue(2, 1) = "Caption"
propValue(0, 2) = "MoreInfo"
propValue(1, 2) = "tboxReference"
propValue(2, 2) = "Value"
Dim element As Integer
For element = 1 To 2
UserForm1.Controls(propValue(1, element)).propValue(2, element) = propValue(0, element)
Next element
Many thanks.
As I tried saying in my comment, it is not possible to use a string (extracted from an array or not) as an Object Property. The next code store a string defining the control type and use it in the following way:
Sub testModifFormControlsProperties()
Dim propValue(2, 2) As String
propValue(0, 1) = "SomeInfo": propValue(1, 1) = "lblReference"
propValue(2, 1) = "Label" 'store the control type as String
propValue(0, 2) = "MoreInfo": propValue(1, 2) = "tboxReference"
propValue(2, 2) = "TextBox" 'store the control type as String
Dim element As Integer, ctrl As MSForms.Control
For element = 1 To 2
Set ctrl = UserForm1.Controls(propValue(1, element)) 'to make a compact code
Select Case propValue(2, element)
Case "TextBox": ctrl.Text = propValue(0, element)
Case "Label": ctrl.Caption = propValue(0, element)
End Select
Next element
UserForm1.Show
End Sub
For the additional price of a very simple data object, the following is an approach that avoids using a 2-d Array. You could use a Collection or an Array with this implementation.
Option Explicit
Private Sub InitTextBoxesAndLabels()
Dim propValue(1) As Variant
Set propValue(0) = CreateTextBoxOrLabel("Label1", "MoreInfo", True)
Set propValue(1) = CreateTextBoxOrLabel("TextBox1", "SomeInfo", False)
Dim dElement As TextBoxOrLabel
Dim element As Long
For element = 0 To 1
Set dElement = propValue(element)
If dElement.IsLabel Then
UserForm1.Controls(dElement.ControlName).Caption = dElement.Content
Else
UserForm1.Controls(dElement.ControlName).Value = dElement.Content
End If
Next
End Sub
Private Function CreateTextBoxOrLabel(ByVal pControlName As String, _
pContent As String, pIsLabel As Boolean) As TextBoxOrLabel
Set CreateTextBoxOrLabel = New TextBoxOrLabel
With CreateTextBoxOrLabel
.ControlName = pControlName
.Content = pContent
.IsLabel = pIsLabel
End With
End Function
TextBoxOrLabel data object
Option Explicit
Public IsLabel As Boolean
Public Content As String
Public ControlName As String
I am trying to order the largest scores in a file that is loaded into an array. Currently, the program opens the file, then reads it and then splits up each line into two parts - a name and a score; then stores that in an array. I am not sure how I can sort the array to find the largest 10 scores and put that into a listbox. At the moment, the program finds any scores above 0 and puts it in the listbox
Dim FileNum As Integer = FreeFile()
FileOpen(FileNum, "GameResultsFile", OpenMode.Input)
For index = 0 To 99
Dim temp() As String = LineInput(FileNum).Split(",") 'CUTTING LINE INTO TWO SECTIONS
MemoryGame.HighScores(index).Name = temp(0) 'NAME (First Part of Line)
MemoryGame.HighScores(index).Score = temp(1) 'SCORE (Second Part of Line)
If temp(1) > 0 Then 'If any of the scores is above 0 then
ListBox1.Items.Add(temp(0) + " " + temp(1)) ' display the name of the person who got that score and their score
End If
Next
FileClose()
Comments and explainations in line
'Note Imports System.IO
Structure Player
Public Score As Integer
Public Name As String
'Added a constructor to the structure to make it easy to add new Player
Public Sub New(myScore As Integer, myName As String)
Score = myScore
Name = myName
End Sub
End Structure
Private HighScores(99) As Player
Private index As Integer 'used in both LoadArray and SortAndDisplayArray
Private Sub LoadArray()
Using sr As New StreamReader("GameResultsFile.txt")
Dim line As String
Do While sr.Peek() > -1 'Peek checks if there is another character in the file
line = sr.ReadLine()
Dim temp() As String = line.Split(","c) 'CUTTING LINE INTO TWO SECTIONS
'Notice the elements of the temp array are switched to match the
'Player constructor (Sub New)
HighScores(index) = New Player(CInt(temp(1)), temp(0))
index += 1 'not only keeps track of the index but remembers how many elements
'we have added to HighScores
Loop
End Using
End Sub
Private Sub SortAndDisplayArray()
'This is the LINQ way to do it, you can do a great deal in one line of code
'There is a loop underneath but you don't have to write it.
'I added a Take clause so we will not get a bunch of 0- in the list box going up to index 99
' You might want to show, for example only the top ten scorers, so change to Take 10
Dim orderArray = From scorer In HighScores Order By scorer.Score Descending Select $"{scorer.Score} - {scorer.Name}" Take index
ListBox1.DataSource = orderArray.ToList
End Sub
I still think a List(Of T) would be easier but I have a feeling your assignment requires you to use an array.
I'd do it something like this using IComparable
First I would load the data from your text file like so and save the data to a List Of and the Type would be the Player class down below.
'' Get Data From Text File And Create An Anonymous Type
Private Sub LoadPlayerAndScore(path As String)
'' Load data from text file
Dim data = From line In System.IO.File.ReadAllLines(path)
Let val = line.Split(",")
Select New With {Key .Name = val(0), Key .Score = val(1)}
'' Save data to list
For Each pair In data
Dim player As New Player With {
.Name = pair.Name,
.Score = pair.Score
}
playersList.Add(player)
Next
End Sub
I would then go on to create a player class which will Implement the ICompareble listed above.
Class Player
Implements IComparable(Of Player)
Public Property Name As String
Public Property Score As Integer
Public Sub Player(ByVal name As String, ByVal score As Integer)
Me.Name = name
Me.Score = score
End Sub
'' Sort Player From The Hightest Score To The Lowest Score
Private Function IComparable_CompareTo(other As Player) As Integer Implements IComparable(Of Player).CompareTo
Return other.Score.CompareTo(Me.Score)
End Function
End Class
I would then create some public variables such as
Dim playersList As New List(Of Player)
Dim fileLocation As String = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "Settings.txt")
Change the path to your file's location.And finally in a Form Load Event I would call it all like this
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
'' Load Data From Text File On Desktop
LoadPlayerAndScore(path:=fileLocation)
'' Sort List
playersList.Sort()
'' Add Values To List
For Each p As Player In playersList
ListBox1.Items.Add("Name: " + p.Name + " Score: " + p.Score.ToString())
Next
End Sub
Here is what the code should look something like altogether
Public Class Form1
Dim playersList As New List(Of Player)
Dim fileLocation As String = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "Settings.txt")
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
'' Load Data From Text File On Desktop
LoadPlayerAndScore(path:=fileLocation)
'' Sort List
playersList.Sort()
'' Add Values To List
For Each p As Player In playersList
ListBox1.Items.Add("Name: " + p.Name + " Score: " + p.Score.ToString())
Next
End Sub
'' Get Data From Text File And Create An Anonymous Type
Private Sub LoadPlayerAndScore(path As String)
'' Load data from text file
Dim data = From line In System.IO.File.ReadAllLines(path)
Let val = line.Split(",")
Select New With {Key .Name = val(0), Key .Score = val(1)}
'' Save data to list
For Each pair In data
Dim player As New Player With {
.Name = pair.Name,
.Score = pair.Score
}
playersList.Add(player)
Next
End Sub
End Class
Class Player
Implements IComparable(Of Player)
Public Property Name As String
Public Property Score As Integer
Public Sub Player(ByVal name As String, ByVal score As Integer)
Me.Name = name
Me.Score = score
End Sub
'' Sort Player From The Hightest Score To The Lowest Score
Private Function IComparable_CompareTo(other As Player) As Integer Implements IComparable(Of Player).CompareTo
Return other.Score.CompareTo(Me.Score)
End Function
End Class
Here is the output I gotAnd here is what the text files data looked like.
ANDREW,25
MERVE,12
RUZGAR,50
And for the top ten people, follow the comments above.
How about try this?
Dim sortedArray = _
File _
.ReadAllLines("GameResultsFile") _
.Select(Function (line) line.Split(","c)) _
.Select(Function (parts) New With { .Name = parts(0), .Score = Integer.Parse(parts(1)) }) _
.OrderByDescending(Function (x) x.Score) _
.Select(Function (x) x.Name & " " & x.Score)
.ToArray()
For Each item As String In sortedArray
ListBox1.Items.Add(item)
Next
Hello my code example is :
/*
bdEmpresa (BindingSource)
Contains:
selet idEmpresa,Nombre,Acceso from Empresa
Result
1, Empresa1,true
2, Empresa2,false
3, Empresa2,true
*/
clEmpresas.DataSource = bdEmpresa
clEmpresas.DisplayMember = ? (Nombre)
clEmpresas.ValueMember = ? (Acceso)
This is the code we would use
With clEmpresas.Properties
If .DataSource IsNot Nothing Then .DataSource = Nothing
.DataSource = bdEmpresa
If .DataSource.rows.count = 0 Then Return Nothing 'no data to load
'get the names from the dataset, don't expect them to be specific names
.ValueMember = .DataSource.rows(0).Table.Columns(0).ColumnName
.DisplayMember = .DataSource.rows(0).Table.Columns(1).ColumnName
'Set the selected items, comma separated list of ids
If selectedIds <> "" Then
For i As Integer = 0 To .ItemCount - 1
If Array.IndexOf(selectedIds.Split(","), .GetItemValue(i).ToString) >= 0 Then
.SetItemChecked(i, True)
End If
Next
End If
End With
You can use the CheckMember property to let the control automatically check the selection values from your assigned data source:
e.g.
clEmpresas.DataSource = bdEmpresa
clEmpresas.DisplayMember = "Nombre"
clEmpresas.ValueMember = "idEmpresa"
clEmpresas.CheckMember= "Acceso"
After that you can use the CheckedItems property to get the selected items if user changes selection in the control. see below example:
Private Sub SimpleButton1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SimpleButton1.Click
For Each item As DevExpress.XtraEditors.Controls.CheckedListBoxItem In CheckedListBoxControl1.CheckedItems
MessageBox.Show(item.Value.ToString())
Next
End Sub
Refer these:
get the selected items from a checkedlistbox
How to get checked rows of a data-bound CheckedListBoxControl
Get item index from databound DevExpress CheckedListBoxControl
I have an array of a structure.
It's declared like this
Public SongsList as New List(Of Song)
"Song" it's structure's name.
It has 2 variables : path and name;
I'm wondering how I can sort this array by the name.
Public Structure Song
Public Path as String
Public Name as String
End Structure
I tried this
ListBox1.Items.Clear()
Dim sorted = SongsList.OrderBy(Function(s) s.Name).ToList
Dim i As Integer
For i = 0 To sorted.Count - 1
ListBox1.Items.Add(sorted(i).Name.ToString)
Next
But it throws a NullReferenceException.
This is how I'm adding items to SongsList
Dim open As New OpenFileDialog
open.Title = "Add songs"
open.Filter = "MP3 Files(*.mp3)|*.mp3"
open.Multiselect = True
ListBox1.Items.Clear()
If open.ShowDialog = DialogResult.OK Then
For Each SelectedSong As String In open.FileNames
i += 1
Dim songToAdd As New Song
songToAdd.Path = SelectedSong.ToString
songToAdd.Name = GetSafeFileName(SelectedSong.ToString)
SongsList.Add(songToAdd)
ListBox1.Items.Add(SongsList(i).Path)
Next
End If
You can use a Lambda expression. It uses the field you select in the OrderBy function. Lets Override the ToString method to tell the Listbox what to display, then you can just set the list as the datasource.
The class:
Public Class Song
Public Property Path as String
Public Property Name as String
Public Overrides Function ToString() As String
Return Me.Path
End If
End Class
Usage:
Dim open As New OpenFileDialog
open.Title = "Add songs"
open.Filter = "MP3 Files(*.mp3)|*.mp3"
open.Multiselect = True
If open.ShowDialog = DialogResult.OK Then
For Each SelectedSong As String In open.FileNames
Dim songToAdd As New Song
songToAdd.Path = SelectedSong
songToAdd.Name = GetSafeFileName(SelectedSong.ToString)
SongsList.Add(songToAdd)
Next
End If
Listbox1.DataSource = SongsList.OrderBy(Function(s) s.Name).ToList
*Very similar to OneFineDay's answer...
You don't need a custom class, just use a List(Of FileInfo):
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim open As New OpenFileDialog
open.Title = "Add songs"
open.Filter = "MP3 Files(*.mp3)|*.mp3"
open.Multiselect = True
If open.ShowDialog = DialogResult.OK Then
ListBox1.DataSource = Nothing
Dim songs As New List(Of FileInfo)
For Each SelectedSong As String In open.FileNames
songs.Add(New FileInfo(SelectedSong))
Next
songs = songs.OrderBy(Function(fi) fi.Name).ToList
ListBox1.DataSource = songs
ListBox1.DisplayMember = "Name"
ListBox1.ValueMember = "FullName"
End If
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
If ListBox1.SelectedIndex <> -1 Then
Dim fi As FileInfo = DirectCast(ListBox1.SelectedItem, FileInfo)
Dim name As String = fi.Name
Dim fullPath As String = fi.FullName
Debug.Print("name = " & name)
Debug.Print("fullPath = " & fullPath)
End If
End Sub
I am trying to make a bit of a leap in coding from just using dictionaries (which I only understand in a basic way) to using a Class object to hold data.
I have created a Class purely to hold 4 items of data which need to be held together and then referenced later. I then have code that creates a couple of these Class objects and which populate data into their 4 bits.
Here is my Class Module (called NarrativeGroup) :
Private pNarrative As String
Private pBillCat As String
Private pDateIndex As String
Private pFrequency As Long
''''''''''''''''''''''
' Narrative properties
''''''''''''''''''''''
Public Property Get Narrative() As String
Narrative = pNarrative
End Property
Public Property Let Narrative(Value As String)
pNarrative = Value
End Property
''''''''''''''''''''''
' BillCat properties
''''''''''''''''''''''
Public Property Get BillCat() As String
BillCat = pBillCat
End Property
Public Property Let BillCat(Value As String)
pBillCat = Value
End Property
''''''''''''''''''''''
' DateIndex properties
''''''''''''''''''''''
Public Property Get DateIndex() As String
DateIndex = pDateIndex
End Property
Public Property Let DateIndex(Value As String)
pDateIndex = Value
End Property
''''''''''''''''''''''
' Frequency properties
''''''''''''''''''''''
Public Property Get Frequency() As String
Frequency = pFrequency
End Property
Public Property Let Frequency(Value As String)
pFrequency = Value
End Property
I then have the following code in a normal module. I am trying to load the 4 item types into an array and then to try and test if it is working. My reason for loading it into an array is to then use a sub to output it onto a worksheet. But the code errors! :
Sub setNarrativeGroup() 'to put the dictionary of Narrative object Items into an array
Set dict_Narratives = New Scripting.Dictionary
dict_Narratives.CompareMode = TextCompare 'make text comparisons so they are not case sensitive
Dim NewNarrative As NarrativeGroup
Set NewNarrative = New NarrativeGroup
Dim array_Narratives As Variant
NewNarrative.Narrative = "fee prep"
NewNarrative.BillCat = "Billing"
NewNarrative.DateIndex = "01.2015"
NewNarrative.Frequency = 3
dict_Narratives.Add NewNarrative.Narrative, NewNarrative
NewNarrative.Narrative = "meeting"
NewNarrative.BillCat = "Trustee Meeting"
NewNarrative.DateIndex = "02.2015"
NewNarrative.Frequency = 1
dict_Narratives.Add NewNarrative.Narrative, NewNarrative
array_Narratives = dict_Narratives.Items
MsgBox array_Narratives(1, 1)
Call PrintArray(array_Narratives, "Sheet1", 1, 1)
End Sub
Sub PrintArray(Data, SheetName As String, intStartRow As Integer, intStartCol As Integer)
Dim oWorksheet As Worksheet
Dim rngCopyTo As Range
Set oWorksheet = ActiveWorkbook.Worksheets(SheetName)
' size of array
Dim intEndRow As Integer
Dim intEndCol As Integer
intEndRow = UBound(Data, 1)
intEndCol = UBound(Data, 2)
Set rngCopyTo = oWorksheet.Range(oWorksheet.Cells(intStartRow, intStartCol), oWorksheet.Cells(intEndRow, intEndCol))
rngCopyTo.Value = Data
End Sub
I have tried to search for help on working with dictionaries of class objects and spitting them out into an array, but there doesn't seem to be much out there! Any help much appreciated, and apologies for any big no-no's in my code above! :)