WP7 - Updating a listbox - vb.net

I've finally got around to starting windows phone dev. I'm not very good at it yet, but anyway, I hope you guys understand what I want to do here.
From what I've learnt from other programmers, an ObservableCollection can be updated in live time whilst it is databound to an object, such as a listbox. All changes to the ObservableCollection will cause the UI of the object it's databound to update it's items.
So what I'm trying to do, is download a file from my server, parse it with json, then update the ObservableCollection with the new data. However, the webclient doesn't seem to be downloading the new data until the app is re opened!
Here's a gif showing how the app works at the moment:
And here's my code (cut down a bit):
Dim aList As New ObservableCollection(Of classes.consoles)
Private Sub PhoneApplicationPage_Loaded(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded
checkforconsoles()
End Sub
Public Sub checkforconsoles()
Dim wc As New WebClient()
AddHandler wc.DownloadStringCompleted, AddressOf downloaded
wc.DownloadStringAsync(New Uri("http://localhost/api/?function=GetConsolesForUser&userid=" & id))
End Sub
Private Sub downloaded(sender As Object, e As DownloadStringCompletedEventArgs)
aList.Clear()
'MessageBox.Show(e.Result)
Dim o As JObject = JObject.Parse(e.Result)
Dim jarray As JArray = DirectCast(o("results"), JArray)
Try
Dim i As Integer = jarray.Count()
For i = 0 To jarray.Count() - 1 Step 1
Dim id As String = jarray(i)("id").ToString
Dim name As String = jarray(i)("name").ToString
Dim image As String = jarray(i)("image").ToString
MessageBox.Show(name)
Dim c As classes.consoles = New classes.consoles()
c.categoryimage = New Uri(image)
c.categoryname = name
c.categoryid = id
aList.Add(c)
Next
listBoxview.ItemsSource = aList
StackPanel1.Visibility = Windows.Visibility.Collapsed
StackPanel2.Visibility = Windows.Visibility.Visible
Catch ex As Exception
StackPanel2.Visibility = Windows.Visibility.Collapsed
StackPanel1.Visibility = Windows.Visibility.Visible
End Try
End Sub
Private Sub ApplicationBarIconButton_Click_1(sender As System.Object, e As System.EventArgs)
checkforconsoles()
End Sub
Does anybody have any clue what's wrong? :(
Thanks in advance.

It's a cachine issue with the WebClient. You can append a random query string to ensure that the URL is always unique so that the WebClient doesn't cache the results. One way to do this is to add a random GUID value since it's very unlikely to generate two of the same GUIDs in a short time frame.
wc.DownloadStringAsync(New Uri("http://localhost/api/?function=GetConsolesForUser&
userid=" & id & "&random=" + Guid.NewGuid().ToString()))

Related

VB.NET DataSet table data empty

I'm trying to use the dataset for a report, but the data is gone when I try to use it. Here is my code for the most part:
Variables:
Dim ResultsDataView As DataView
Dim ResultsDataSet As New DataSet
Dim ResultsTable As New DataTable
Dim SQLQuery As String
Search:
This is where a datagrid is populated in the main view. The data shows up perfectly.
Private Sub Search(Optional ByVal Bind As Boolean = True, Optional ByVal SearchType As String = "", Optional ByVal SearchButton As String = "")
Dim SQLQuery As String
Dim ResultsDataSet
Dim LabelText As String
Dim MultiBudgetCenter As Integer = 0
SQLQuery = "A long and detailed SQL query that grabs N rows with 7 columns"
ResultsDataSet = RunQuery(SQLQuery)
ResultsTable = ResultsDataSet.Tables(0)
For Each row As DataRow In ResultsTable.Rows
For Each item In row.ItemArray
sb.Append(item.ToString + ","c)
Response.Write(item.ToString + "\n")
Response.Write(vbNewLine)
Next
sb.Append(vbCr & vbLf)
Next
'Response.End()
If Bind Then
BindData(ResultsDataSet)
End If
End Sub
Binding Data:
I think this is a cause in the issue.
Private Sub BindData(ByVal InputDataSet As DataSet)
ResultsDataView = InputDataSet.Tables("Results").DefaultView
ResultsDataView.Sort = ViewState("SortExpression").ToString()
ResultsGridView.DataSource = ResultsDataView
ResultsGridView.DataBind()
End Sub
Reporting action:
This is where I am trying to use the table data. But it is showing as nothing.
Protected Sub ReportButton_Click(sender As Object, e As EventArgs) Handles ReportButton.Click
For Each row As DataRow In ResultsTable.Rows
For Each item In row.ItemArray
Response.Write(item.ToString)
Next
Next
End Sub
The reason I'm trying to loop through this data is to both display the data in a gridview on the main view as well as export the data to CSV. If there is a different way to export a SQL query to CSV, I'm open to any suggestions.
There has to be something I can do to get the data from the SQL query to persist through the ReportButton_Click method. I've tried copying the datatable, I've tried global variables, I've tried different methods of looping through the dataset. What am I missing?!
Thank you all in advance.
EDIT
Here is the Page_Load:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Page.IsPostBack Then
'set focus to postback control
Dim x As String = GetPostBackControlName(Page)
If Len(x) > 0 Then
x = x.Replace("$", "_")
SetFocus(x)
End If
End If
If Not IsPostBack Then
ResultsGridView.AllowPaging = False
'Enable Gridview sorting
ResultsGridView.AllowSorting = True
'Initialize the sorting expression
ViewState("SortExpression") = "ID DESC"
'Populate the Gridview
Search()
End If
End Sub
In your search function add this line after the ResultsTable setting
ResultsTable = ResultsDataSet.Tables(0)
Session("LastSearch") = ResultsTable
Then in your report click event handler recover your data from the Session variable
Protected Sub ReportButton_Click(sender As Object, e As EventArgs) Handles ReportButton.Click
ResultsTable = DirectCast(Session("LastSearch"), DataTable)
For Each row As DataRow In ResultsTable.Rows
For Each item In row.ItemArray
Response.Write(item.ToString)
Next
Next
End Sub
You need to read about ASP.NET Life Cycle and understand that every time ASP.NET calls your methods it creates a new instance of your Page class. Of course this means that global page variables in ASP.NET are not very useful.
Also consider to read about that Session object and not misuse it.
What is the difference between SessionState and ViewState?

Form Loads slowly in vb.net

I am currently working in ERP project on vb.net. I want to load product data in a textbox on form load. I am using autocomplete method but having a data of around 26000 the form loads slowly for 4 mins. Is there any way to avoid this or is there any way to call this function in background when the application starts?
This is my autocomplete textbox code. It works fine but it hangs alot as of the data is so large.
Private Sub pn()
Try
con = Class1.dbconn
Dim dt As New DataTable
Dim ds As New DataSet
ds.Tables.Add(dt)
Dim da As New SqlDataAdapter("select [Part Name] from
Part_Master_Download$", con)
da.Fill(dt)
Dim r As DataRow
TextBox9.AutoCompleteCustomSource.Clear()
For Each r In dt.Rows
TextBox9.AutoCompleteCustomSource.Add(r.Item(0).ToString)
Next
con.Close()
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
the properties of the textbox should be set to true for autocompletetextbox
Don't populate the AutoCompleteCustomSource in a loop. Populate an array first and then load the list in one go with a single call to AddRange:
Dim items = dt.Rows.Cast(Of DataRow)().
Select(Function(row) CStr(row(0)).
ToArray()
TextBox9.AutoCompleteCustomSource.AddRange(items)
You should find that that speeds things up considerably. If there's still a problem with performance, we can look a bit further.
EDIT: To prove my point, I just tested the following code:
Public Class Form1
Private timer As Stopwatch
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
timer = Stopwatch.StartNew()
Dim rng As New Random
Dim a = Convert.ToInt32("a"c)
Dim z = Convert.ToInt32("z"c)
Dim items = Enumerable.Range(1, 26000).Select(Function(n) Convert.ToChar(rng.Next(a, z + 1)).ToString())
For Each item In items
TextBox1.AutoCompleteCustomSource.Add(item)
Next
End Sub
Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles Me.Shown
MessageBox.Show(timer.Elapsed.ToString())
End Sub
End Class
and the message displayed "00:03:08.3167858", i.e. just over three minutes to load the list. I then changed the Load event handler to this:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
timer = Stopwatch.StartNew()
Dim rng As New Random
Dim a = Convert.ToInt32("a"c)
Dim z = Convert.ToInt32("z"c)
Dim items = Enumerable.Range(1, 26000).Select(Function(n) Convert.ToChar(rng.Next(a, z + 1)).ToString())
TextBox1.AutoCompleteCustomSource.AddRange(items.ToArray())
End Sub
so a single call to AddRange instead of calling Add in a loop, and the message was "00:00:00.0557427", i.e. just under 56 milliseconds. Is that better?
You can use paging to control the amount of returned data. Check this link for detailed examples.
Another way is to use (Task Async and await) so you won't lock your UI.
Here is a few last suggestions not related directly to the question but might help clean the code a bit:
you can skip the dataset and use the datatable directly, you don't need it for just one table.
Bind your results in the datatable to a datagridview or a combobox instead of iterating through your results and filling a textbox.
cheers

Get Source Code from Webview (VB for Metro)

I'm Making a Windows Phone's app that I can, From a webview called "DebWeb", get the ClassRoom of a specific class. The DebWeb load the site where is all the classRooms, but I want to make that my App search just my class.
Before I made an app with almost the same objetive (search the Name of a App from the Source Code), but it was made from VB for PC, now I'm working on VB for Metro (or for App Store) and I can't use the same code.
For example, On VB for PC I can use:
Dim EHTML = DebWeb.Document.All.Item(1)
Dim sourceString As String = EHTML.InnerHtml
'Use Regex Match to search from SourceString"
But on VB for Metro it's shows me the " 'Document' is not a member of 'Windows.UI.XAML.Controls.WebView' " error, so I can't get the Source Code from the page and I can't look for the ClassRoom.
I Looked on the MSDN page about Webview but the most close thing that I can do is to get the "DocumentTittle", but not the content.
This is my code, everything "works" except the "Source" variable:
Dim Source = DebWeb.[Control] 'Here is where I need the Control to get the SourceCode
Dim m As System.Text.RegularExpressions.Match = System.Text.RegularExpressions.Regex.Match(Source.ToString, _
"DERECHO CONSTITUCIONAL", _
System.Text.RegularExpressions.RegexOptions.IgnoreCase)
Edited with my Entire code:
Private Sub MainPage_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
Dim URL As String = "http://goo.gl/uqohKw"
Me.DebWeb.Navigate(New Uri(URL))
End Sub
Private Sub DebWeb_LoadCompleted(ByVal sender As Object, ByVal e As WebViewNavigationCompletedEventArgs)
LListo.Text = "Listo!"
Dim html As String = DebWeb.InvokeScriptAsync("eval", New String() {"document.documentElement.outerHTML;"}).ToString
Dim Source = html
Dim m As System.Text.RegularExpressions.Match = System.Text.RegularExpressions.Regex.Match(Source.ToString, _
"LECTURA CRÍTICA", _
System.Text.RegularExpressions.RegexOptions.IgnoreCase)
If (m.Success) Then
Dim key As String = m.Groups(1).Value
End If
End Sub
Something like this?
Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
Try
Dim html As String = Await myWebView.InvokeScriptAsync("eval", New String() {"document.documentElement.outerHTML;"})
Catch ex As Exception
End Try
End Sub
More Info here

HI, New to programming with textfiles loops and much more

i have a textfile which is in this format
and i am trying to use a stream reader to help me loop each word into a text box, i am new to programming and really need help because all other examples are too complicated for me to understand,
this is what i am trying to do :
Dim objectreader As New StreamReader("filepath")
Dim linereader(1) As String
linereader = Split(objectreader.ReadLine, ",")
For i As Integer = 0 To UBound(linereader)
Spelling_Test.txtSpelling1.Text = linereader(0)
Spelling_Test.txtSpelling2.Text = linereader(0)
Next
but only get the first line of the text file in to a textbox, i need it to loop to the next line so i can write the next line in!
your help would be much appreciated, and if possible then can you show it practically , if you dont understand what i am trying to do then please ask
It is a little confusing on what you are trying to do, it looks like your text file consists of a word and a hint, you only have one set of textbox's and 3 lines of information in your file.
This example show you how to incrementally read your Stream.
Public Class Form1
Dim objectreader As StreamReader
Dim linereader() As String
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
If IsNothing(objectreader) Then
objectreader = New StreamReader("C:\Temp\data.txt")
End If
linereader = Split(objectreader.ReadLine, ",")
If String.IsNullOrEmpty(linereader(0)) Then
objectreader.Close()
objectreader = Nothing
Else
txtSpelling1.Text = linereader(0) 'Word
txtSpelling2.Text = linereader(1) 'Hint
End If
End Sub
End Class
But in your case, I would probably just use the File.ReadAllLines Method
Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
Dim result As String() = File.ReadAllLines("C:\Temp\data.txt")
For x = 0 To UBound(result)
Dim c As Control = Controls.Find("txtSpelling" + (x + 1).ToString, True)(0)
If Not IsNothing(c) Then
c.Text = Split(result(x), ",")(0)
End If
Next
End Sub

Using a combo box to store items in an array from a text file and then using that array and its components in another form

I'm currently designing an application within visual basic using vb.net. The first form asks for login information and then prompts the next form to select a customer. The customer information is stored in a text file that gets put in an array. I next have a form for the user to display and edit that information. How can I use the array I already created in the previous form in my display and edit form?
Private Sub frmCustomerList_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim sr As StreamReader = File.OpenText("customer.txt")
Dim strLine As String
Dim customerInfo() As String
Do While sr.Peek <> -1
strLine = sr.ReadLine
customerInfo = strLine.Split("|")
cboCustomers.Items.Add(customerInfo(0))
customerList(count) = strLine
count = count + 1
Loop
End Sub
Private Sub cboCustomers_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cboCustomers.SelectedIndexChanged
Dim customerInfo() As String
Dim index As Integer = cboCustomers.SelectedIndex
Dim selectedCustomer As String = customerList(index)
customerInfo = selectedCustomer.Split("|")
End Sub
Make the next form require it in the constructor:
Public Class EditCustomer
Public Sub New(customerInfo As String())
InitializeComponent() 'This call is required, do not remove
'Yay! Now you have your info
End Sub
End Class
You'd call it by doing something like...
Dim editForm = New EditCustomerFrom(customerInfo)
editForm.Show()
Alternatively, you could have a property on the form you set.
Dim editForm = New EditCustomerFrom()
editForm.Customer = customerInfo
editForm.Show()
Then inside the Load event of that form, you'd write the logic that would display it looking at that property.
Aside: You should look at maybe defining an object to hold customer info and do some JSON or XML serialization for reading/writing to the file, IMO. This architecture is kind of not good as is....