Два перекрывающихся списка. Проблема выбора
Я пытаюсь отобразить фигуры в двух отдельных списках, занимающих одинаковое пространство. Я установил в качестве фона значение "Прозрачный" и {x:Null}, но щелчок мыши все еще захватывается самым верхним списком, поэтому я не могу выбрать какие-либо фигуры из базового списка.
Вот пример кода, воспроизводящего проблему.
<Grid>
<!-- ListBox 1 -->
<ListBox Background="{x:Null}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Background="{x:Null}"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Background="Transparent">
<Ellipse Width="100" Height="100" Stroke="Blue" StrokeThickness="10"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
1
</ListBox>
<!-- ListBox 2 -->
<ListBox Background="{x:Null}">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Background="{x:Null}"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="Canvas.Left" Value="100"/>
<Setter Property="Canvas.Top" Value="100"/>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<Ellipse Width="100" Height="100" Stroke="Blue" StrokeThickness="10"/>
</DataTemplate>
</ListBox.ItemTemplate>
1
</ListBox>
</Grid>
Вот как я решил эту проблему сейчас, но я более чем открыт для других предложений:) Я включил тестирование совпадений в Grid и отключил его для обоих списков. Затем я сделал тестирование в обработчике событий вместо
<Grid MouseDown="Grid_MouseDown"
IsHitTestVisible="True"
Background="Transparent">
<!-- ListBox 1 -->
<ListBox Background="Transparent"
IsHitTestVisible="True"
..>
</ListBox>
<!-- ListBox 2 -->
<ListBox Background="Transparent"
IsHitTestVisible="True"
..>
</ListBox>
</Grid>
Обработчик событий и тестирование
private void Grid_MouseDown(object sender, MouseButtonEventArgs e)
{
Grid grid = sender as Grid;
Point ptCurrent = e.GetPosition(grid);
VisualTreeHelper.HitTest(grid, null, new HitTestResultCallback(HitTestCallback), new PointHitTestParameters(ptCurrent));
}
public HitTestResultBehavior HitTestCallback(HitTestResult htrResult)
{
ListBoxItem listBoxItem = GetVisualParent<ListBoxItem>(htrResult.VisualHit);
if (listBoxItem != null)
{
listBoxItem.IsSelected = true;
return HitTestResultBehavior.Stop;
}
return HitTestResultBehavior.Continue;
}
public T GetVisualParent<T>(object child) where T : Visual
{
DependencyObject c = child as DependencyObject;
while ((c != null) && !(c is T))
{
c = VisualTreeHelper.GetParent(c);
}
return c as T;
}
2 ответа
Вы можете привязать несколько наборов данных к одному ListBox, используя CompositeCollection в качестве источника элементов:
<ListBox ...>
<ListBox.ItemsSource>
<CompositeCollection>
<CollectionContainer Collection={Binding ...}" />
<CollectionContainer Collection={Binding ...}" />
</CompositeCollection>
</ListBox.ItemsSource>
</ListBox>
Затем вы можете использовать шаблоны данных для управления внешним видом различных типов данных. Вы можете использовать неявные шаблоны данных или использовать ItemTemplateSelector.
Для получения дополнительной информации об использовании и привязке к CompositeCollection см. Этот ресурс: Как связать CollectionContainer с коллекцией в модели представления?
Вы можете привязать свои ListBoxes к переменной Visibility. Таким образом, вы можете сделать нижнюю рамку видимой, когда окажетесь в ситуации, когда будет выбрана нижняя, а верхняя часть свернута, и в стихе, когда вам нужно выбрать верхнюю.