views:

2732

answers:

2

I was trying to bind a collection of my W3CError type objects to a WPF ListView control.

It was a nice little 13 line class...

Class W3CError

    Public Type As ErrorOrWarning
    Public Line As Integer
    Public Col As Integer
    Public Message As String
    Public MessageId As String
    Public Explanation As String
    Public Source As String

    Enum ErrorOrWarning
        ValidationError
        ValidationWarning
    End Enum

End Class

It didn't work. I got these binding errors in Visual Studio's Output window:

System.Windows.Data Error: 39 : BindingExpression path error: 'Line' property not found on 'object' ''W3CError' (HashCode=...)'. BindingExpression:Path=Line; DataItem='W3CError' (HashCode=...); target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String')

Well, no, that's not a Property. It's simply Public. I guess that's not good enough for WPF binding?

I got it to work by lengthening my class to an ugly 69 lines of Properties boilerplate...

Class W3CError

    Private _Type As ErrorOrWarning
    Private _Line As Integer
    Private _Col As Integer
    Private _Message As String
    Private _MessageId As String
    Private _Explanation As String
    Private _Source As String

    Enum ErrorOrWarning
        ValidationError
        ValidationWarning
    End Enum

    Public Property Type() As ErrorOrWarning
        Get
            Return _Type
        End Get
        Set(ByVal value As ErrorOrWarning)
            _Type = value
        End Set
    End Property

    Public Property Line() As Integer
        Get
            Return _Line
        End Get
        Set(ByVal value As Integer)
            _Line = value
        End Set
    End Property

    Public Property Col() As Integer
        Get
            Return _Col
        End Get
        Set(ByVal value As Integer)
            _Col = value
        End Set
    End Property

    Public Property Message() As String
        Get
            Return _Message
        End Get
        Set(ByVal value As String)
            _Message = value
        End Set
    End Property

    Public Property MessageId() As String
        Get
            Return _MessageId
        End Get
        Set(ByVal value As String)
            _MessageId = value
        End Set
    End Property

    Public Property Explanation() As String
        Get
            Return _Explanation
        End Get
        Set(ByVal value As String)
            _Explanation = value
        End Set
    End Property

    Public Property Source() As String
        Get
            Return _Source
        End Get
        Set(ByVal value As String)
            _Source = value
        End Set
    End Property

End Class

Is there a better way?

+4  A: 

If you were using C# I'd say use Automatic Properties, but I don't think they're in VB.

So probably not. You may even want to go further and make your class implement INotifyPropertyChanged so that your UI knows if the properties change.

Ray
Humbug! I'd rather VB had automatic properties than inline XML.
Zack Peterson
I believe that the next version of VB (the one that ships with .NET 4.0 / Visual Studio 2010) will have automatic properties. Doesn't help now, but at least eventually it'll help.
Andy
+1  A: 

I wouldn't call it a better way, but you could implement ICustomTypeDescriptor and expose your fields as fake properties through the GetProperties method. It would only end up being less code if you had a few dozen fields, though.


Originally posted by Robert Macnee, but later removed. Restored here because it interests me...

Shog9