对列表框中的列表项进行命中测试

hittesting on Listitems in a Listbox

我自定义了一个列表框来显示饼图(每个列表项都是饼图的一个片段)。为此,我使用了一个 Itemtemplate,它(目前)仅包含一个 Shape。为了使这些形状形成一个完整的圆,我计算了每块 start/endangle 并使用自定义 ItemsPanelTemplate 将项目堆叠在一起。

当我点击饼图附近的任何地方时,"last" 项目被选中,因为它位于其他项目之上。这很明显,但我希望因为 ItemTemplate 只包含一个 Shape,它会从那里继承命中测试,而不是假设所有项目都由矩形表示。

我应该在哪里包含命中测试?我想将 IsHitTestVisible="false" 设置为 ItemTemplate 中的所有内容,形状除外 - 但由于它实际上不包含除我的形状之外的任何内容,所以我现在被卡住了。

编辑:

我尝试用透明背景的网格围绕我的 Shape,我确实在其上设置了 IsHitTestVisible="false"。这仍然会导致每次单击时选择最后一个元素,而我会假设不会选择任何内容。我想我可能对命中测试应该如何工作感到困惑?

代码:

由于我是 WPF 的新手,我可能在实施过程中遗漏了一些东西。我添加了一个最小示例的相关代码部分:

我的Shape-class:

public class PiePiece : Shape
{
    protected override Geometry DefiningGeometry
    {
        get { return GetPieGeometry() }
    }

    //some DependencyProperties and helper methods.

    private Geometry GetPieGeometry()
    {
        //calculations
    }
}

XAML:

<Window [...] xmlns:Runner="clr-namespace:MyNamespace">
<Window.Resources>

    <!-- some custom converters -->

    <!-- ListBox-Style with the custom ControlTemplate for my Listbox -->

    <ItemsPanelTemplate x:Key="ItemPanel">
        <Grid/>
    </ItemsPanelTemplate>
</Window.Resources>

<ListBox [...] ItemsPanel="{StaticResource ItemPanel}">
<ListBox.ItemTemplate>
    <DataTemplate>
        <Grid Background="{x:Null}" IsHitTestVisible="False">
            <Runner:PiePiece IsHitTestVisible="False" [...]>
                <!-- Dependency Properties are set via Multibinding here -->
            </Runner:PiePiece>
        </Grid>
    </DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

</Window>

我终于找到了命中测试没有按预期工作的原因:

ListBoxItem-Style 的默认模板将 ContentPresenter 和带有透明背景的 Border 包围起来。所有点击事件都被该边框捕获和处理,而不是我的 ContentPresenter。按照 Gaz 的建议为 ListBoxItem 编写我自己的样式并将背景设置为 {x:null} 解决了这个问题(删除边框也是如此,但我现在添加了另一个边框以进行进一步自定义)。