Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: VB.NET
Please keep in mind while reading this, I am using vb.net 4.0 to write a wpf user control. I have an ASCII text file that contains tab delimited customer contact info (herein refered to as DB)...
<vbTab> Customer Name <vbTab> Address 1 <vbTab> Address 2 <vbTab> Phone <vbTab> Fax <vbTab> Cell <vbTab> OtherPhone <vbTab> Contact <vbTab> email
All in all there are 9 fields, some may be blank within the DB.
I need to read each line into an array splitting each line at vbNewLine,
then each line to an array splitting at vbTab.
 
I will be using this array to populate a Combobox with the Customer Name field in the array and 8 other TextBox controls with the corresponding fields.
 
When the ComboBox changes I want the other 8 TextBoxes to update accordingly.
 
Finally, when the ComboBox is manually changed to a value that is not present in the original DB, or if any contact info is changed for a customer, I want to add the new or revised record to the DB. I also want to sort the DB by customer name.
I know this is asking a lot at once, but I had this working in VBA 6.0 and am trying to convert to .Net 4.0
Would it be helpful to post the original VBA code?
Posted 27-Feb-13 5:43am
Edited 27-Feb-13 5:47am
v2
Comments
ThePhantomUpvoter at 27-Feb-13 11:55am
   
I do not know if posting the VBA code would help or not as your question is not clear at all. Read the text out of the file and use the Split method to separate your fields. What is the problem that you are having?
Sean Donnahoe at 27-Feb-13 12:58pm
   
The problem I am having, is wrapping my head around arrays. My original macro code is quite lengthy (I suspect from the lack of array processing options in VBA6).
 
I want to know how to populate the textboxes by calling the index value from the combobox change.
ThePhantomUpvoter at 27-Feb-13 13:14pm
   
textbox.Text = yourArray(index) should do it for you. At least I think that is what you are asking. it would help if you posted the .NET code you have written and described the problem or what it is that is not working.
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 2

Were you using a Structure in VB6? Anyhow .Net is very different. You should read some articles about .Net before you attempt to just port VB6 code directly into .Net.
 
There are many ways to accomplish parsing a delimited file. Below is a simple example of code that will work:
 
Using fs As StreamReader = File.OpenText("C:\File.txt")
   While fs.Peek() <> -1
	Dim line As String = fs.ReadLine()
	Dim fields As String() = line.Split(New String() {"/t"}, StringSplitOptions.None)
	'Do more stuff like add it to a DataTable, array or generic list
   End While
End Using
  Permalink  
v7
Comments
Sean Donnahoe at 27-Feb-13 13:05pm
   
Unfortunately, since I am using .Net 4.0, I can't use StreamReader or any My. functionality. Those are only available in .Net 4.5
ThePhantomUpvoter at 27-Feb-13 13:15pm
   
StreamReader IS available in versions < 4.5. Where did you get that idea?
Sean Donnahoe at 27-Feb-13 14:24pm
   
because it isn't available to me when I try to input the code (see screen shot)...
oatesflag.com/images/temp/vb_error.jpg
ThePhantomUpvoter at 27-Feb-13 14:53pm
   
Are you importing System.IO?
Sean Donnahoe at 27-Feb-13 14:58pm
   
no, my current imports are...
Imports c = Corel.Interop.CorelDRAW
Imports v = Corel.Interop.VGCore
I assume that i should add
Imports sio = System.IO
Sean Donnahoe at 27-Feb-13 15:00pm
   
added "Imports sio = System.IO", but StreamReader is still showing as not declared
Sean Donnahoe at 27-Feb-13 15:11pm
   
dropped the "sio=" portion and it works. Thanks for all the help.
BC @ CV at 27-Feb-13 13:14pm
   
StreamReader has been available since 2.0:
 
#region Assembly mscorlib.dll, v2.0.50727
// c:\WINNT\Microsoft.NET\Framework\v2.0.50727\mscorlib.dll#endregion
using System;using System.Runtime.InteropServices;using System.Text;
namespace System.IO{ // Summary:
// Implements a System.IO.TextReader that reads characters from a byte stream
// in a particular encoding. [Serializable] [ComVisible(true)]
public class StreamReader : TextReader......
Sean Donnahoe at 27-Feb-13 15:05pm
   
Do I need to add a reference in my project? If so, where is the ref for System.IO?
BC @ CV at 27-Feb-13 15:24pm
   
You should already have System.dll referenced you just need to add: Imports System.IO
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

You can use File.ReadAllText() to read teh file and the .Split method will turn the string into an array.
 
Arrays have a sort method.
 

If you can just re-write the file when something is added to the array, I believe the file.writealltext would work for the output.
  Permalink  
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 3

Sean,
 
Relax it is not that hard. They made VB.Net very friendly to VB6 programmers.
 
Some might argue to friendly to the point that it causes confusion, but that discussion will not help you.
 
The reason you are not seeing the StreamReader class is that you have not imported the necessary namespace. VB imports several for you automatically behind the scenes, but the one that you need is System.IO. System.IO is in one of the default assemblies loaded for you, but it is not automatically imported.
 
To see which assemblies and namespaces are loaded for your project, go the Project Menu and select "YourAssemblyName Properties"; if you did not set a name when you created the project, this most likely will be name "WindowsApplication1 Properties". You should now be on the Application tab of the properties page. Select the References tab to see all the assemblies loaded for your project. On the bottom of that tab you will see the default namespaces imported from those assemblies. Anything with a check-mark is automatically available. At this point you could scroll down to System.IO and check that one, or you code go back to your code and add this statement at the top of the code.
 
Imports System.IO
 
Remember that this just provides you a short cut to specifying what class you want to use. You could just as well type this:
 
Dim sr As New System.IO.StreamReader
 
If using the StreamReader is a bit overwhelming for you at this point, VB provides a helper class for reading delimited files called TextFieldParser[^]. In that example, you would need the set the delimiter to VbTab (see a familiar constant) instead of the comma shown.
 
Once you have your arrays read in, you can set the ComboBox's DataSource property equal to the needed array. In this example, I have used a list of string arrays as a central storage device.
 
Public Class Form1
 
    ' combosource could hold your string arrays
    Dim combosource As New List(Of String())
 
    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
 
        ' simulate reading your data
        ' adding string arrays to combosource
        combosource.Add({"1", "2"})
        combosource.Add({"4", "42"})
 
        ' Note the zero based indexing here
        ComboBox1.DataSource = combosource(0)
        ComboBox2.DataSource = combosource(1)
    End Sub
End Class
  Permalink  
Comments
Sean Donnahoe at 27-Feb-13 16:42pm
   
I got the code working thus far (see below), but I'm kinda confused at this point. I could do
Combobox.Items.Add(fields(1))
to populate the combobox, but how do I relate the other changes to the textboexs? I'm getting confused about Multidimensional arrays.
 
Dim path As String = "C:\Users\sean\Dropbox\Visual Studio 2012\Projects\SD_DataBaseTest\SD_DataBaseTest\CustDB.txt"
Dim str As String = "Fields..."
Dim sr As StreamReader = New StreamReader(path)
Do While sr.Peek() >= 0
'MessageBox.Show(sr.ReadLine())
Dim records As String = sr.ReadLine()
MessageBox.Show("Records: " & records)
Dim fields As String() = records.Split(New String() {vbTab}, StringSplitOptions.None)
For i As Integer = 0 To fields.GetUpperBound(0)
str = str & vbLf & i & ": " & fields(i)
Next
MessageBox.Show(str)
str = ""
Loop
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 4

Sean,
 
I just realized that I did not read your original post accurately. This is my understanding at this point.
1. You are reading in multiple records from your text file
2. One of the Fields in the record is "Name".
3. You want to populate a combobox with the name fields.
4. The textboxes should auto update with based on the combobox value.
5. This is a WPF usercontrol.
 
I only put the combobox and 2 textboxes on the UC, but you should get the idea. The code behind the UC will need to be adjusted to match your data. It reads your DB into a DataTable and uses binding to handle the rest.
 
Edit Modified to address comments:
 
Imports System.IO
Imports System.Data
 
Partial Public Class UserControl1
   Private Dt As New System.Data.DataTable
   Private source As New Binding
 
   Private fn As String = "d:\my documents\fields.txt"
 

   Private Sub UserControl1_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles Me.Loaded
      Dim r As System.Data.DataRow
      With Dt
         .Columns.Add("FX", GetType(String)) 'added this for you preceeding tab
         .Columns.Add("Name", GetType(String))
         .Columns.Add("F1", GetType(String)) ' replace F# with something more meaningful
         .Columns.Add("F2", GetType(String))
         .Columns.Add("F3", GetType(String))
         .Columns.Add("F4", GetType(String))
         .Columns.Add("F5", GetType(String))
         .Columns.Add("F6", GetType(String))
         .Columns.Add("F7", GetType(String))
         .Columns.Add("F8", GetType(String))
         .DefaultView.Sort = "[Name] ASC"
 
         Dim sr As New IO.StreamReader(fn)
 
         Do While sr.Peek() <> -1
            r = .NewRow
            r.ItemArray = sr.ReadLine().Split(New Char() {vbTab(0)}, 9, System.StringSplitOptions.None)
            .Rows.Add(r)
         Loop
         sr.Close()
      End With
 
      ComboBox1.DataContext = Dt
      TextBox1.DataContext = Dt
      TextBox2.DataContext = Dt
   End Sub
 

   ' this is the method to write out the datatable
   Public Sub WriteDB()
      Dim sw As IO.StreamWriter = My.Computer.FileSystem.OpenTextFileWriter(fn, False)
      Dim line As New System.Text.StringBuilder(1000)
      For Each r As DataRow In Dt.Rows
         line.Length = 0
         For Each obj As Object In r.ItemArray
 
            If obj IsNot DBNull.Value AndAlso Not String.IsNullOrEmpty(obj.ToString) Then
 
               line.Append(obj.ToString)
 
            End If
            line.Append(vbTab)
         Next
         sw.WriteLine(line.ToString)
      Next
      sw.Close()
   End Sub
 
   Private Sub ComboBox1_GotFocus(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles ComboBox1.GotFocus
      Dt.DefaultView.RowFilter = Filter()
      ComboBox1.EditableTextBox.CaretIndex = ComboBox1.Text.Length
      ComboBox1.EditableTextBox.SelectionLength = 0
      ComboBox1.IsDropDownOpen = True
      ComboBox1.StaysOpenOnEdit = True
   End Sub
 
   Private Function Filter() As String
      Return "[Name] Like '" & ComboBox1.Text & "*'"
   End Function
 
   Private Sub ComboBox1_KeyUp(ByVal sender As Object, ByVal e As System.Windows.Input.KeyEventArgs) Handles ComboBox1.KeyUp
      Dim tmp As String = ComboBox1.Text
      Dt.DefaultView.RowFilter = Filter() ' "[Name] Like '" & ComboBox1.Text & "*'"

      ComboBox1.SelectedIndex = -1
      ComboBox1.Text = tmp
      ComboBox1.EditableTextBox.CaretIndex = ComboBox1.Text.Length
 
   End Sub
 
   Private Sub ComboBox1_LostFocus(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles ComboBox1.LostFocus
      ComboBox1.IsDropDownOpen = False
      ' ****** Hack.  
      ' There must be a better way to force this update, if Name is not in the data
      Dim tmp As String = ComboBox1.Text
      ComboBox1.Text = ""
      ComboBox1.Text = tmp
      ' ***** End Hack
   End Sub
 
End Class
 
' created a custom combobox so that I could access the internal textbox
Public Class myCombo
   Inherits System.Windows.Controls.ComboBox
 
   Friend ReadOnly Property EditableTextBox() As TextBox
      Get
         Return (TryCast(MyBase.GetTemplateChild("PART_EditableTextBox"), TextBox))
      End Get
   End Property
End Class
 

<UserControl x:Class="UserControl1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="269" Height="263"
    xmlns:MyNamespace="clr-namespace:WpfApplication1"    
>
    
    <Grid Height="122" Width="200">
        
        <MyNamespace:myCombo 
                  Height="23" HorizontalAlignment="Left" Margin="5,0,0,0" x:Name="ComboBox1" 
                  VerticalAlignment="Top" Width="150" IsSynchronizedWithCurrentItem="True"
                  IsEditable="True" 
 
                  IsTextSearchEnabled="False"
                  
                  ItemsSource="{Binding}"
                  DisplayMemberPath="Name"            
        />
        
 
        <TextBox Margin="5,51,45,48" Name="TextBox1" Text="{Binding Path=F1}"/>
        
        <TextBox Margin="5,0,0,13.5"  Height="20" Name="TextBox2" Text="{Binding Path=F2}" 
                 VerticalAlignment="Bottom" HorizontalAlignment="Left" Width="150" />
    </Grid>
</UserControl>
  Permalink  
v2
Comments
Sean Donnahoe at 28-Feb-13 9:35am
   
Thanks TnTinMn your code works great [with a few typo tweaks :)]. However, there is a small catch, my DB file has a leading VBTab on each row, which puts all the data off by one position. I added a new column at the top of the Dt structure, which seems to have fixed this, but now ComboBox1 only shows "System.Data.DataRowView" as it's contents. The drop down area shows all the names and the rest of the text boxes update as expected, but the upper contents of ComboBox1 never visually change.
I have 2 scenarios at this point.
After I change ComboBox1 to IsEditable...
1. When I change the contents of ComboBox1 manually I want to test the data table to see if there is an entry that matches and update the text boxes accordingly.
2. If I manually change the contents of one of the text boxes, I want the new data updated in the table and written back to the CustDB.txt file. I have a button on my form that is intended to write data to the ASCII text file, but I haven't coded it yet.
TnTinMn at 28-Feb-13 21:29pm
   
I was bored so I thought I would give it a try. I'm still new to WPF.
Besides, I found many comments that doing a filtered ComboBox was pain and I like a challenge. :)
 
I replaced the code in my previous post to give what I think you are looking for. I now agree with a comment that I found that WPF can hurt your brain, :)) WinForms is so much easier to to achieve this with. At least I didn't give you a WinForm control and tell you to host it in WPF.
Sean Donnahoe at 1-Mar-13 13:30pm
   
TnTinMn, I have been putting your code into my project and I ran across a problem.
Dim sw As IO.StreamWriter = My....
doesn't have .Computer. I only get options for ".MySettings" ".Resources" & ".Settings"
Any ideas what to do?
Sean Donnahoe at 1-Mar-13 14:14pm
   
Also, the line xmlns:MyNamespace="clr-namespace:WpfApplication1" in the top of the XAML is throwing an error.
Error 4 Undefined CLR namespace. The 'clr-namespace' URI refers to a namespace 'WpfApplication1' that could not be found. C:\Users\sean\Dropbox\Visual Studio 2012\Projects\OrderForms_4.5\OrderForms_4.5\Docker.xaml 7 32 OrderForms_4.5
 
Even after I changes "WpfApplication1" to "Docker"
TnTinMn at 1-Mar-13 15:29pm
   
Go to the Project Properties page. On the Application Tab Copy the RootNamespace field and substitute that for WpfApplication1. You may have to issue a rebuild to get it to take. I had a few isssues also when I typed it in as well. Since it looks like you are using VS2012, it looks like they still have not made it any friendlier to use than it is in VS2008.
TnTinMn at 1-Mar-13 15:22pm
   
Go to the Project properties page (double-click on "My Project" in the solution explorer) and the to the "My Extensions" tab. Click on the "Add Extension" button and then select "WPF My extension". That should clear up the problem.
Sean Donnahoe at 1-Mar-13 15:26pm
   
Was I correct in renaming WpfApplication1 to Docker since my userControl header looks likes this...
<pre lang="xml">usercontrol x:class="Docker"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"</pre>
Sean Donnahoe at 1-Mar-13 15:33pm
   
There are no errors in hte Class myCombo, but the XAML still throws 2 errors.
1. The type 'MyNamespace:myCombo' was not found. Verify that you are not missing an assembly reference and that all referenced assemblies have been built.
2. The name "myCombo" does not exist in the namespace "clr-namespace:Docker".

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
0 OriginalGriff 404
1 Nirav Prabtani 268
2 _Amy 230
3 CHill60 170
4 Sergey Alexandrovich Kryukov 166
0 OriginalGriff 8,004
1 Sergey Alexandrovich Kryukov 7,017
2 Maciej Los 4,039
3 Peter Leow 3,738
4 CHill60 2,912


Advertise | Privacy | Mobile
Web04 | 2.8.140721.1 | Last Updated 28 Feb 2013
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100