Friday, December 31, 2010
Exporting Data from TopSpeed Data bases
The easiest way I found to programatically access the data is to use MS access to pull the tps files as an external data source and then use .Net to connect to that access db. I also build a data mapper that will read the tps db, display sample data, and give you a list of "destination" fields from a text file.
I used this method to pull data from a Time Matters db and pump it into an Outlook / Exchange shared folder. The nice thing about doing it this way is I was able to map the user defined fields I wanted, and define the custom form for outlook for the client.
I can't share the tps driver, 'cause those pesky things call licenses and all, but I can definitely help someone out with pumping data if they need.
Friday, November 5, 2010
Observable Dictionary
Public Class ObservableDictionary(Of T, P)
Implements IDictionary(Of T, P)
Event ItemAdded(ByVal Key As T)
Event ItemRemoved(ByVal Key As T, ByVal value As P, ByVal Success As Boolean)
Event ItemChanged(ByVal Key As T, ByVal OldValue As P, ByVal NewValue As P)
Dim _BaseDictionary As Dictionary(Of T, P)
Sub New()
_BaseDictionary = New Dictionary(Of T, P)
End Sub
Public Sub Clear() Implements System.Collections.Generic.ICollection(Of System.Collections.Generic.KeyValuePair(Of T, P)).Clear
_BaseDictionary.Clear()
End Sub
Public Function Contains(ByVal item As System.Collections.Generic.KeyValuePair(Of T, P)) As Boolean Implements System.Collections.Generic.ICollection(Of System.Collections.Generic.KeyValuePair(Of T, P)).Contains
Return _BaseDictionary.Contains(item)
End Function
Public Sub CopyTo(ByVal array() As System.Collections.Generic.KeyValuePair(Of T, P), ByVal arrayIndex As Integer) Implements System.Collections.Generic.ICollection(Of System.Collections.Generic.KeyValuePair(Of T, P)).CopyTo
Throw New NotImplementedException
End Sub
Public ReadOnly Property Count As Integer Implements System.Collections.Generic.ICollection(Of System.Collections.Generic.KeyValuePair(Of T, P)).Count
Get
Return _BaseDictionary.Count
End Get
End Property
Public ReadOnly Property IsReadOnly As Boolean Implements System.Collections.Generic.ICollection(Of System.Collections.Generic.KeyValuePair(Of T, P)).IsReadOnly
Get
Throw New NotImplementedException
End Get
End Property
Public Function RemovePair(ByVal item As System.Collections.Generic.KeyValuePair(Of T, P)) As Boolean Implements System.Collections.Generic.ICollection(Of System.Collections.Generic.KeyValuePair(Of T, P)).Remove
Dim Value As P = _BaseDictionary(item.Key)
Dim Success = _BaseDictionary.Remove(item.Key)
RaiseEvent ItemRemoved(item.Key, Value, Success)
Return Success
End Function
Public Function ContainsKey(ByVal key As T) As Boolean Implements System.Collections.Generic.IDictionary(Of T, P).ContainsKey
Return _BaseDictionary.ContainsKey(key)
End Function
Default Public Property Item(ByVal key As T) As P Implements System.Collections.Generic.IDictionary(Of T, P).Item
Get
Return _BaseDictionary.Item(key)
End Get
Set(ByVal value As P)
Dim oldvalue As P = _BaseDictionary.Item(key)
_BaseDictionary.Item(key) = value
RaiseEvent ItemChanged(key, oldvalue, value)
End Set
End Property
Public ReadOnly Property Keys As System.Collections.Generic.ICollection(Of T) Implements System.Collections.Generic.IDictionary(Of T, P).Keys
Get
Return _BaseDictionary.Keys
End Get
End Property
Public Function Remove(ByVal key As T) As Boolean Implements System.Collections.Generic.IDictionary(Of T, P).Remove
Dim value = _BaseDictionary(key)
Dim Success = _BaseDictionary.Remove(key)
RaiseEvent ItemRemoved(key, Value, Success)
Return Success
End Function
Public Function TryGetValue(ByVal key As T, ByRef value As P) As Boolean Implements System.Collections.Generic.IDictionary(Of T, P).TryGetValue
If _BaseDictionary.ContainsKey(key) Then
value = _BaseDictionary(key)
Return True
Else
value = Nothing
Return False
End If
End Function
Public ReadOnly Property Values As System.Collections.Generic.ICollection(Of P) Implements System.Collections.Generic.IDictionary(Of T, P).Values
Get
Return _BaseDictionary.Values
End Get
End Property
Public Function GetEnumerator() As System.Collections.Generic.IEnumerator(Of System.Collections.Generic.KeyValuePair(Of T, P)) Implements System.Collections.Generic.IEnumerable(Of System.Collections.Generic.KeyValuePair(Of T, P)).GetEnumerator
Return _BaseDictionary.GetEnumerator
End Function
Public Function GetEnumerator1() As System.Collections.IEnumerator Implements System.Collections.IEnumerable.GetEnumerator
Throw New NotImplementedException
End Function
Public Sub AddPair(ByVal item As System.Collections.Generic.KeyValuePair(Of T, P)) Implements System.Collections.Generic.ICollection(Of System.Collections.Generic.KeyValuePair(Of T, P)).Add
_BaseDictionary.Add(item.Key, item.Value)
RaiseEvent ItemAdded(item.Key)
End Sub
Public Sub Add(ByVal key As T, ByVal value As P) Implements System.Collections.Generic.IDictionary(Of T, P).Add
_BaseDictionary.Add(key, value)
RaiseEvent ItemAdded(key)
End Sub
End Class
Tuesday, July 27, 2010
DataForm + Combobox == Silly Bugs (combobox in dataFormToolkit:DataField)
Each time the form reloads (by adding, removing items from the collection) the bindings are reset, and not nicely... Long story short we found it impossible to get the combo box to work correctly using anything in XAML. For some reason "they" haven't made it easy in Silverlight.
To work around this issue the easiest thing I could come up with turns out to be pretty neat. On the Datafield that held the combo box, there is a Loaded event, so I thunk (yes, thunk; We were very frustrated...) why not just add a new combobox each time it loads so we KNOW that the bindings are correct.
Here is what we did:
Added an empty datafield to the grid in the dataform:
dataFormToolkit:DataField Grid.Row="5" Grid.Column="0" Loaded="ComboBoxField_Loaded" Label="Period Type" LabelPosition="Auto"
Note the lovely RED event handler.
in this hanlder we define the contents of this DataField:
Private Sub ComboBoxField_Loaded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
Dim comboBoxField As DataField = sender 'Get the dataField that sent us here
Dim BindingForItems As New Binding With {.Source = ItemListDomainDataSource,
.Path = New PropertyPath("Data")}
'No need to set Source as it will pick up from the formDim BindingForValue As New Binding With {.Path = New PropertyPath("ItemValue"),
.Mode = BindingMode.TwoWay}
Dim combobox As ComboBox = New ComboBox 'Make a new combobox
combobox.DisplayMemberPath = "Name" 'Set Paths FIRST, yes, they have to be done first
combobox.SelectedValuePath = "PeriodType"
combobox.SetBinding(combobox.ItemsSourceProperty, BindingForItems)
combobox.SetBinding(combobox.SelectedValueProperty, BindingForValue)
'add styling wireups if not using default styling
comboBoxField.Content = combobox 'Push the new combobox back to the datafield
End Sub
So, load the data field, add the combobox, with its bindings already set. Now, for all those that are super concerned, like my friend John, about performance etc, you should go look at his blog, 'cause i am pretty sure he will take this and turn it into some shared resource.... :)