First had the problem with collapse of Expander not giving back space.
Based on the borders it appears to be the ListView is not shrinking rather than the Expander not shrinking.
The following code fixed the shrinking problem.
From ListBox control does not shrink
This loses virtualization but I am OK with that as this is as much data as I need to display.
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
But then a new problem.
If you open up any two levels of Expander and try to click on the check box it will often jump around and some times jump so much that the click misses the check box.
Scroll all the way to the bottom so the check box is not at the bottom (there are some Expanders below it).
Then click and it will jump and most likely even miss the item.
I can take several attempts to check or uncheck the last row.
Pretty sure this is because of the click being processed twice and things moving between.
So how to fix both problems?
1. Collapse shrink / give back space?
2. Check box not jumping?
Tried refresh via dispatcher, UpdateLayout(), InvalidateVisual(), and Height = Double.NaN.
The StackPanel is not the problem as I can remove it and use just Exp1 and still have the problem.
Had a similar problem before on double click with SelectedItem that I was able to fix with eating the second click but that fix does not work here. MissClick
Tried TreeView but I am not displaying the same information at each level so it does not work.
But I am open to another approach.
Two level hierarchy and just need check boxes on the second level.
Sorry for a lot of code but this is a complete program to reproduce the problem.
Exp1 is identical to Exp2 and not really necessary to reproduce the problem but that reflects the real program in case someone suggests an alternate solution.
<Window x:Class="ListViewJump.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>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="165"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ScrollViewer Grid.Row="0" Grid.Column="0"
HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Visible">
<StackPanel>
<Expander IsExpanded="False" Header="Exp1" BorderThickness="2" BorderBrush="Green">
<ListView ItemsSource="{Binding Path=List1}"
HorizontalAlignment="Left" BorderThickness="2" BorderBrush="Orange">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate >
<DataTemplate>
<Expander Header="{Binding Path=DispName}">
<ListView ItemsSource="{Binding Path=Rows}"
HorizontalAlignment="Left" BorderThickness="2" BorderBrush="Purple">
<ListView.ItemTemplate >
<DataTemplate>
<CheckBox Width="125" IsChecked="{Binding Path=On}">
<TextBlock Text="{Binding Path=StrValue}" TextWrapping="Wrap"/>
</CheckBox>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Expander>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Expander>
<Expander IsExpanded="False" Header="Exp2" BorderThickness="2" BorderBrush="Green">
<ListView ItemsSource="{Binding Path=List2}"
HorizontalAlignment="Left" BorderThickness="2" BorderBrush="Orange">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate >
<DataTemplate>
<Expander Header="{Binding Path=DispName}">
<ListView ItemsSource="{Binding Path=Rows}"
HorizontalAlignment="Left" BorderThickness="2" BorderBrush="Purple">
<ListView.ItemTemplate >
<DataTemplate>
<CheckBox Width="125" IsChecked="{Binding Path=On}">
<TextBlock Text="{Binding Path=StrValue}" TextWrapping="Wrap"/>
</CheckBox>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Expander>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Expander>
</StackPanel>
</ScrollViewer>
</Grid>
</Window>
namespace ListViewJump
{
public partial class MainWindow : Window
{
private List<ListItem> list1 = new List<ListItem>();
private List<ListItem> list2 = new List<ListItem>();
public MainWindow()
{
this.DataContext = this;
for (int i = 1; i < 10; i++)
{
List<ListItemRow> lr1 = new List<ListItemRow>();
List<ListItemRow> lr2 = new List<ListItemRow>();
for (int j = 1; j < 100; j++)
{
lr1.Add(new ListItemRow("Row Row Row Row Row Row" + j.ToString()));
lr2.Add(new ListItemRow("Rwo Rwo Rwo Rwo Rwo Rwo" + j.ToString()));
}
list1.Add(new ListItem("one " + i.ToString(), lr1));
list2.Add(new ListItem("two " + i.ToString(), lr2));
}
InitializeComponent();
}
public List<ListItem> List1 { get { return list1; } }
public List<ListItem> List2 { get { return list2; } }
}
public class ListItem
{
private string dispName;
private List<ListItemRow> rows;
public string DispName { get { return dispName; } }
public List<ListItemRow> Rows { get { return rows; } }
public ListItem(String DispName, List<ListItemRow> Rows) { dispName = DispName; rows = Rows; }
}
public class ListItemRow
{
private string strValue;
private bool on = false;
public string StrValue { get { return strValue; } }
public bool On
{
get { return on; }
set { on = value; }
}
public ListItemRow(String StrValue) { strValue = StrValue; }
}
}
I think there are two bugs here.
Control not shrinking and a click getting processed twice.
I get shrink would add overhead but still why not an option.