我在xaml中有一个ListBox,它在顶级ListBox的项目模板中有一个子ListBox。因为子ListBox是多选的,并且由于某种原因我无法将子ListBox的SelectedItems绑定到viewmodel属性,所以我试图在视图代码中做很多事情 - 后面。
我有一切正常,除了一个障碍:我想默认选择每个子ListBox中的所有项目。由于SelectedItems没有数据绑定,每当SelectionChanged事件在顶级ListBox上触发时,我都会尝试在代码中手动执行此操作。问题是我不知道如何从顶级ListBox到顶级选定项的子ListBox。我想我需要使用可视树,但我不知道如何获得与所选项对应的依赖对象。
以下是代码:
<ListBox ItemsSource="{Binding Path=Stuff}" SelectionChanged="StuffListBox_SelectionChanged" SelectedItem="{Binding Path=SelectedStuff, Mode=TwoWay}" telerik:RadDockPanel.Dock="Bottom">
<ListBox.ItemTemplate>
<DataTemplate>
<telerik:RadDockPanel>
<TextBlock Text="{Binding Path=Name}" telerik:RadDockPanel.Dock="Top" />
<ListBox ItemsSource="{Binding Path=SubStuff}" SelectionMode="Multiple" SelectionChanged="SubStuffListBox_SelectionChanged" Visibility="{Binding Converter={StaticResource StuffToSubStuffVisibilityConverter}}" telerik:RadDockPanel.Dock="Bottom">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Name}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</telerik:RadDockPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
转换器确保只有选定的顶级项目具有可见的子列表框,并且它正在工作。
我需要实现以下方法:
private void StuffListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ListBox stuffListBox = (ListBox)sender;
foreach (Stuff stuff in e.AddedItems)
{
...
subStuffListBox.SelectAll();
}
}
我尝试了stuffListBox.ItemContainerGenerator.ContainerFromItem(stuff)
,但总是返回null。即使stuffListBox.ItemContainerGenerator.ContainerFromIndex(0)
始终返回null。
我也从选择更改方法中得到奇怪的行为。 &#39; e.AddedItems
将包含项目,但stuffListBox.SelectedItem
始终为空。我错过了什么吗?
从我所读过的内容来看,我的问题来自于我在获得选择更改事件时尚未生成容器的事实。我已经看到了涉及收听项目容器生成器状态更改事件的变通方法,但我在Silverlight中工作并且无法访问该事件。由于忽略了将ListBox上的SelectedItems设为只读,我在Silverlight中做的事情是不可能的吗?
答案 0 :(得分:2)
就像你说的那样,最好在ViewModel中完成,但你可以使用VisualTreeHelper选择代码中的所有子列表项。
private void StuffListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var stuffListBox = (ListBox)sender;
ListBoxItem item = (ListBoxItem)stuffListBox.ContainerFromItem(stuffListBox.SelectedItem);
ListBox sublist = FindVisualChild<ListBox>(item);
sublist.SelectAll();
}
根据MSDN
的FindVisualChild方法private childItem FindVisualChild<childItem>(DependencyObject obj)
where childItem : DependencyObject
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(obj, i);
if (child != null && child is childItem)
return (childItem)child;
else
{
childItem childOfChild = FindVisualChild<childItem>(child);
if (childOfChild != null)
return childOfChild;
}
}
return null;
}