String with apostrophe doubles when bound to property - wpf

I have a radgridview with a cell whose data may contain an apostrophe. When the row is selected, the row context is cast to a collection of public properties. This works well except for the cell with an apostrophe.
Private Sub dgSelectOrder_MouseLeftButtonDown(sender As Object, e As MouseButtonEventArgs)
Dim row = TryCast(sender, GridViewRow)
Dim selectedOrder = TryCast(row.DataContext, myProperties)
If the cell data has an apostrophe, for example LET'S GO, the property returns the value LET''S GO. The apostrophe is doubled. If that data gets saved back to the database, then retrieved again, the property returns LET''''S GO.
How do I cast the row data correctly?
Public Class myProperties
Public Property pProjectNbr As String = String.Empty
Thanks.

I shouldn't have to do this but it's the only way it would work. I have similar code to cast the row.datacontext elsewhere. And that code runs as expected with the apostrophe.
Private Sub dgArchivedOrders_MouseLeftButtonDown(sender As Object, e As MouseButtonEventArgs)
Dim row = TryCast(sender, GridViewRow)
Dim selectedOrder = TryCast(row.DataContext, myProperties)
If selectedOrder.pProjectNbr.Contains("''") Then
Dim convertThis As String = selectedOrder.pProjectNbr
selectedOrder.pProjectNbr = convertThis.Replace("''", "'")
End If

Related

Auto fill Combo Boxs with data from SQL server database VB.Net

l have a data source that contains two columns
block_name total_lands
A-0 5
A-1 15
A-2 18
A-3 18
And I have two combo boxes one for the block name and the other for the no of lands
the first one is loaded with the block names
Private Sub LoadItems()
SQL.ExecQuery("SELECT block_name FROM blocks;")
For Each i As DataRow In SQL.DBDTable.Rows
ComboBox1.Items.Add(i("block_name"))
Next
End Sub
I want the second one to be loaded with numbers from 1 to whatever is in the data source row total_lands
For example if the user chose the block name as A-1 I want the second combo box to have the items from 1 to 15 add in it
My code trying to do so
Private Sub LoadNoOfLands()
SQL.AddParam("#blockname", ComboBox1.Text)
SQL.ExecQuery("SELECT totla_lands FROM blocks WHERE total_lands LIKE #blockname;")
For Each no As DataRow In SQL.DBDTable.Rows
Dim lands As Integer = no("block_lands")
'For Each i As Integer In lands
'
'
'Next
Next
End Sub
Load required data at once and use Enumerator.Range to generate collection of numbers for second combobox
Public Class Block
Public ReadOnly Property Name As String
Public ReadOnly Property TotalLands As Integer
Public ReadOnly Property Lands As Integer()
Public Sub New(name As String, totalLands As Intger)
Name = name
TotalLands = totalLands
Lands = Enumerable.Range(1, totalLands).ToArray()
End Sub
End Class
Private Function LoadBlocks() As Block()
Dim query = "SELECT block_name, total_lands FROM table"
Dim rows = SQL.ExecuteQuery(query)
Return rows.AsEnumerable().
Select(Function(row) New Block(row.Field(Of String)("block_name"), row.Field(Of Integer)("total_lands"))).
ToArray()
End Function
Private Sub SetupComboBox()
cmbBlocks.DisplayMemeber = "Name"
cmbBlocks.DataSource = LoadBlocks()
End Sub
Private Sub cmbBlocks_SelectionChangeCommitted(sender As Object, e As EventArgs) Handles cmbBlocks.SelectionChangeCommitted
Dim combobox As ComboBox = DirectCast(sender, ComboBox)
Dim block As Block = DirectCast(combobox.SelectedValue, Block)
cmbLands.DataSource = block.Lands
End
I have come up with a simple answer
Private Sub LoadNoOfLands()
cmbLands.Items.Clear()
SQL.AddParam("#blockname", cmbBlocks.Text)
SQL.ExecQuery("SELECT total_lands FROM blocks WHERE block_name LIKE #blockname;")
If SQL.HasException(True) Then Exit Sub
For Each i As DataRow In SQL.DBDTable.Rows
Dim lands = i("total_lands")
Dim r = 1
For r = 1 To lands
cmbLands.Items.Add(r).ToString()
Next
Next
End Sub
This function just adds number to combobox form 1 to the total_lands value
I created a class for the data.
Public Class Block
Public Property Name As String
Public Property TotalLands As Integer
Public Sub New(BlockName As String, Lands As Integer)
Name = BlockName
TotalLands = Lands
End Sub
Public Overrides Function ToString() As String
Return Name
End Function
End Class
The combo box will call .ToString on the items to determine what to display.
We get the data from the database and add it to the List(Of Block)
Public Function FillBlocksList() As List(Of Block)
Dim lst As New List(Of Block)
Using cn As New SqlConnection("Your connection string"),
cmd As New SqlCommand("Select block_name, total_lands From BlockTable;", cn)
cn.Open()
Using reader = cmd.ExecuteReader
Do While reader.Read
Dim b As New Block(reader.GetString(0), reader.GetInt32(1))
lst.Add(b)
Loop
End Using
End Using
Return lst
End Function
To fill the first combo we get the list then loop through it adding the Block objects to the combo. You would probably call this from Form.Load.
Public Sub FillBlocksCombo()
Dim lst = FillBlocksList()
For Each item In lst
ComboBox1.Items.Add(item)
Next
End Sub
To fill the second combo cast the select item back its underlying type, Block and use the TotalLands property to add the numbers.
Private Sub ComboBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox1.SelectedIndexChanged
Dim NumberOfLands = DirectCast(ComboBox1.SelectedItem, Block).TotalLands
For i = 1 To NumberOfLands
ComboBox2.Items.Add(i.ToString)
Next
End Sub

(VB.NET) display the lower half of a textfile to a listbox

I have to make a application that organizes a list of runners and their teams. In the following text file, I have to remove the top half of the text file (the top half being the listed teams) and display only the bottom half (the runners)in a listbox item.
The Text file:
# School [School Code|School Name|Coach F-Name|Coach L-Name|AD F-Name|AD L Name]
WSHS|Worcester South High School|Glenn|Clauss|Bret|Zane
WDHS|Worcester Dorehty High School|Ellsworth|Quackenbush|Bert|Coco
WBCHS|Worcester Burncoat High School|Gail|Cain|Kevin|Kane
QRHS|Quabbin Regional High School|Bob|Desilets|Seth|Desilets
GHS|Gardner High School|Jack|Smith|George|Fanning
NBHS|North Brookfield High School|Hughe|Fitch|Richard|Carey
WHS|Winchendon High School|Bill|Nice|Sam|Adams
AUBHS|Auburn High School|Katie|Right|Alice|Wonderland
OXHS|Oxford High School|Mary|Cousin|Frank|Daughter
# Roster [Bib #|School Code|Runner's F-Name|Runner's L-Name]
101|WSHS|Sanora|Hibshman
102|WSHS|Bridgette|Moffitt
103|WSHS|Karine|Chunn
104|WSHS|Shanita|Wind
105|WSHS|Fernanda|Parsell
106|WSHS|Albertha|Baringer
107|WSHS|Carlee|Sowards
108|WDHS|Maisha|Kleis
109|WDHS|Lezlie|Berson
110|WDHS|Deane|Rocheleau
111|WDHS|Hang|Hodapp
112|WDHS|Zola|Dorrough
113|WDHS|Shalon|Mcmonigle
I have some code that reads each row from the text file as an array and uses boolean variables to determine where to end the text file. This worked with displaying only the teams, which I've managed to do. But I now need to do the opposite and display only the players, and I'm a bit stumped.
My Code:
Private Sub btnLoadTeams_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnLoadTeam.Click
' This routine loads the lstTeam box from an ASCII .txt file
' # School [School Code | Name | Coach F-Name| Coach L-Name | AD F-Name | AD L-Name]
Dim strRow As String
Dim bolFoundCode As Boolean = False
Dim bolEndCode As Boolean = False
Dim bolFoundDup As Boolean = False
Dim intPosition As Integer
Dim intPosition2 As Integer
Dim strTeamCodeIn As String
Dim textIn As New StreamReader( _
New FileStream(txtFilePath.Text, FileMode.OpenOrCreate, FileAccess.Read))
' Clear Team listbox
lstTeam.Items.Clear()
btnDeleteRunner.Enabled = True
Do While textIn.Peek <> -1 And Not bolEndCode
Me.Refresh()
strRow = textIn.ReadLine.Trim
If Not bolFoundCode Then
If "# SCHOOL " = UCase(Mid(strRow, 1, 9)) Then
bolFoundCode = True
End If
Else
If Mid(strRow, 1, 2) <> "# " Then
For Each item As String In lstTeam.Items
intPosition = InStr(1, strRow, "|")
strTeamCodeIn = Mid(strRow, 1, intPosition - 1)
intPosition2 = InStr(1, item, strTeamCodeIn)
If intPosition2 > 0 Then
bolFoundDup = True
MsgBox("Found Duplicate School Code: " & strTeamCodeIn)
End If
Else
bolEndCode = True
Next
If Not bolFoundDup Then
lstTeam.Items.Add(strRow)
Else
lstTeam.Items.Add("DUPLICATE School Code: " & strRow)
lstTeam.Items.Add("Please correct input file and reload teams")
bolEndCode = True
End If
End If
End If
Loop
End Sub
Ive put bolEndCode = True in between the part that reads the mid section of the text file, but all Ive managed to display is the following in the listbox:
# Roster [Bib #|School Code|Runner's F-Name|Runner's L-Name]
Any help or hints on how I would display just the runners to my "lstPlayers" listbox would be greatly appreciated. I'm a beginner programmer and We've only just started learning about reading and writing arrays in my .NET class.
First I made 2 classes, one Runner and one School. These have the properties available in the text file. As part of the class I added a function that overrides .ToString. This is for he list boxes that call .ToString for display.
Next I made a function that reads all the data in the file. This is very simple with the File.ReadLines method.
Then I created 2 variables List(Of T) T stands for Type. Ours Types are Runner and School. I used List(Of T) instead of arrays because I don't have to worry about what the size of the list is. No ReDim Preserve, just keep adding items. The FillList method adds the data to the lists. First I had to find where the schools ended and the runners started. I used the Array.FindIndex method which is a bit different because the second parameter is a predicate. Check it out a bit. Now we know the indexes of the lines we want to use for each list and use a For...Next loop. In each loop an instance of the class is created and the properties set. Finally the new object is added to the the list.
Finally we fill the list boxes with a simple .AddRange and the lists.ToArray. Note that we are adding the entire object, properties and all. The neat thing is we can access the properties from the listbox items. Check out the SelectedIndexChanged event. You can do the same thing with the Runner list box.
Sorry, I couldn't just work with your code. I have all but forgotten the old vb6 methods. InStr, Mid etc. It is better when you can to use .net methods. It makes your code more portable when the boss says "Rewrite the whole application in C#"
Public Class Runner
Public Property BibNum As Integer
Public Property SchoolCode As String
Public Property FirstName As String
Public Property LastName As String
Public Overrides Function ToString() As String
'The listbox will call .ToString when we add a Runner object to determin what to display
Return $"{FirstName} {LastName}" 'or $"{LastName}, {FirstName}"
End Function
End Class
Public Class School
Public Property Code As String
Public Property Name As String
Public Property CoachFName As String
Public Property CoachLName As String
Public Property ADFName As String
Public Property ADLName As String
'The listbox will call .ToString when we add a School object to determin what to display
Public Overrides Function ToString() As String
Return Name
End Function
End Class
Private Runners As New List(Of Runner)
Private Schools As New List(Of School)
Private Function ReadData(path As String) As String()
Dim lines = File.ReadLines(path).ToArray
Return lines
End Function
Private Sub FillLists(data As String())
Dim location = Array.FindIndex(data, AddressOf FindRosterLine)
'The first line is the title so we don't start at zero
For index = 1 To location - 1
Dim SplitData = data(index).Split("|"c)
Dim Schl As New School
Schl.Code = SplitData(0)
Schl.Name = SplitData(1)
Schl.CoachFName = SplitData(2)
Schl.CoachLName = SplitData(3)
Schl.ADFName = SplitData(4)
Schl.ADLName = SplitData(5)
Schools.Add(Schl)
Next
For index = location + 1 To data.GetUpperBound(0)
Dim SplitData = data(index).Split("|"c)
Dim Run As New Runner
Run.BibNum = CInt(SplitData(0))
Run.SchoolCode = SplitData(1)
Run.FirstName = SplitData(2)
Run.LastName = SplitData(3)
Runners.Add(Run)
Next
End Sub
Private Function FindRosterLine(s As String) As Boolean
If s.Trim.StartsWith("# Roster") Then
Return True
Else
Return False
End If
End Function
Private Sub FillListBoxes()
Dim arrRunners As Runner() = Runners.ToArray
Dim arrSchools As School() = Schools.ToArray
ListBox1.Items.AddRange(arrSchools)
ListBox2.Items.AddRange(arrRunners)
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim arrRunner = ReadData("Runners.txt")
FillLists(arrRunner)
FillListBoxes()
End Sub
Private Sub ListBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ListBox1.SelectedIndexChanged
Dim Schl = DirectCast(ListBox1.SelectedItem, School)
TextBox1.Text = Schl.CoachLName
TextBox2.Text = Schl.Code
End Sub

How to remove a record from a Listbox control in my WPF application with VB.Net code behind

I know similar questions to mine have been posted before, but I have tried various suggestions and nothing seem to work.
Here is my issue: I get the following error when trying to remove an item\from my listbox control:
Additional information: Operation is not valid while ItemsSource is in use. Access and modify elements with ItemsControl.ItemsSource instead.
I need help removing an item from a listbox in WPF with VB.Net code-behind.
When I click a row in the listbox, I want to remove that item from the listbox.
I create alist of object 'ToLoadImages' to load into my listbox.
How would I remove the selected item from the list box and from my list ob object 'ToLoadImages'?
See my code below:
'CODE TO LOAD Listbox
Private Sub GetListToLoad(ClaimNo As String)
Dim ta As New ImagesDataSetTableAdapters.usp_SELECT_ImageTableAdapter
Dim dt As ImagesDataSet.usp_SELECT_ImageDataTable = ta.GetData(1, _ClaimNo, True)
Dim dr As DataRow
ListToLoad = New List(Of ToLoadImages)
Dim i As Integer = 0
For Each dr In dt
Dim ImgSource2() As Byte = DirectCast(dr(7), Byte())
Dim stream2 As MemoryStream = New MemoryStream
stream2.Write(ImgSource2, 0, ImgSource2.Length - 1)
stream2.Seek(0, SeekOrigin.Begin)
bitMap2 = New BitmapImage
bitMap2.BeginInit()
bitMap2.StreamSource = stream2
bitMap2.EndInit()
ListToLoad.Add(New ToLoadImages(dr(0), bitMap2))
Next
ImageListBox.ItemsSource = ListToLoad
End Sub
'Code to retrieve selected item from the listbox
'Here is where I want to add the code that will remove the selected item from my listbox and from the List of 'ToLoadImages'.
Private Sub ImageListBox_SelectionChanged(sender As Object, e As SelectionChangedEventArgs) Handles ImageListBox.SelectionChanged
Try
Dim itemsToLoad As ToLoadImages
itemsToLoad = ImageListBox.SelectedItem
Dim imageID as String = itemsToLoad.ImgID.ToString
Catch ex As Exception
MsgBox("Error encountered.")
End Try
End Sub
Class ToLoadImages
Public Class ToLoadImages
Private m_imgID As Integer
Private m_imageX As BitmapImage
Public Sub New(imgID As Integer, imagex As BitmapImage)
Me.m_imgID = imgID
Me.m_imageX = imagex
End Sub
Public Property ImgID() As Integer
Get
Return m_imgID
End Get
Set(ByVal value As Integer)
m_imgID = value
End Set
End Property
Public Property ImageX() As BitmapImage
Get
Return m_imageX
End Get
Set(ByVal value As BitmapImage)
m_imageX = value
End Set
End Property
End Class
Use ObservableCollection instead of List.
ObservableCollection
updates the changes automatically

VB.NET: DYNAMICALLY ADD ARRAY TO COMBOBOX

Does anyone know how to dynamically add an array to a bunch of comboboxes in VB.net? I could really use the help (I've been struggling with this all day). When I try to do it my way I get an error on form load.
My code:
Private Sub Form1_Load(ByVal sender as Object, ByVal e as EventArgs) Handles Me.Load
Dim MyArray() as String = {"a","b","c"}
For each ctl as ComboBox in Me.Controls
if ctl.tag = "yadda" then ctl.Items.AddRange(MyArray)
Next
End Sub
Error: "Unable to cast object of type '...Button' to type '...Combobox'."
I've tried so many variations to this code but I just can't get it to work. I will eventually have nearly a hundred similarly constructed comboboxes in my application, and I'd like to be able to programmatically initialize their items. Could someone please help?
Thanks,
Elias
This is the way to do it :
Public Class Form1
Function getControl(ByVal controlName As String) As Control
Dim numCtrls = Me.Controls.Count()
For I As Integer = 0 To numCtrls - 1
If Me.Controls.Item(I).Name = controlName Then
If TypeOf Me.Controls.Item(I) Is ComboBox Then
Return CType(Me.Controls(controlName), ComboBox)
End If
End If
Next
End Function
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim myArray As Array = {"a", "b", "c"}
Dim myComboBox As ComboBox
For Each ctl As Control In Me.Controls
If TypeOf ctl Is ComboBox Then
If ctl.Tag = "yadda" Then
myComboBox = getControl(ctl.Name)
myComboBox.Items.AddRange(myArray)
End If
End If
Next
End Sub
End Class
You loop through all controls (buttons, combo, etc ...) then you check if it is the type you want (ComboBox) and do whatever you need.
Good luck !

VB.NET using LINQ to transpose an ObservableCollection

I have a custom item class (basically two string values with associated properties), as below:
Public Class itmDataDetails
Private _strDataName As String
Private _strDataValue As String
Public Property strDataName() As String
Get
Return _strDataName
End Get
Set(ByVal value As String)
_strDataName = value
End Set
End Property
Public Property strDataValue() As String
Get
Return _strDataValue
End Get
Set(ByVal value As String)
_strDataValue = value
End Set
End Property
Public Sub New(Optional ByVal strDataNameIn As String = "", Optional ByVal strDataValueIn As String = "")
strDataName = strDataNameIn
strDataValue = strDataValueIn
End Sub
and an ObservableCollection wrapper class around this. I'd like to transpose this ObservableCollection (that is, make the data names into the columns and their associated values into the rows) for display in a WPF ListView.
Here's what I have so far:
Private Sub Transpose()
Dim colGroupedValues = From x In MyBase.Items Group x By Key = x.strDataName Into Group Select strName = Key, colValues = Group
MyBase.Clear()
For Each x In colGroupedValues
MyBase.Add(x)
Next
End Sub
Naturally, this doesn't work as x cannot be added to the ObservableCollection(Of itmDataDetails). Any suggestions on how to accomplish this? I don't know LINQ that well, so I wouldn't be surprised to discover I'm doing it wrong.
Thanks in advance, everyone.
So I think I was asking the wrong question here. What I really wanted was to have each column in a GridView be set to the DataName part of itmDataDetails and its corresponding records be set to the DataValue.
To do this, I followed the helpful guide at: http://weblogs.asp.net/psheriff/archive/2010/03/08/using-a-wpf-listview-as-a-datagrid.aspx
So the whole thing is replaced by:
Private Sub FillDataList()
Dim strConnectionString As String = "INSERT CONNECTION INFO HERE"
Dim strCommandString As String = "INSERT QUERY HERE"
Dim objCommand As New OleDb.OleDbCommand(strCommandString)
Dim objConnection As New OleDb.OleDbConnection(strConnectionString)
Dim objAdapter As New OleDb.OleDbDataAdapter
Dim ds As New DataSet
objConnection.Open()
objAdapter.SelectCommand = objCommand
objCommand.Connection = objConnection
objAdapter.Fill(ds)
lsvData.View = BuildDataView(ds)
lsvData.DataContext = ds.Tables(0)
lsvData.SetBinding(ListView.ItemsSourceProperty, New Binding)
objConnection.Close()
End Sub
Public Function BuildDataView(ByVal ds As DataSet) As GridView
Dim gv As New GridView
For Each item As DataColumn In ds.Tables(0).Columns
Dim gvc As New GridViewColumn
gvc.DisplayMemberBinding = New Binding(item.ColumnName)
gvc.Header = item.ColumnName
gvc.Width = [Double].NaN
gv.Columns.Add(gvc)
Next
Return gv
End Function
This gives me what I wanted. Sorry for the misunderstanding, if there was any. I'll still accept an answer that does this task better than my solution (to be charitable, etc.)
I also suspect that the database engine doesn't matter here, so you could probably do something similar for Oracle databases, etc.

Resources