0

I am trying to bind a List(Of Customer) data object to a Listview. This listview uses a custom control to display the values. The problem is that no data is being displayed by the custom control and my output shows this error:

System.Windows.Data Error: 5 : Value produced by BindingExpression is not valid for target property.; Value='WPF_Controls.OrderItem' BindingExpression:Path=; DataItem='OrderItem' (Name=''); target element is 'OrderItem' (Name=''); target property is 'Customer' (type 'Customer')

I looked up this error and it seems to be a conversion error. The application expects a different datatype. What I don't understand is why it expects a different datatype. Let me show you the code.

The customer class:

Public Class Customer
    Property Name As String
    Property Address As String
End Class

The XAML for the listview:

<UserControl x:Name="userControl" x:Class="OrderListview"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:WPF_Controls"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <ListView Margin="5" ItemsSource="{Binding Customers}">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <local:OrderItem Customer="{Binding}" />
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid>
</UserControl>

Codebehind for the listview:

Imports System.ComponentModel

Public Class OrderListview
    Implements INotifyPropertyChanged
    
    Private _Customers As New List(Of Customer)
    
    Public Sub New()
        InitializeComponent()
        Me.DataContext = Me
    End Sub

    Public Property Customers As List(Of Customer)
        Get
            Return _Customers
        End Get
        Set(value As List(Of Customer))
            _Customers = value
            DoPropertyChanged("Customers")
        End Set
    End Property

    Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged

    Public Sub DoPropertyChanged(propertyName As String)
        Dim e As New PropertyChangedEventArgs(propertyName)
        RaiseEvent PropertyChanged(Me, e)
    End Sub
End Class

The XAML for the user control:

<UserControl x:Class="OrderItem"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" Height="112.5" Width="632.717">
    <Grid>
        <Label Content="{Binding Customer.Name}" />
    </Grid>
</UserControl>

Codebehind for the user control:

Public Class OrderItem

    Public Sub New()
        InitializeComponent()
        Me.DataContext = Me
    End Sub

    Public Shared ReadOnly CustomerProperty As DependencyProperty =
        DependencyProperty.Register("Customer",
        GetType(Customer),
        GetType(OrderItem),
        New FrameworkPropertyMetadata(Nothing))

    Public Property Customer As Customer
        Get
            Return DirectCast(GetValue(CustomerProperty), Customer)
        End Get
        Set(value As Customer)
            SetValue(CustomerProperty, value)
        End Set
    End Property

End Class

As you can see in the listview XAML is that the ItemSource is bound to the Customers property. That works because when I replace the user control with a simple label it shows my data. I created a user control with a Customer DependencyProperty so that I could pass the customers into the user control. The label inside the user control binds to Customer.Name and the DataContext is set to the control itself so the Customer property should be visible. No errors are given so the paths seem to be correct.

So why the error? The List(Of Customer) itemsource produces the correct datatype for Customer in my opinion.

Martin
  • 1,184
  • 8
  • 24
  • Remove `Me.DataContext = Me` from the UserControl's constructor, and bind in its XAML like `` – Clemens Oct 01 '21 at 08:17
  • @Clemens Thank you! Post that as an answer for the points. (I see my question has been closed, thanks anyway) – Martin Oct 01 '21 at 09:05

0 Answers0