Silverlight DomainCollectionView in VB.NET - silverlight

Anyone can share the code for the DomainCollectionView in VB.NET?
I have an error, Argument not specified for parameter 'op' of 'Private Sub OnLoadProductPMListCompleted(op As System.ServiceModel.DomainServices.Client.LoadOperation(Of ProductPM))'.
Public Sub New()
InitializeComponent()
Dim collectionViewLoader As DomainCollectionViewLoader(Of ProductPM)
collectionViewLoader = New DomainCollectionViewLoader(Of ProductPM)(Function() Me.LoadProductPMList(), Me.OnLoadProductPMListCompleted)
ProductCollectionView = New DomainCollectionView(collectionViewLoader, Products)
ProductCollectionView.Refresh()
Me.ProductListBox.ItemsSource = ProductCollectionView
End Sub
Public Function LoadProductPMList() As LoadOperation(Of ProductPM)
Dim qry As EntityQuery(Of ProductPM) = context.GetProductsQuery
Return context.Load(qry)
End Function
Private Sub OnLoadProductPMListCompleted(op As LoadOperation(Of ProductPM))
If op.HasError = True Then
ElseIf op.IsCanceled = False Then
CType(Products, EntityList(Of ProductPM)).Source = op.Entities
End If
End Sub

Sorry for the late reply, I have been busy. I've corrected the code, as noted below:
Dim context As ProductPMContext
Dim productCollectionView As DomainCollectionView
Dim products As IEnumerable(Of ProductPM)
Public Sub New()
InitializeComponent()
context = New ProductPMContext()
'You need to initialise the products collection
products = New EntityList(Of ProductPM)(context.ProductPMs)
Dim collectionViewLoader As DomainCollectionViewLoader(Of ProductPM)
'Have fixed this line, using AddressOf
collectionViewLoader = New DomainCollectionViewLoader(Of ProductPM)(AddressOf LoadProductPMList, AddressOf OnLoadProductPMListCompleted)
productCollectionView = New DomainCollectionView(collectionViewLoader, products)
productCollectionView.Refresh()
ProductListBox.ItemsSource = productCollectionView
End Sub
Public Function LoadProductPMList() As LoadOperation(Of ProductPM)
Return context.Load(context.GetProductsQuery)
End Function
Private Sub OnLoadProductPMListCompleted(ByVal op As LoadOperation(Of ProductPM))
If op.HasError = True Then
ElseIf op.IsCanceled = False Then
CType(products, EntityList(Of ProductPM)).Source = op.Entities
End If
End Sub
Hope this helps...
Chris

Related

Are generics the answer to handling varying UI Elements concisely?

Working with Visual Basic (+ DevExpress, WPF) and I've got the fields changing colours based on some validation checks, but the code duplication is bothersome. I feel as though implementing generics is the answer but am struggling with implementation.
Private Sub txt_LostFocus(sender As Object, e As RoutedEventArgs) Handles txtFileNo.LostFocus, txtDataLoc.LostFocus,
txtCltName.LostFocus, dtCurYE.LostFocus, dtPrevYE.LostFocus, seMinThres.LostFocus, cboDivType.LostFocus, cboCltType.LostFocus
Dim todim As String = sender.GetType.ToString
Select Case True
Case todim.EndsWith("TextBox")
makeTB(sender)
Case todim.EndsWith("DateEdit")
makeDE(sender)
Case todim.EndsWith("SpinEdit")
makeSE(sender)
Case todim.EndsWith("ComboBoxEdit")
makeCB(sender)
End Select
End Sub
Private Sub makeTB(sender As Object)
Dim btn As TextBox = CType(sender, TextBox)
If commandFN.bValidNewClient(btn.Name) Then
btn.Background = New SolidColorBrush(Colors.LawnGreen)
Else
btn.Background = New SolidColorBrush(Colors.Red)
End If
End Sub
Private Sub makeDE(sender As Object)
Dim btn As DateEdit = CType(sender, DateEdit)
If commandFN.bValidNewClient(btn.Name) Then
btn.Background = New SolidColorBrush(Colors.LawnGreen)
Else
btn.Background = New SolidColorBrush(Colors.Red)
End If
End Sub
Private Sub makeSE(sender As Object)
Dim btn As SpinEdit = CType(sender, SpinEdit)
If commandFN.bValidNewClient(btn.Name) Then
btn.Background = New SolidColorBrush(Colors.LawnGreen)
Else
btn.Background = New SolidColorBrush(Colors.Red)
End If
End Sub
Private Sub makeCB(sender As Object)
Dim btn As ComboBoxEdit = CType(sender, ComboBoxEdit)
If commandFN.bValidNewClient(btn.Name) Then
btn.Background = New SolidColorBrush(Colors.LawnGreen)
Else
btn.Background = New SolidColorBrush(Colors.Red)
End If
End Sub
Why don't you simply cast the sender argument to Control?:
Private Sub txt_LostFocus(sender As Object, e As RoutedEventArgs) Handles txtFileNo.LostFocus, txtDataLoc.LostFocus,
txtCltName.LostFocus, dtCurYE.LostFocus, dtPrevYE.LostFocus, seMinThres.LostFocus, cboDivType.LostFocus, cboCltType.LostFocus
Dim obj As Control = TryCast(sender, Control)
If obj IsNot Nothing Then
make(obj)
End If
End Sub
Private Sub make(sender As Control)
If commandFN.bValidNewClient(sender.Name) Then
sender.Background = New SolidColorBrush(Colors.LawnGreen)
Else
sender.Background = New SolidColorBrush(Colors.Red)
End If
End Sub
In this instance you can just use the base class, Control, rather than writing a method using generics:
Private Sub txt_LostFocus(sender As Object, e As RoutedEventArgs) Handles txtFileNo.LostFocus, txtDataLoc.LostFocus,
txtCltName.LostFocus, dtCurYE.LostFocus, dtPrevYE.LostFocus, seMinThres.LostFocus, cboDivType.LostFocus, cboCltType.LostFocus
Dim todim As String = sender.GetType.ToString
Dim btn As Control = CType(sender, Control) 'Cast to base class here
If commandFN.bValidNewClient(btn.Name) Then
btn.Background = New SolidColorBrush(Colors.LawnGreen)
Else
btn.Background = New SolidColorBrush(Colors.Red)
End If
End Sub

Using a Back Ground worker in VB.Net WPF

I'm new to WPF and the whole threading format. I'm pretty sure I'm close to getting this correct, however, I'm getting the error. "The calling thread cannot access this object because a different thread owns it." I was getting this error before and i had to add the "Dispatcher.BeginInvoke(Sub() LoadLoad())" line, but I'm still getting the error. When i get the error, it highlights the line "Dim dc = New VSCSystemEntities1" in the LoadLoad() sub method. Any help would be appreciated. Thanks.
Public Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
InitialLoad()
End Sub
Private Sub InitialLoad()
Try
loadPayeeTransactionAccounts()
bw.WorkerSupportsCancellation = True
bw.WorkerReportsProgress = True
AddHandler bw.DoWork, AddressOf bw_DoWork
AddHandler bw.ProgressChanged, AddressOf bw_ProgressChanged
AddHandler bw.RunWorkerCompleted, AddressOf bw_RunWorkerCompleted
Catch ex As Exception
MessageBox.Show(ex.Message, "Atlas Error while Loading", MessageBoxButton.OK, MessageBoxImage.Error)
Finally
End Try
End Sub
Private Sub bw_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs)
Dim worker As BackgroundWorker = CType(sender, BackgroundWorker)
LoadLoad()
End Sub
Private Sub LoadLoad()
Dispatcher.BeginInvoke(Sub() LoadLoad())
txtSearch.Text = ""
Dim dc = New VSCSystemEntities1
Dim ContainsSearch = New List(Of tblActgPayeeTransactionAccounts2)
Try
ContainsSearch = (From z In dc.tblActgPayeeTransactionAccounts2 Select z Where z.intActgAcctID <> 236).ToList
For Each item In (ContainsSearch)
For i = 1 To ContainsSearch.Count
aList.add(New PayeeTransactions() With {.AccountingAccountID = item.intActgAcctID, .ProgramCode = item.chrPgmCode, _
.CarrierCode = item.intCarrierCode, .DealerNumber = item.chrDlrNum, _
.CoverageCode = item.chrCvgCode, .PayeeType = item.chrPayeeType, .FeeType = item.chrFeeType, .PayeeCode = item.intPayeeCode.ToString, _
.TransactionType = item.chrTransType, .AccountID = item.inbAcctgID, _
.CarrierDescription = item.chrCarrierDesc, .CarrierDescriptionShort = item.chrCarrierDescSht, _
.AccountCustomerID = item.intAcctCustID.ToString, .AccountCode = item.intAcctCo, _
.AccountCodeReceived = item.intAcctCoRec})
System.Threading.Thread.Sleep(200)
bw.ReportProgress(i)
Next
Next
lblCount.Content = ContainsSearch.Count()
dGrid.ItemsSource = Nothing
_ContainsText = CollectionViewSource.GetDefaultView(aList)
dGrid.ItemsSource = _ContainsText
Catch ex As Exception
Throw New Exception("Error: " & ex.Message)
Finally
dc.Dispose()
End Try
End Sub
Private Sub bw_ProgressChanged(ByVal sender As Object, ByVal e As ProgressChangedEventArgs)
Me.tbProgress.Text = e.ProgressPercentage.ToString() & "%"
End Sub
Private Sub bw_RunWorkerCompleted(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs)
If e.Cancelled = True Then
Me.tbProgress.Text = "Canceled!"
ElseIf e.Error IsNot Nothing Then
Me.tbProgress.Text = "Error: " & e.Error.Message
Else
Me.tbProgress.Text = "Done!"
End If
End Sub
Private Sub btnRefresh_Click(sender As Object, e As RoutedEventArgs) Handles btnRefresh.Click
If Not bw.IsBusy = True Then
bw.RunWorkerAsync()
End If
End Sub

WPF Multi-Threading and rotating image

This one has driven me nuts for long enough.
Start a background thread to download data from a webservice on a new thread then show an image on the status bar and change the text.
I have tried with Dispatcher (with each priority) but nothing happens until the threaded sub completes. The closest I can get is implementing the equivalent of DoEvents that at least loads the image and the text, but then the image stops spinning until the thread completes.
Any ideas?
Public Sub Return_DT(ByVal TableName As String)
CurrentDT = TableName
If DownloadingDS Is Nothing Then
DownloadingDS = New Dictionary(Of String, String)
End If
If DownloadingDS.ContainsKey(TableName) = False Then
DownloadingDS.Add(TableName, "Loading")
Else
Exit Sub
End If
Select Case TableName
Case "A_Documents"
strSQL = "SELECT Document_ID, Account_Type, Account_No, Document_Description, Accounts_Only, Open_Editing, Editing_Name, Updated_Name, Updated FROM A_Documents"
Case Else
strSQL = "SELECT * FROM " & TableName
End Select
' Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background, CType(Sub() LoadMetroImage(), SendOrPostCallback), Nothing)
'Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background, CType(Sub() ChangeLeftStatusText("Downloading " & CurrentDT & " data..."), SendOrPostCallback), Nothing)
LoadMetroImage()
ChangeLeftStatusText("Downloading " & CurrentDT & " data...")
Application.Current.MainWindow.FindName("MainMetroStatusBar")
Dim vWorker As New BackgroundWorker
AddHandler vWorker.DoWork, AddressOf BackgroundDownload
AddHandler vWorker.RunWorkerCompleted, AddressOf DownloadCompleted
vWorker.RunWorkerAsync()
DoEvents()
End Sub
This is the closest I can get
Public Sub DoEvents()
Dim frame As New DispatcherFrame()
Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background, New DispatcherOperationCallback(AddressOf ExitFrame), frame)
Dispatcher.PushFrame(frame)
End Sub
Public Function ExitFrame(ByVal f As Object) As Object
CType(f, DispatcherFrame).Continue = False
Return Nothing
End Function
=== EDIT === How Return_DT is called
Public Function DT_Return(ByVal DT As DataTable, ByVal TableName As String) As DataTable
Try
If Not DT Is Nothing Then
If DT_CheckUpdated(TableName) = True Then
Return DT
Else
Return_DT(TableName)
vService = New Service1Client
Dim DS As DataSet = vService.ReturnDataSet("SELECT * FROM " & TableName, Current_HOA_ID)
Dim vDT As DataTable = DS.Tables(0).Copy
DS.Dispose()
Return vDT
End If
Else
Return_DT(TableName)
vService = New Service1Client
Dim DS As DataSet = vService.ReturnDataSet("SELECT * FROM " & TableName, Current_HOA_ID)
Dim vDT As DataTable = DS.Tables(0).Copy
DS.Dispose()
Return vDT
End If
Catch ex As Exception
EmailError(ex)
Return Nothing
End Try
End Function
I found the solution was to use Dispatcher.Timer in the UI thread to check every second to see if the DT had been downloaded..
Public Function DT_Return(ByVal DT As DataTable, ByVal TableName As String) As DataTable
Try
If Not DT Is Nothing Then
If DT_CheckUpdated(TableName) = True Then
Return DT
Else
CurrentlyDownloading = True
Return_DT(TableName)
Dim vTimer As New DispatcherTimer
vTimer.Interval = TimeSpan.FromMilliseconds(1000)
AddHandler vTimer.Tick, Sub(sender As Object, e As EventArgs)
Do While CurrentlyDownloading = True
Loop
vTimer.Stop()
End Sub
vTimer.Start()
Return DT
End If
Else
CurrentlyDownloading = True
Return_DT(TableName)
Dim vTimer As New DispatcherTimer
vTimer.Interval = TimeSpan.FromMilliseconds(1000)
AddHandler vTimer.Tick, Sub(sender As Object, e As EventArgs)
Do While CurrentlyDownloading = True
Loop
vTimer.Stop()
End Sub
vTimer.Start()
Return DT
End If
Catch ex As Exception
EmailError(ex)
Return Nothing
End Try
End Function

WPF VB.NET 4.0 DatagridComboBoxColumn binding at runtime

I had a similar question for DatagridComboboxColumn but that shown me how to use the .itemsource to bind to an array outside of the datagrid. I am having a problem trying to bind to the collection that the datagrid is bound to at runtime.
I have included a working test program for how I am approaching this.
Class MainWindow
Dim ServerInfoArray As List(Of ServerInfo) = New List(Of ServerInfo)
Private Sub GetInfo(ByVal list As List(Of String))
For Each server As String In list
Dim tempip As ComboBoxItem = New ComboBoxItem
Dim tempip2 As ComboBoxItem = New ComboBoxItem
Dim sinfo As ServerInfo = New ServerInfo
tempip.Content = "192.129.123.23"
tempip2.Content = "23.213.223.21"
sinfo.IPArray.Items.Add(tempip)
sinfo.IPArray.Items.Add(tempip2)
sinfo.ServerName = server
ServerInfoArray.Add(sinfo)
DataGrid1.Items.Refresh()
Next
End Sub
Private Sub Button1_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles Button1.Click
Dim serverlist As List(Of String) = New List(Of String)
serverlist.Add("Test")
serverlist.Add("Random")
serverlist.Add("Local")
GetInfo(serverlist)
End Sub
Private Sub Window_Loaded(sender As System.Object, e As System.Windows.RoutedEventArgs) Handles MyBase.Loaded
Dim Col_Serial As DataGridTextColumn = New DataGridTextColumn()
Col_Serial.Binding = New Binding("Servername")
Col_Serial.Header = "Servername"
Col_Serial.Width = 40
Dim Col_IPArray = New DataGridComboBoxColumn()
Col_IPArray.Header = "IP Addresses"
Col_IPArray.IsReadOnly = True
'Col_IPArray.ItemsSource = serverInfoArray ' Don't know how to do this.
Col_IPArray.SelectedValuePath = "IPArray"
Col_IPArray.DisplayMemberPath = "IPArray"
DataGrid1.Columns.Add(Col_Serial)
DataGrid1.Columns.Add(Col_IPArray)
DataGrid1.ItemsSource = ServerInfoArray
End Sub
End Class
Class ServerInfo
Dim _Servername As String
Dim _IPArray As ComboBox
Public Property Servername() As String
Get
Return _Servername
End Get
Set(ByVal value As String)
_Servername = value
End Set
End Property
Public Property IPArray As ComboBox
Get
Return _IPArray
End Get
Set(ByVal value As ComboBox)
_IPArray = value
End Set
End Property
Public Sub New()
_Servername = Nothing
_IPArray = New ComboBox
End Sub
End Class
I can get all Strings and Boolean to bind.
I do not know how I can bind this DataGridComboBoxColumn to the list of attached on the property. I cannot use XAML as I need to do this at runtime.
Dim Col_Serial As DataGridComboColumn = New DataGridComboColumn()
Col_Serial.ItemSource = GetData();
Col_Serial.SelectedValuePath = "ID_value";
Col_Serial.DisplayMemberPath = "displya_col";
Col_Serial.Header = "Disk4"
Col_Serial.Width = 40
Col_Serial.IsEnabled= false;
dg.Columns.Add(Col_serial);

WPF asynchronous invoke question

What's wrong in my code? It's not updating the TextBox and the ProgressBar while deleting files.
Imports System.Windows.Threading
Imports System.IO
Class MainWindow
Private Sub bt_Click(ByVal sender As Object,
ByVal e As RoutedEventArgs) Handles bt.Click
Dim sb As New System.Text.StringBuilder
Dim files = IO.Directory.EnumerateFiles(
My.Computer.FileSystem.SpecialDirectories.Temp, "*.*",
SearchOption.TopDirectoryOnly)
Dim count = files.Count
pb.Minimum = 0
pb.Maximum = count
For i = 0 To count - 1
Dim f = files(i)
Dispatcher.BeginInvoke(
New Action(Of String, Integer)(
Sub(str, int)
tb.SetValue(TextBox.TextProperty, str)
pb.SetValue(ProgressBar.ValueProperty, int)
End Sub),
DispatcherPriority.Send,
f, i + 1)
Try
File.Delete(f)
Catch ex As Exception
sb.AppendLine(f)
End Try
Dim exceptions = sb.ToString
Stop
Next
End Sub
End Class
I got this working with the BackgroundWorker object. This places your work in a background thread, with calls to update the UI going through the ProgressChanged event. I also used Invoke instead of BeginInvoke within the work loop, which forces the loop to wait for the UI to become updated before it proceeds.
Imports System.ComponentModel
Imports System.IO
Class MainWindow
Private WithEvents bw As New BackgroundWorker
Private Sub Button1_Click(ByVal sender As System.Object,
ByVal e As RoutedEventArgs) Handles btn.Click
pb.Minimum = 0
pb.Maximum = 100
bw.WorkerReportsProgress = True
bw.RunWorkerAsync()
End Sub
Private Sub bw_DoWork(ByVal sender As Object,
ByVal e As DoWorkEventArgs) Handles bw.DoWork
Dim sb As New System.Text.StringBuilder
Dim files = IO.Directory.EnumerateFiles(
My.Computer.FileSystem.SpecialDirectories.Temp, "*.*",
SearchOption.TopDirectoryOnly)
Dim count = files.Count
Me.Dispatcher.BeginInvoke(Sub()
tb.Text = "SOMETHING ELSE"
End Sub)
For i = 0 To count - 1
Dim f = files(i)
Dim myI = i + 1
Me.Dispatcher.Invoke(
Sub()
bw.ReportProgress(CInt((myI / count) * 100), f)
End Sub)
'Try
' File.Delete(f)
'Catch ex As Exception
' sb.AppendLine(f)
'End Try
Dim exceptions = sb.ToString
'Stop
Next
End Sub
Private Sub bw_ProgressChanged(
ByVal sender As Object,
ByVal e As ProgressChangedEventArgs) Handles bw.ProgressChanged
Dim fString As String = TryCast(e.UserState, String)
Me.Dispatcher.BeginInvoke(Sub()
tb.Text = fString
End Sub)
End Sub
End Class

Resources