两个重叠的列表框。选择问题
我试图在占据相同空间的两个单独的列表框中显示形状。我已将背景设置为透明和 {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 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;
}
I'm trying to display shapes in two separate Listboxes occupying the same space. I've set the Background to both Transparent and {x:Null} but the mouseclick is still getting captured by the topmost Listbox so I can't select any shapes from the underlying ListBox.
Here is some sample code reproducing the problem.
<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>
This is how I solved this problem for now but I'm more than open for other suggestions :) I enabled hittesting on the Grid and disabled it for both ListBoxes. Then I did the hittesting in the event handler instead
<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>
Event handler and hittesting
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;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可以通过使用 CompositeCollection 作为项目源将多组数据绑定到单个 ListBox:
然后您可以使用数据模板来控制不同数据类型的外观。您可以使用隐式数据模板,也可以使用 项目模板选择器。
有关使用和绑定到 CompositeCollection 的更多信息,请参阅此资源:如何将 CollectionContainer 绑定到视图模型中的集合?
You can bind multiple sets of data to a single ListBox by using a CompositeCollection as the items source:
You can then use data templates to control the appearance of different data types. You can either use implicit data templates or you can use an ItemTemplateSelector.
For more information about using and binding to a CompositeCollection, see this resource: How do you bind a CollectionContainer to a collection in a view model?
您可以将列表框绑定到可见性变量。这样,当您处于要选择底部框和折叠顶部框的情况时,您可以使底部框可见,反之亦然,当您需要选择顶部框时。
You could bind your ListBoxes to a Visibility variable. This way you can make the bottom box visible when you are in a situation where the bottom one would be selected and the top on collapsed and visa verse when you need the top one to be selected.