0

I am trying to make an "infinite scrollable calendar". My idea is to generate the requested portion of the calendar on the fly, so as ItemsSource i use a custom class WeekList that implements IList. Upon initialization i calculate an interval around the current date (5 years radius at the moment, later i want to go as far as IntMax allows). From there on out i just calculate the requested weeks by the index.

I have implemented the Item Method to only create data on demand and GetEnumerator as follows:

Public Iterator Function GetEnumerator1() As IEnumerator Implements IEnumerable.GetEnumerator
    For i As Integer = 1 To _Count
        Yield Item(i)
    Next
End Function

While trying to understand what Yield does i was under the impression that this will only calculate Items as needed.

Functionally the calendar works perfect, but upon binding a WeekList "Dates" to a ListBox.ItemsSource, all weeks are generated at once.

EDIT: I have isolated the problem in a complete code example:

My MainWindow Code-Behind:

Class MainWindow
Public Sub New()

    ' This call is required by the designer.
    InitializeComponent()

    ' Add any initialization after the InitializeComponent() call.
    Me.DataContext = Me
End Sub


Private _TestList As VirtList
Public ReadOnly Property TestList As VirtList
    Get
        If _TestList Is Nothing Then
            _TestList = New VirtList(10000)
        End If
        Return _TestList
    End Get
End Property
End Class

And the class to procedurally generate a list of given size:

Public Class VirtList
Implements IEnumerable

Private _Count As Integer
Public Sub New(size As Integer)
    _Count = size
End Sub

Private _Items As New Dictionary(Of Integer, String)

Private Function Item(i As Integer) As String
    If Not _Items.ContainsKey(i) Then
        _Items(i) = "I am Item Number " & i
        Debug.Print("Current Cache Size: {0}", _Items.Count)
    End If
    Return _Items(i)
End Function

Public Iterator Function GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
    For i As Integer = 0 To _Count
        Yield Item(i)
    Next
End Function
End Class

In my MainWindow.xaml

        <ListBox 
        VirtualizingPanel.IsVirtualizing="True"
        ItemsSource="{Binding TestList}"/>

The whole list (all 10.000 items) is generated at the time of binding. How can I achieve that only the "visible portion" is enumerated? I was under the impression that that is exactly what the ListBox does with Virtualization so I suspect my incomprehension of the GetEnumerator/Yield as the culprit.

themightylc
  • 304
  • 2
  • 15

1 Answers1

0

Implementing the IList Interface instead of only IEnumerator solved the virutalization Problem in my example. I will work from there backwards to my full solution to see what's wrong.

Additional Information: My real problem was that i had a Style with a DataTrigger that implicitly manipulated the height of the ItemContainer. Having a variation in the size of the ItemContainer effectively disables virtualization.

themightylc
  • 304
  • 2
  • 15