acdn
acdn

Reputation: 73

Why isn't my ItemsControl showing my ViewModels?

I am trying to populate a page with a list of items from my database. I have created models and viewmodels for these items, but they are not showing up in my ItemsControl.

I have a Model, which has a corresponding ViewModel that implements INotifyPropertyChanged.

Model:

Public Class ItemModel

    Private _year As String

    Public Property Year As String
        Get
            Return _year
        End Get
        Set(value As String)
            _year = value
        End Set
    End Property

    Public Sub New()
        _year = Now.Year & "-" & (Now.Year + 1)
    End Sub

    Public Function ToString() As String
        Return _year & " Item Model"
    End Function
End Class

ViewModel:

Imports System.ComponentModel

Public Class ItemViewModel
    Implements INotifyPropertyChanged

    Private _currentItem As ItemModel

    Public Property CurrentItem As ItemModel
        Get
            Return _currentItem
        End Get
        Set(value As ItemModel)
            If _currentItem IsNot value Then
                _currentItem = value
                NotifyPropertyChanged("CurrentItem")
            End If
        End Set
    End Property

    Public Sub New()
        _currentItem = New DciSurveyModel()
    End Sub

    Public Function ToString() As String
        Return _currentItem.Year & " Item ViewModel"
    End Function

    Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged

    Private Sub NotifyPropertyChanged(Optional ByVal propertyName As String = Nothing)
        RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
    End Sub
End Class

I bind the ItemsControl to an ObservableCollection of ViewModels, but the ViewModels do not appear. I have tried using an ItemsTemplate to create a textbox setting the Text={Binding Path=CurrentItem.Year} to no avail.

XAML:

<Page x:Class="ItemPage"
      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" 
      d:DesignHeight="300" d:DesignWidth="300"
      Name="ItemPage"
      Title="ItemPage" Loaded="Page_Loaded_1" Margin="10">

    <Grid>
        <ItemsControl ItemsSource="{Binding Path=ItemCollection}" />
    </Grid>
</Page>

Here is the code-behind:

Imports OClient = Oracle.DataAccess.Client
Imports System.Collections.ObjectModel
Imports System.Data

Class ItemPage

    Private ds As DataSet
    Private itemsTable As DataTable
    Public Property ItemsCollection As ObservableCollection(Of ItemViewModel)

    Private Sub Page_Loaded_1(sender As Object, e As RoutedEventArgs)


        Dim itemsQry = "select item_year from items order by item_year desc"
        Dim queryCmd As New OClient.OracleCommand(itemsQry, O.con)
        Dim adapter As New OClient.OracleDataAdapter(queryCmd)
        ds = New DataSet
        adapter.Fill(ds, "items")
        itemsTable = ds.Tables("items")

        ItemsCollection = New ObservableCollection(Of ItemViewModel)

        For Each r As DataRow In surveys.Rows
            Dim newItem As New ItemViewModel
            newItem.CurrentItem.Year = r.Item("ITEM_YEAR").ToString
        Next

        Me.DataContext = Me
    End Sub
End Class

I am having a very hard time figuring out where my app is falling apart. Is it in my implementation of the ViewModels? Am I not binding the data correctly? Do I need to do something different with my ObservableCollection?

Thanks for helping a newbie.

Upvotes: 1

Views: 47

Answers (1)

Clemens
Clemens

Reputation: 128060

You iterate over the elements of surveys.Rows and create a new ItemViewModel for each one, but you never add them to ItemsCollection, by ItemsCollection.Add(newItem):

For Each r As DataRow In surveys.Rows
    Dim newItem As New ItemViewModel
    newItem.CurrentItem.Year = r.Item("ITEM_YEAR").ToString

    ItemsCollection.Add(newItem) 
Next

You're also using a wrong Path for the ItemsSource Binding. It must be ItemsCollection instead of ItemCollection.

Besides that, instead of overriding ToString() you should declare a DataTemplate:

<ItemsControl ItemsSource="{Binding ItemsCollection}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <TextBlock
                Text="{Binding CurrentItem.Year, StringFormat={}{0} Item ViewModel}"/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

Upvotes: 2

Related Questions