0
votes

Is it possible to fill a listBox with items which have predefined index? Such as if I have collection of items with index values:

  • item1, index 1
  • item2, index 2
  • item3, index 4

ListBox:

  • item1
  • item2
  • empty space
  • item3

the list can contain any number of combination of empty or filled positions.

Which methods would be the most direct way of achieving the desired result with MVVM structure in a WPF environment?

1
Create model class with two property item and index but add item sequentially in ListBox - Darshan Faldu
Bind the ListBox's ItemsSource to a collection with null items for the empty spaces. - Clemens

1 Answers

1
votes

Doing this MVVMfully, your list box items will be an ObservableCollection of instances of some class of your own, which represents whatever you're putting in the listbox (users, used cars, whatever). That collection is a property on your viewmodel.

At the ListBox end of things, you'll have to represent empty slots with spacer items -- null should do fine. You'd then do something in the view with the ListBox's ItemTemplate and ItemContainerStyle to display the "empty" items correctly and prevent them from being selected by the user. You might have to handle the SelectionChanged event to make that happen; if you want to reuse this stuff in a generalized way, you could handle SelectionChanged via an attached property that your style would apply.

Option 1, not quite the purest MVVM but a whole lot less work than Doing It Right, is very simple: When you populate your ObservableCollection, sort the items and insert nulls for spacer items. Done.

<ListBox 
    ItemsSource="{Binding WeirdGappyCollectionWithNulls}" 
    ItemTemplate="{StaticResource GappyItemTemplate}"
    ItemContainerStyle="{StaticResource GappyItemContainerStyle}"
    />

...where GappyItemTemplate and GappyItemContainerStyle are defined in a ResourceDictionary above.

Option 2, if you want to go Full MVVMtard and build for the ages:

For sorting, I'd ordinarily use a sorted CollectionViewSource. Then you're binding that to ItemsSource

<ListBox 
    ItemTemplate="{StaticResource GappyItemTemplate}"
    ItemContainerStyle="{StaticResource GappyItemContainerStyle}"
    >
    <ListBox.ItemsSource>
        <local:GappyCollectionViewSource
            Source="{Binding GappyCollection}"
            ...etc. etc.
            />
    </ListBox.ItemsSource>
</ListBox>

I wouldn't want the viewmodel to have any clue about ListBoxes, or even about empty items.

I would give the viewmodel a gappy collection of "non empty" items, and write a CollectionViewSource subclass that will sort by whatever property you like, and additionally project that collection to another, readonly collection which includes null "spacer" items, which it exposes in its View property.

Sort of an anti-filter. It could use the SortDescriptions to define what the gaps are, at least if you're sorting by integers. Or you could do that part semi-quick and dirty by giving it a keyselector lambda or an event analogous to the existing Filter event.

CollectionViewSource.View isn't a virtual property, but it is a DependencyProperty. There should be some way to slip in a ringer there. If that gives you any trouble, start over with CollectionView instead.