I have implemented a LongListSelector for my Windows Phone 7 app. However when I tap an item it doesn't navigate to the desired page. Does anyone know why and how this can be fixed? Below is my code. Each page has it's own uri and I want to navigate to different pages.
All help would be very much appreciated.
Many thanks
Code:
Imports System.Linq
Imports Microsoft.Phone.Controls
Partial Public Class Victoria_line
Inherits PhoneApplicationPage
Public Sub New()
InitializeComponent()
Dim source As New List(Of JumpDemo)()
source.Add(New JumpDemo() With { _
.Name = "Blackhorse Road", _
.FareZone = "Fare zone 3", _
.GroupBy = "b", _
.Link = "/Lines and Stations/Victoria/Blackhorse_Road_(Victoria).xaml" _
})
source.Add(New JumpDemo() With { _
.Name = "Warren Street", _
.FareZone = "Fare zone 1", _
.GroupBy = "w", _
.Link = "/Lines and Stations/Victoria/Warren_Street_(Victoria).xaml" _
})
Dim MygroupBy = From jumpdemo In source _
Group jumpdemo By jumpdemo.GroupBy Into c = Group _
Order By GroupBy _
Select New _
Group(Of JumpDemo)(GroupBy, c)
Me.Victoria_line.ItemsSource = MygroupBy
End Sub
Private Sub Victoria_line_SelectionChanged(ByVal sender As Object, ByVal e As SelectionChangedEventArgs)
If Victoria_line.SelectedItem = Nothing Then
Return
End If
Dim addressString As String = "/StationPage.xaml"
Dim pageUri As Uri = New Uri(addressString, UriKind.Relative)
NavigationService.Navigate(pageUri)
' Reset selected item to -1 (no selection)
Victoria_line.SelectedItem = Nothing
End Sub
End Class
Public Class Group(Of T)
Implements IEnumerable(Of T)
Public Sub New(name As String, items As IEnumerable(Of T))
Me.Title = name
Me.Items = New List(Of T)(items)
End Sub
Public Overrides Function Equals(obj As Object) As Boolean
Dim that As Group(Of T) = TryCast(obj, Group(Of T))
Return (that IsNot Nothing) AndAlso (Me.Title.Equals(that.Title))
End Function
Public Property Title() As String
Get
Return m_Title
End Get
Set(value As String)
m_Title = value
End Set
End Property
Private m_Title As String
Public Property Items() As IList(Of T)
Get
Return m_Items
End Get
Set(value As IList(Of T))
m_Items = value
End Set
End Property
Private m_Items As IList(Of T)
Public Function GetEnumerator() As IEnumerator(Of T) Implements IEnumerable(Of T).GetEnumerator
Return Me.Items.GetEnumerator()
End Function
Private Function System_Collections_IEnumerable_GetEnumerator() As System.Collections.IEnumerator Implements System.Collections.IEnumerable.GetEnumerator
Return Me.Items.GetEnumerator()
End Function
End Class
Public Class Victoria
Public Property Name() As String
Get
Return m_Name
End Get
Set(value As String)
m_Name = value
End Set
End Property
Private m_Name As String
Public Property FareZone() As String
Get
Return m_FareZone
End Get
Set(value As String)
m_FareZone = value
End Set
End Property
Private m_FareZone As String
Public Property GroupBy() As String
Get
Return m_GroupBy
End Get
Set(value As String)
m_GroupBy = value
End Set
End Property
Private m_GroupBy As String
Public Property Link() As Uri
Get
Return m_Link
End Get
Set(value As Uri)
m_Link = value
End Set
End Property
Private m_Link As Uri
End Class
If what you are trying to achieve is navigate to another page when you tap on an item you should just register for the Tap event inside your Item DataTemplate and in the event handler do something like this:
Private Sub Item_Tap(sender As Object, e As GestureEventArgs)
Dim element As FrameworkElement = TryCast(sender, FrameworkElement)
Dim item As JumpDemo = TryCast(element.DataContext, JumpDemo)
Dim addressString As String = item.Link
Dim pageUri As Uri = New Uri(addressString, UriKind.Relative)
NavigationService.Navigate(pageUri)
End Sub
Related
I have written my on editor for a property in a propertyGrid. Everything works as expected, but for best user experience i want to hide the expand button on the propertygrid for this property. Can someone tell me how to do that?
I am using a custom typeconverter
Public Class PropertyLanguageSetupEditor
Inherits UITypeEditor
Public Overrides Function GetEditStyle(context As ITypeDescriptorContext) As UITypeEditorEditStyle
Return UITypeEditorEditStyle.Modal
End Function
Public Overrides Function EditValue(context As ITypeDescriptorContext, provider As IServiceProvider, value As Object) As Object
Try
Dim svc As IWindowsFormsEditorService = CType(provider.GetService(GetType(IWindowsFormsEditorService)), IWindowsFormsEditorService)
Dim settings As LanguageSettings = value
Dim oldSettings As LanguageSettings = CType(value, LanguageSettings).Clone
If Not svc Is Nothing And Not settings Is Nothing Then
Dim form As New PropertyLanguageSetupWindow(settings)
If svc.ShowDialog(form) = DialogResult.OK Then
value = form.Data
Else
value = oldSettings
End If
End If
Catch ex As Exception
Debug.WriteLine(ex.Message)
End Try
Return MyBase.EditValue(context, provider, value)
End Function
End Class
And this is de property which uses the typeConverter
<DisplayName("Properties Translation Settings"), Editor(GetType(PropertyLanguageSetupEditor), GetType(System.Drawing.Design.UITypeEditor)), TypeConverter(GetType(BrowsableTypeConverter)),
Description("Settings for the output text"), BrowsableTypeConverter.BrowsableLabelStyleAttribute(BrowsableTypeConverter.LabelStyle.lsEllipsis),
Category("10 - DXF Export"), Browsable(True)>
Public Property TranslationSettings As LanguageSettings = New LanguageSettings
My BrowsAbleTypeConverter
Public Class BrowsableTypeConverter
Inherits ExpandableObjectConverter
Public Enum LabelStyle
lsNormal
lsTypeName
lsEllipsis
lsText
End Enum
Public Class BrowsableLabelStyleAttribute
Inherits System.Attribute
Private eLabelStyle As LabelStyle = LabelStyle.lsEllipsis
Public Sub New(ByVal LabelStyle As LabelStyle)
eLabelStyle = LabelStyle
End Sub
Public Property LabelStyle() As LabelStyle
Get
Return eLabelStyle
End Get
Set(ByVal value As LabelStyle)
eLabelStyle = value
End Set
End Property
End Class
Public Class BrowsableLabelTextAttribute
Inherits System.Attribute
Private strText As String = ""
Public Sub New(ByVal value As String)
strText = value
End Sub
Public Property Text() As String
Get
Return strText
End Get
Set(ByVal value As String)
strText = value
End Set
End Property
End Class
Public Overrides Function CanConvertTo(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal destinationType As System.Type) As Boolean
Return True
End Function
Public Overrides Function ConvertTo(ByVal context As System.ComponentModel.ITypeDescriptorContext, ByVal culture As System.Globalization.CultureInfo, ByVal value As Object, ByVal destinationType As System.Type) As Object
Dim Style As BrowsableLabelStyleAttribute = context.PropertyDescriptor.Attributes(GetType(BrowsableLabelStyleAttribute))
If Not Style Is Nothing Then
Select Case Style.LabelStyle
Case LabelStyle.lsNormal
Return MyBase.ConvertTo(context, culture, value, destinationType)
Case LabelStyle.lsTypeName
Return "(" & value.GetType.Name & ")"
Case LabelStyle.lsEllipsis
Return "(...)"
Case LabelStyle.lsText
Dim text As BrowsableLabelTextAttribute = context.PropertyDescriptor.Attributes(GetType(BrowsableLabelTextAttribute))
If text IsNot Nothing Then
Return text.Text
End If
End Select
End If
Return MyBase.ConvertTo(context, culture, value, destinationType)
End Function
End Class
Your TypeConverter derives from ExpandableObjectConverter, which means subproperties will be visible because of its GetPropertiesSupported method returning true.
In your TypeConverter, you simply need to override GetPropertiesSupported and return false.
I am trying to create an arraylist of objects, and everything is working fine except that the value of all 11 objects are the same. I've have tried multiple ways of writing the code, but I get the same outcome everytime.
arrFullProdList collects the name of all the products in the database. This is working properly. arrProducts is where I am having the issue with all the objects being the same.
What am I doing wrong?
Declared
Private objReader As SqlDataReader
Private objProducts As New CProducts
Private arrFullProdList As ArrayList = New ArrayList
Public arrProdcuts As ArrayList = New ArrayList
class CProduct
Public Class CProduct
Private _pstrProdId As String
Private _pstrProdDesc As String
Private _psngWhCost As Single
Private _psngRetPrice As Single
Private _pblnTaxable As Boolean
Private _isNewProd As Boolean
Public Sub New()
'_pstrProdId = ""
'_pstrProdDesc = ""
'_psngWhCost = 0
'_psngRetPrice = 0
'_pblnTaxable = False
'_isNewProd = False
End Sub
Public Property strProdId() As String
Get
Return _pstrProdId
End Get
Set(strVal As String)
_pstrProdId = strVal
End Set
End Property
Public Property strProdDesc() As String
Get
Return _pstrProdDesc
End Get
Set(strVal As String)
_pstrProdDesc = strVal
End Set
End Property
Public Property sngWhCost() As Single
Get
Return _psngWhCost
End Get
Set(sngVal As Single)
_psngWhCost = sngVal
End Set
End Property
Public Property sngRetPrice() As Single
Get
Return _psngRetPrice
End Get
Set(sngVal As Single)
_psngRetPrice = sngVal
End Set
End Property
Public Property blnTaxable() As Boolean
Get
Return _pblnTaxable
End Get
Set(blnVal As Boolean)
_pblnTaxable = blnVal
End Set
End Property
Public Property IsNewProd() As Boolean
Get
Return _isNewProd
End Get
Set(blnVal As Boolean)
_isNewProd = blnVal
End Set
End Property
Public ReadOnly Property GetSaveParameters() As ArrayList
Get
Dim paramList As New ArrayList
paramList.Add(New SqlClient.SqlParameter("ProdId", _pstrProdId))
paramList.Add(New SqlClient.SqlParameter("ProdDesc", _pstrProdDesc))
paramList.Add(New SqlClient.SqlParameter("WhCost", _psngWhCost))
paramList.Add(New SqlClient.SqlParameter("RetPrice", _psngRetPrice))
paramList.Add(New SqlClient.SqlParameter("Taxable", _pblnTaxable))
Return paramList
End Get
End Property
Public Function Save() As Integer
'return -1 if the ID already exists and we can't create a new record
If _isNewProd Then
Dim strRes As String = myDB.GetSingleValueFromSP("sp_CheckProdIDExists", _
New SqlClient.SqlParameter("ProdId", _pstrProdId))
If Not strRes = 0 Then
Return -1 'ID NOT unique!!
End If
End If
'if not a new member or it is new and is unique, then do the save (update or insert)
Return myDB.ExecSP("sp_SaveProduct", GetSaveParameters)
End Function
End Class
class CProducts
Imports System.Data.SqlClient
Public Class CProducts
'This class represents the Members table and the associated business rules
Private _Product As CProduct
'constructor
Public Sub New()
'instantiate the CMember object
_Product = New CProduct
End Sub
Public ReadOnly Property CurrentObject() As CProduct
Get
Return _Product
End Get
End Property
Public Sub Clear()
_Product = New CProduct
End Sub
Public Sub CreateNewProduct() 'call me when you are clearing the screen to create a new member
Clear()
_Product.IsNewProd = True
End Sub
Public Function Save() As Integer
Return _Product.Save
End Function
Public Function GetProductList() As SqlDataReader
Return myDB.GetDataReaderBySP("dbo.sp_GetProductList")
End Function
Public Function GetProducIdList() As SqlDataReader
Return myDB.GetDataReaderBySP("dbo.sp_GetProductIdList")
End Function
Public Function GetProductByName(strProdDesc As String) As CProduct
Dim params As New ArrayList
Dim param1 As New SqlParameter("proddesc", strProdDesc)
params.Add(param1)
FillObject(myDB.GetDataReaderBySP("dbo.sp_GetProductByName", params))
Return _Product
End Function
Public Function GetProductById(strProdId As String) As CProduct
Dim aParam As New SqlParameter("ProdId", strProdId)
FillObject(myDB.GetDataReaderBySP("dbo.sp_GetProductByID", aParam))
Return _Product
End Function
Public Function FillObject(sqlDR As SqlDataReader) As CProduct
Using sqlDR
If sqlDR.Read Then
With _Product
.strProdId = sqlDR.Item("ProdId") & ""
.strProdDesc = sqlDR.Item("ProdDesc") & ""
.sngWhCost = sqlDR.Item("WhCost") & ""
.sngRetPrice = sqlDR.Item("RetPrice") & ""
.blnTaxable = sqlDR.Item("Taxable") & ""
End With
Else
'failed for some reason
End If
End Using
Return _Product
End Function
'----------Start Alex's Code---------
Public Function GetProductByDesc(strProdDesc As String) As SqlDataReader
Dim aParam As New SqlParameter("ProdDesc", strProdDesc)
Return myDB.GetDataReaderBySP("dbo.sp_GetProductByDesc", aParam)
End Function
End Class
main
Private Sub LoadProducts()
arrProdcuts.Clear()
objReader = objProducts.GetProductByDesc(txtSearch.Text)
While objReader.Read
arrFullProdList.Add(objReader.Item("prodDesc"))
End While
objReader.Close()
For i = 0 To arrFullProdList.Count - 1
Dim aNewProd As CProduct
aNewProd = objProducts.GetProductByName(arrFullProdList.Item(i).ToString)
arrProdcuts.Add(aNewProd)
Next
End Sub
Have a class with a string attribute (usign vs 2005 here)
Private _foo As String
Public Property Foo() As String
Get
Return _foo
End Get
Set(ByVal value As String)
??
End Set
End Property
I want to restric the values of Foo into a set list of values.
Unfortunately those values include special characters:
"bar/bar", "smthing/smthing" etc..
so I dont think I can use a simple enumeration
Any ideas?
Does something like this help where it checks an arraylist for allowed values and returns an error if it doesnt. Obviously not a strict as an enum
Public Class footest
Private _foo As String
Private allowed_values As ArrayList
Public Sub New(ByVal text As String)
MyBase.New()
allowed_values.Add("bar/bar")
allowed_values.Add("smthing/smthing")
End Sub
Public Property Foo() As String
Get
Return _foo
End Get
Set(ByVal value As String)
If allowed_values.Contains(value) Then
_foo = value
Else
_foo = "NA#"
End If
End Set
End Property
End Class
Or you could create your enum without the special characters then look them up in a hashtable/sortedlist/dictionary that you create in the New sub
Private hashtable As Hashtable
Public Sub New(ByVal text As String)
MyBase.New()
hashtable.Add("barbar", "bar/bar")
hashtable.Add("smthingsmthing", "smthing/smthing")
End Sub
Found this at CodeProject and it allows me to return an enum with special characters to the console and will require you to create 3 classes. To avoid creating new arraylists etc. at every new foo you need to be a bit more elaborate
String Enumerations in VB.NET # CodeProject
Console
Module Module1
Sub Main()
Dim x As New _foo
x.Foo = FooString.barbar
Console.WriteLine(x.Foo)
End Sub
End Module
The foo class
Public Class _foo
Private _foo As String
Public Property Foo() As FooString
Get
Return _foo
End Get
Set(ByVal value As FooString)
_foo = value
End Set
End Property
End Class
A custom enumeration that outputs special characters
Public NotInheritable Class FooString
Inherits StringEnumeration(Of FooString)
''ADD YOUR ALLOWED VALUES HERE
Public Shared ReadOnly barbar As New FooString("Bar/Bar")
Public Shared ReadOnly smthingsmthing As New FooString("smthing/smthing")
Private Sub New(ByVal StringConstant As String)
MyBase.New(StringConstant)
End Sub
End Class
A String enumeration handling class
Public MustInherit Class StringEnumeration(Of TStringEnumeration _
As StringEnumeration(Of TStringEnumeration))
Implements IStringEnumeration
Private myString As String
Sub New(ByVal StringConstant As String)
myString = StringConstant
End Sub
#Region "Properties"
Public Class [Enum]
Public Shared Function GetValues() As String()
Dim myValues As New List(Of String)
For Each myFieldInfo As System.Reflection.FieldInfo _
In GetSharedFieldsInfo()
Dim myValue As StringEnumeration(Of TStringEnumeration) = _
CType(myFieldInfo.GetValue(Nothing), _
StringEnumeration(Of TStringEnumeration))
'Shared Fields use a Null object
myValues.Add(myValue)
Next
Return myValues.ToArray
End Function
Public Shared Function GetNames() As String()
Dim myNames As New List(Of String)
For Each myFieldInfo As System.Reflection.FieldInfo _
In GetSharedFieldsInfo()
myNames.Add(myFieldInfo.Name)
Next
Return myNames.ToArray
End Function
Public Shared Function GetName(ByVal myName As _
StringEnumeration(Of TStringEnumeration)) As String
Return myName
End Function
Public Shared Function isDefined(ByVal myName As String) As Boolean
If GetName(myName) Is Nothing Then Return False
Return True
End Function
Public Shared Function GetUnderlyingType() As Type
Return GetType(String)
End Function
Friend Shared Function GetSharedFieldsInfo() _
As System.Reflection.FieldInfo()
Return GetType(TStringEnumeration).GetFields
End Function
Friend Shared Function GetSharedFields() As _
StringEnumeration(Of TStringEnumeration)()
Dim myFields As New List(Of _
StringEnumeration(Of TStringEnumeration))
For Each myFieldInfo As System.Reflection.FieldInfo _
In GetSharedFieldsInfo()
Dim myField As StringEnumeration(Of TStringEnumeration) = _
CType(myFieldInfo.GetValue(Nothing), _
StringEnumeration(Of TStringEnumeration))
'Shared Fields use a Null object
myFields.Add(myField)
Next
Return myFields.ToArray
End Function
End Class
#End Region
#Region "Cast Operators"
'Downcast to String
Public Shared Widening Operator CType(ByVal myStringEnumeration _
As StringEnumeration(Of TStringEnumeration)) As String
If myStringEnumeration Is Nothing Then Return Nothing
Return myStringEnumeration.ToString
End Operator
'Upcast to StringEnumeration
Public Shared Widening Operator CType(ByVal myString As String) As _
StringEnumeration(Of TStringEnumeration)
For Each myElement As StringEnumeration(Of TStringEnumeration) In _
StringEnumeration(Of TStringEnumeration).Enum.GetSharedFields
'Found a Matching StringEnumeration - Return it
If myElement.ToString = myString Then Return myElement
Next
'Did not find a Match - return NOTHING
Return Nothing
End Operator
Overrides Function ToString() As String Implements IStringEnumeration.ToString
Return myString
End Function
#End Region
#Region "Concatenation Operators"
Public Shared Operator &(ByVal left As StringEnumeration(Of _
TStringEnumeration), ByVal right As StringEnumeration(Of _
TStringEnumeration)) As String
If left Is Nothing And right Is Nothing Then Return Nothing
If left Is Nothing Then Return right.ToString
If right Is Nothing Then Return left.ToString
Return left.ToString & right.ToString
End Operator
Public Shared Operator &(ByVal left As StringEnumeration(Of _
TStringEnumeration), ByVal right As IStringEnumeration) As String
If left Is Nothing And right Is Nothing Then Return Nothing
If left Is Nothing Then Return right.ToString
If right Is Nothing Then Return left.ToString
Return left.ToString & right.ToString
End Operator
#End Region
#Region "Operator Equals"
Public Shared Operator =(ByVal left As StringEnumeration(Of _
TStringEnumeration), ByVal right As _
StringEnumeration(Of TStringEnumeration)) As Boolean
If left Is Nothing Or right Is Nothing Then Return False
Return left.ToString.Equals(right.ToString)
End Operator
Public Overrides Function Equals(ByVal obj As Object) As Boolean
If TypeOf (obj) Is StringEnumeration(Of TStringEnumeration) Then
Return CType(obj, StringEnumeration(Of _
TStringEnumeration)).ToString = myString
ElseIf TypeOf (obj) Is String Then
Return CType(obj, String) = myString
End If
Return False
End Function
#End Region
#Region "Operator Not Equals"
Public Shared Operator <>(ByVal left As StringEnumeration(Of _
TStringEnumeration), ByVal right As StringEnumeration(Of _
TStringEnumeration)) As Boolean
Return Not left = right
End Operator
#End Region
End Class
'Base Interface without any Generics for StringEnumerations
Public Interface IStringEnumeration
Function ToString() As String
End Interface
I have a label which is databound to a Property in a Class which returns the highest number from another class. The numbers are filled into the other class from 6 text fields.
The 6 properties for the numbers all raise the PropertyChanged event when modified with the Parameter "BestThrow.Distance" as can be seen below:
Public Property Distance() As String
Get
If Status = ThrowStatus.Valid Then
If (m_Distance > 0) Then
Return m_Distance
Else
Return Nothing
End If
ElseIf Status = ThrowStatus.Pass Then
Return "PASS"
ElseIf Status = ThrowStatus.Foul Then
Return "FOUL"
Else
Return Nothing
End If
End Get
Set(value As String)
If (value.Length > 0) Then
If (IsNumeric(value)) Then
m_Distance = value
Status = ThrowStatus.Valid
ElseIf (value = "FOUL") Then
Status = ThrowStatus.Foul
ElseIf (value = "PASS") Then
Status = ThrowStatus.Pass
Else
Status = ThrowStatus.Valid
m_Distance = Nothing
End If
Else
m_Distance = Nothing
Status = ThrowStatus.Valid
End If
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("BestThrow.Distance"))
End Set
End Property
The Property which the label is bound to is as follows:
Public ReadOnly Property BestThrow() As Object
Get
Dim bt = Throws.Where(Function(t) t.Status = ThrowStatus.Valid).OrderByDescending(Function(t) t.Distance).First()
If (IsNothing(bt.Distance)) Then
bt.Distance = "0"
End If
Return bt
End Get
End Property
For the sake of providing all the information the Databinding for the label is as follows
best.DataBindings.Add(New Binding("text", athlete, "BestThrow.Distance", False, DataSourceUpdateMode.OnPropertyChanged))
When I add in the first Distance the label updates fine and displays Distance(0).Distance as expected, however when I change the other 5 values the label will not update. If, however, I then modify the first value again it will recalculate the BestThrow and display the correct distance.
I have also tried manually raising the event using a button on the form which also did not work.
From using watch values I can see that when requested the BestThrow Property is spitting out the correct values, it just seems the label only is interested in an event from the first Throw.
Thank you in advance for any assistance.
Current Code:
Imports System.ComponentModel
Imports System.Runtime.CompilerServices
Public Class Competition
Public Sub New()
Competitors = New List(Of Competitor)()
End Sub
Public Property Competitors() As List(Of Competitor)
Get
Return m_Competitors
End Get
Set(value As List(Of Competitor))
m_Competitors = value
End Set
End Property
Private m_Competitors As List(Of Competitor)
Public ReadOnly Property CurrentPlacings() As List(Of Competitor)
Get
Return Competitors.OrderByDescending(Function(c) c.BestThrow).ToList()
End Get
End Property
End Class
Public Class Competitor
Public Sub New()
Throws = New List(Of [Throw])()
End Sub
Public Property athletenum() As Integer
Get
Return m_athnum
End Get
Set(value As Integer)
m_athnum = value
End Set
End Property
Private m_Athnum As Integer
Public Property FirstName() As String
Get
Return m_FirstName
End Get
Set(value As String)
m_FirstName = value
End Set
End Property
Private m_FirstName As String
Public Property LastName() As String
Get
Return m_LastName
End Get
Set(value As String)
m_LastName = value
End Set
End Property
Private m_LastName As String
Public Property compNumber() As String
Get
Return m_compNumb
End Get
Set(value As String)
m_compNumb = value
End Set
End Property
Private m_compNumb As String
Public Property club() As String
Get
Return m_club
End Get
Set(value As String)
m_club = value
End Set
End Property
Private m_club As String
Public Property Throws() As List(Of [Throw])
Get
Return m_Throws
End Get
Set(value As List(Of [Throw]))
m_Throws = value
End Set
End Property
Private m_Throws As List(Of [Throw])
Public ReadOnly Property BestThrow() As String
Get
Dim list As IList(Of [Throw]) = (From t As [Throw] In Throws Select t Where t.Status = ThrowStatus.Valid Order By t.Distance Descending).ToList()
If (list.Count > 0) Then
If (IsNothing(list(0).Distance)) Then
Return "0"
Else
Return list(0).Distance
End If
End If
Return "0"
End Get
End Property
Public ReadOnly Property getLabel()
Get
Return compNumber & " " & LastName & ", " & FirstName & vbCrLf & club
End Get
End Property
Public Property currentPlace
Get
Return m_curplace
End Get
Set(value)
m_curplace = value
End Set
End Property
Private m_curplace As Integer
End Class
Public Enum ThrowStatus
Valid
Pass
Foul
End Enum
Public Class [Throw]
Implements INotifyPropertyChanged
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
'Throw Status
Public Property Status() As ThrowStatus
Get
Return m_Status
End Get
Set(value As ThrowStatus)
m_Status = value
End Set
End Property
Private m_Status As ThrowStatus
'Throw Distance
Public Property Distance() As String
Get
Dim value As String = Me.m_Distance
If Status = ThrowStatus.Valid Then
If (m_Distance > 0) Then
value = m_Distance
Else
value = Nothing
End If
ElseIf Status = ThrowStatus.Pass Then
value = "PASS"
ElseIf Status = ThrowStatus.Foul Then
value = "FOUL"
Else
value = Nothing
End If
If (value Me.m_Distance) Then
Me.Distance = value
End If
Return value
End Get
Set(value As String)
If (value.Length > 0) Then
If (IsNumeric(value)) Then
m_Distance = value
Status = ThrowStatus.Valid
ElseIf (value = "FOUL") Then
Status = ThrowStatus.Foul
ElseIf (value = "PASS") Then
Status = ThrowStatus.Pass
Else
Status = ThrowStatus.Valid
m_Distance = Nothing
End If
Else
m_Distance = Nothing
Status = ThrowStatus.Valid
End If
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("BestThrow"))
End Set
End Property
Private m_Distance As Decimal
Public Property attempt() As Integer
Get
Return m_attempt
End Get
Set(value As Integer)
m_attempt = value
End Set
End Property
Private m_attempt As Integer
End Class
Current binding:
best.DataBindings.Add(New Binding("text", athlete, "BestThrow", False, DataSourceUpdateMode.OnPropertyChanged))
First things first, I don't like seeing properties calculating the return value. I think this should be done in a method. (It might be okay in a read only property.) Just my opinion. What I find strange is that the getter for Distance depends on Status, and the setter acts more like a setter for Status.
Your binding expects a PropertyDescriptor named Distance. You return a String, and as you know the string class doesn't have a property named Distance.
best.DataBindings.Add(New Binding("text", athlete, "BestThrow.Distance", False, DataSourceUpdateMode.OnPropertyChanged))
Option 1
For this to work you'll need to do it like this:
Public ReadOnly Property BestThrow() As TYPE_OF_YOUR_CLASS
Get
'IMPORTANT:
'This approach requires at least ONE matching object and
'ONE item returned. If not, the binding will fail.
Return (From t As TYPE_OF_YOUR_CLASS In throws Select t Where t.Status = ThrowStatus.Valid Order By t.Distance Ascending).First()
End Get
End Property
Option 2
Another option is to just bind to the BestThrow property:
best.DataBindings.Add(New Binding("text", athlete, "BestThrow", False, DataSourceUpdateMode.OnPropertyChanged))
And change your property to this:
Public ReadOnly Property BestThrow() As String
Get
'NOTE:
'Do not use First() as this will fail if no matching items are found.
'We use ToList() and check the count property.
Dim list As IList(Of TYPE_OF_YOUR_CLASS) = (From t As TYPE_OF_YOUR_CLASS In throws Select t Where t.Status = ThrowStatus.Valid Order By t.Distance Ascending).ToList()
If (list.Count > 0) Then
Return list(0).Distance
End If
Return "0"
End Get
End Property
EDIT
To be honest I think this is bad designed. Please look in detail at this approach:
Public Class Athlete
'TODO: Implements INotifyPropertyChanged
Public Sub New(athleteNumber As Integer, Optional firstName As String = Nothing, Optional ByVal lastName As String = Nothing, Optional ByVal club As String = Nothing)
Me.m_athleteNumber = athleteNumber
Me.m_firstName = If((firstName Is Nothing), String.Empty, firstName)
Me.m_lastName = If((lastName Is Nothing), String.Empty, lastName)
Me.m_club = If((club Is Nothing), String.Empty, club)
End Sub
Public ReadOnly Property AthleteNumber() As Integer
Get
Return Me.m_athleteNumber
End Get
End Property
Public Property Club() As String
Get
Return Me.m_club
End Get
Set(value As String)
Me.m_club = value
'TODO: If changed raise property changed.
End Set
End Property
Public Property FirstName() As String
Get
Return Me.m_firstName
End Get
Set(value As String)
Me.m_firstName = value
'TODO: If changed raise property changed.
End Set
End Property
Public Property LastName() As String
Get
Return Me.m_lastName
End Get
Set(value As String)
Me.m_lastName = value
'TODO: If changed raise property changed.
End Set
End Property
Public Overrides Function ToString() As String
Return String.Concat(Me.m_firstName, " ", Me.m_lastName).Trim()
End Function
Private m_athleteNumber As Integer
Private m_club As String
Private m_firstName As String
Private m_lastName As String
End Class
Public Class Competitor
Implements INotifyPropertyChanged
Public Sub New(athlete As Athlete, Optional competitorNumber As String = Nothing)
If (athlete Is Nothing) Then
Throw New ArgumentNullException("athlete")
End If
Me.m_athlete = athlete
Me.m_bestThrow = 0D
Me.m_competitorNumber = If((competitorNumber Is Nothing), String.Empty, competitorNumber)
Me.m_curplace = 0
Me.m_throws = New ObjectCollection(Of [Throw])
AddHandler Me.m_throws.CollectionChanged, New CollectionChangeEventHandler(AddressOf Me.OnThrowCollectionChanged)
End Sub
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
Public ReadOnly Property Athlete() As Athlete
Get
Return Me.m_athlete
End Get
End Property
Public ReadOnly Property BestThrow() As Decimal
Get
Return Me.m_bestThrow
End Get
End Property
Public Property CompetitorNumber() As String
Get
Return Me.m_competitorNumber
End Get
Set(value As String)
If (value <> Me.m_competitorNumber) Then
Me.m_competitorNumber = value
Me.RaisePropertyChanged("CompetitorNumber")
End If
End Set
End Property
Public Property CurrentPlace() As Integer
Get
Return Me.m_curplace
End Get
Set(value As Integer)
If (value <> Me.m_curplace) Then
Me.m_curplace = value
Me.RaisePropertyChanged("CurrentPlace")
End If
End Set
End Property
Public ReadOnly Property Throws() As ObjectCollection(Of [Throw])
Get
Return Me.m_throws
End Get
End Property
Protected Sub OnThrowCollectionChanged(sender As Object, e As CollectionChangeEventArgs)
Dim list As IList(Of [Throw]) = (From t As [Throw] In Me.m_throws Select t Where t.Status = ThrowStatus.Valid Order By t.Distance Descending).ToList()
Dim bestThrow As Decimal = If((list.Count > 0), list(0).Distance, 0D)
If (Me.m_bestThrow <> bestThrow) Then
Me.m_bestThrow = bestThrow
Me.RaisePropertyChanged("BestThrow")
End If
End Sub
Private Sub RaisePropertyChanged(propertyName As String)
If (Not Me.PropertyChangedEvent Is Nothing) Then
Me.PropertyChangedEvent.Invoke(Me, New PropertyChangedEventArgs(propertyName))
End If
End Sub
Private m_athlete As Athlete
Private m_bestThrow As Decimal
Private m_competitorNumber As String
Private m_curplace As Integer
Private m_throws As ObjectCollection(Of [Throw])
End Class
Public Class [Throw]
Public Sub New(Optional ByVal status As ThrowStatus = ThrowStatus.Valid, Optional distance As Decimal = 0D)
Me.m_status = status
Me.m_distance = Math.Max(distance, 0D)
End Sub
Public ReadOnly Property Status() As ThrowStatus
Get
Return Me.m_status
End Get
End Property
Public ReadOnly Property Distance() As Decimal
Get
Return Me.m_distance
End Get
End Property
Public Overrides Function ToString() As String
Select Case Me.m_status
Case ThrowStatus.Valid
Return Me.m_distance.ToString("N2")
Case ThrowStatus.Pass
Return "PASS"
Case ThrowStatus.Foul
Return "FOUL"
Case Else
Return 0D.ToString("N2")
End Select
End Function
Private m_attempt As Integer
Private m_distance As Decimal
Private m_status As ThrowStatus
End Class
Public Class ObjectCollection(Of T)
Inherits Collections.ObjectModel.Collection(Of T)
Public Event CollectionChanged As CollectionChangeEventHandler
Protected Overrides Sub ClearItems()
MyBase.ClearItems()
Me.RaiseCollectionChanged(CollectionChangeAction.Refresh, Nothing)
End Sub
Protected Overrides Sub InsertItem(index As Integer, item As T)
If (item Is Nothing) Then
Throw New ArgumentNullException("item")
ElseIf (Me.Contains(item)) Then
Throw New ArgumentException("Item duplicate.", "item")
End If
MyBase.InsertItem(index, item)
Me.RaiseCollectionChanged(CollectionChangeAction.Add, item)
End Sub
Protected Overridable Sub OnCollectionChanged(e As CollectionChangeEventArgs)
If (Not Me.CollectionChangedEvent Is Nothing) Then
Me.CollectionChangedEvent.Invoke(Me, e)
End If
End Sub
Private Sub RaiseCollectionChanged(action As CollectionChangeAction, item As T)
Me.OnCollectionChanged(New CollectionChangeEventArgs(action, item))
End Sub
Protected Overrides Sub RemoveItem(index As Integer)
Dim item As T = Me.Item(index)
MyBase.RemoveItem(index)
Me.RaiseCollectionChanged(CollectionChangeAction.Remove, item)
End Sub
Protected Overrides Sub SetItem(index As Integer, item As T)
Throw New NotSupportedException()
End Sub
End Class
Public Enum ThrowStatus As Integer
Valid = 0 '<- This is the default value.
Pass = 1
Foul = 2
End Enum
The following code are tested and works. Drop a Button and a TextBox onto a Form and append:
Public Class Form1
Public Sub New()
Me.InitializeComponent()
Me.competitor = New Competitor(New Athlete(1, "John", "Smith", "Team JS"), "CP_1")
Me.competitor.Throws.Add(New [Throw](distance:=123.3472D))
Me.competitor.Throws.Add(New [Throw](distance:=424.1234D))
Me.competitor.Throws.Add(New [Throw](distance:=242.1234D))
Dim b As New Binding("Text", Me.competitor, "BestThrow", True, DataSourceUpdateMode.Never)
AddHandler b.Format, New ConvertEventHandler(AddressOf Me._FormatBinding)
Me.TextBox1.DataBindings.Add(b)
End Sub
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Me.competitor.Throws.Add(New [Throw](distance:=845.4365D))
End Sub
Private Sub _FormatBinding(sender As Object, e As ConvertEventArgs)
If ((TypeOf e.Value Is Decimal) AndAlso (e.DesiredType Is GetType(String))) Then
e.Value = CDec(e.Value).ToString("N2")
End If
End Sub
Private competitor As Competitor
End Class
I have a sub which on SelectedIndexChange - of Customer returns the TransactionBindingSource.
What I want is to show on the databound controls the latest transaction of each selected customer instead of the first one. The weird thing is that when the tab loads (on the 'enter' event I call the selectedIndexChange method and the latest record is selected. However, when I manually select another customer, the first record of each transaction is displayed! This is what I have
Private Sub cboCustomerName_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cboCustomerName.SelectedIndexChanged
resetstats()
'Try
Dim iTotalbuyin, iCountBuyins, iSumBuyins, iSumCashouts, iBiggestWin, iBiggestLoss As Integer
Dim oTotalbuyin, oCountBuyIns, oSumCashouts, oBiggestWin, oBiggestLoss As Object
' If Me.cboCustomerName.SelectedIndex <> -1 Then
Dim drv As DataRowView = CType(Me.cboCustomerName.SelectedItem, DataRowView)
Dim SelCustId As Integer = drv.Item("CustomerID")
Me.TransactionTableAdapter.Fill(Me.DbPBDataSet.Transaction, SelCustId)
Me.TransactionBindingSource.Sort = "TransactionID"
Me.TransactionBindingSource.MoveLast()
Any ideas?
You can make your own SortableBindingList class, like so:
Imports System.ComponentModel
Imports System.Reflection
Public Class SortableBindingList(Of T)
Inherits BindingList(Of T)
Private Property IsSorted As Boolean
Private Property SortDirection As ListSortDirection
Private Property SortProperty As PropertyDescriptor
Protected Overrides ReadOnly Property SupportsSortingCore() As Boolean
Get
Return True
End Get
End Property
Protected Overrides ReadOnly Property SortDirectionCore() As ListSortDirection
Get
Return _SortDirection
End Get
End Property
Protected Overloads Overrides ReadOnly Property SortPropertyCore() As PropertyDescriptor
Get
Return _SortProperty
End Get
End Property
Protected Overloads Overrides Sub ApplySortCore(ByVal PDsc As PropertyDescriptor, ByVal Direction As ListSortDirection)
Dim items As List(Of T) = TryCast(Me.Items, List(Of T))
If items Is Nothing Then
IsSorted = False
Else
Dim PCom As New PCompare(Of T)(PDsc.Name, Direction)
items.Sort(PCom)
IsSorted = True
SortDirection = Direction
SortProperty = PDsc
End If
OnListChanged(New ListChangedEventArgs(ListChangedType.Reset, -1))
End Sub
Protected Overloads Overrides ReadOnly Property IsSortedCore() As Boolean
Get
Return _IsSorted
End Get
End Property
Protected Overrides Sub RemoveSortCore()
_IsSorted = False
End Sub
#Region " Constructors "
Sub New(ByVal list As ICollection(Of T))
MyBase.New(CType(list, Global.System.Collections.Generic.IList(Of T)))
End Sub
Sub New()
MyBase.New()
End Sub
#End Region
#Region " Property comparer "
Private Class PCompare(Of T)
Implements IComparer(Of T)
Private Property PropInfo As PropertyInfo
Private Property SortDir As ListSortDirection
Friend Sub New(ByVal SortProperty As String, ByVal SortDirection As ListSortDirection)
SortProperty = CheckPropertyName(SortProperty)
PropInfo = GetType(T).GetProperty(SortProperty)
SortDir = SortDirection
End Sub
''' <summary>
''' Used to change the name of the sorted property for certain classes.
''' </summary>
''' <param name="SortProperty"></param>
''' <returns></returns>
''' <remarks></remarks>
Private Function CheckPropertyName(ByVal SortProperty As String) As String
If SortProperty = "BinNumber" AndAlso GetType(T).Name = "BinReportDisplay" Then
Return "BinNumberSort"
End If
Return SortProperty
End Function
Friend Function Compare(ByVal x As T, ByVal y As T) As Integer Implements IComparer(Of T).Compare
Return If(SortDir = ListSortDirection.Ascending, Comparer.[Default].Compare(PropInfo.GetValue(x, Nothing),
PropInfo.GetValue(y, Nothing)), Comparer.[Default].Compare(PropInfo.GetValue(y, Nothing),
PropInfo.GetValue(x, Nothing)))
End Function
End Class
#End Region
End Class
Then sort the list according to how you want it sorted.