ListBox の ItemTemplate に Expander があります。うまくレンダリングします。私が遭遇した問題は、エキスパンダーが展開または選択されたときに ListBox_SelectionChanged イベントを発生させたいということです。MouseDown イベントは、ListBox までバブルアップしていないようです。
必要なのは、ListBox の SelectedIndex です。ListBox_SelectionChanged が起動されないため、インデックスは -1 になり、どの項目が選択されているかを判断できません。
ListBox_SelectionChanged イベントは、展開された後にユーザーが Expander のコンテンツをクリックすると発生します。エキスパンダーのみをクリックした場合、イベントは発生しません。これは、Expander ヘッダーを実際にクリックしたときに、そのアイテムを既にクリックしたと視覚的に考えるため、ユーザーを混乱させます。ユーザーが Expander を展開するときに ListBox Item を選択する必要があります。これは、ユーザーに関する限り、アイテムが実際には選択されていないときに選択されているためです。
これを機能させる方法、またはエキスパンダーを含むリストボックスの SelectedIndex を決定する別の方法についての提案はありますか?
参照用の簡略化されたコード:
<Window x:Class="WpfApplication3.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300"
Loaded="Window_Loaded">
<Grid Name="Root">
<ScrollViewer>
<ListBox SelectionChanged="ListBox_SelectionChanged" ItemsSource="{Binding}">
<ItemsControl.ItemTemplate >
<DataTemplate>
<Border>
<Expander>
<Expander.Header>
<TextBlock Text="{Binding Path=Name}"/>
</Expander.Header>
<Expander.Content>
<StackPanel>
<TextBlock Text="{Binding Path=Age}"/>
<TextBlock Text="Line 2"/>
<TextBlock Text="Line 3"/>
</StackPanel>
</Expander.Content>
</Expander>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ListBox>
</ScrollViewer>
</Grid>
</Window>
Binding の単純なクラス:
public class Person
{
public string Name {
get;
set;
}
public int Age {
get;
set;
}
}
バインド用のデータの作成と入力:
private void Window_Loaded(object sender, RoutedEventArgs e) {
data = new ObservableCollection<Person>();
data.Add(new Person {
Name = "One",
Age=10
});
data.Add(new Person {
Name = "Two",
Age = 20
});
data.Add(new Person {
Name = "Three",
Age = 30
});
Root.DataContext = data;
}
これは私が必要とするイベントです (実際には必要な SelectedIndex だけです)
private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e) {
ListBox box = (ListBox)sender;
// This value is not set because events from Expander are not bubbled up to fire SelectionChanged Event
int index = box.SelectedIndex;
}