patrick
patrick

Reputation: 16999

Why don't my listboxitems collapse?

If I click an item in the middle of the list, I expect all but 1 element to be collapsed. The actual output is that many items are left. Why? This is the entire program.

using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;

namespace WpfApplication2
{
    public partial class MainWindow : Window
    {
        public class obj { }

        public MainWindow()
        {
            InitializeComponent();
            List<obj> objList = new List<obj>();
            for (int i = 0; i < 30; i++) objList.Add(new obj());
            lb.ItemsSource = objList;
        }

        private void lb_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            ListBox lb = sender as ListBox;
            for (int i = 0; i < lb.Items.Count; i++)
            {
                ListBoxItem tmp = (ListBoxItem)(lb.ItemContainerGenerator.ContainerFromItem(lb.Items[i]));
                if (tmp != null)
                {
                    if (tmp.IsSelected)
                        tmp.Visibility = System.Windows.Visibility.Visible;
                    else
                        tmp.Visibility = System.Windows.Visibility.Collapsed;
                }
            }
        }
    }
}


<Window x:Class="WpfApplication2.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525"
        >
    <Grid>
        <ListBox Name="lb" SelectionChanged="lb_SelectionChanged" IsSynchronizedWithCurrentItem="True" >
            <ListBox.ItemTemplate >
                <DataTemplate>
                    <StackPanel Orientation="Vertical">
                        <TextBlock Name="tb1" Text="whatever"/>
                    </StackPanel>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>
</Window>

Upvotes: 6

Views: 1516

Answers (2)

CodeNaked
CodeNaked

Reputation: 41403

You probably need to disable virtualization. The ListBoxItems will not be created by default, until needed. When you collapse the visible ListBoxItems, you make room for more, which will be created after your code is run.

Add this to your ListBox:

VirtualizingStackPanel.IsVirtualizing="False"

Or you could probably use a Style to collapse the items like so:

<ListBox.ItemContainerStyle>
     <Style TargetType="ListBoxItem">
         <Style.Triggers>
             <Trigger Property="IsSelected" Value="False">
                 <Setter Property="Visibility" Value="Collapsed" />
             </Trigger >
         </Style.Triggers>
     </Style>
</ListBox.ItemContainerStyle>

Upvotes: 4

Tim
Tim

Reputation: 15247

I believe its because of your use of ItemContainerGenerator.ContainerFromItem.

The ListBox is using a VirtualizingStackPanel by default. So the items that aren't on the screen when you load the window are not created yet. Setting them to Collapsed has no effect once they're brought back on the screen.

You can play around with this a little bit by changing the initial height of the Window. If you set it to 550 or so, it works as expected. If you set it to 150 or so, you'll have A LOT of elements still visible.

One thing you can do to change this if you're not going to have that many elements is just change the ItemsPanel.

Upvotes: 7

Related Questions