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>
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
.
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With