如何正确使用列表框itemtemplate/datatemplate中的按钮?

Ben*_*ale 5 c# silverlight styles datatemplate

我有一个Silverlight应用程序,显示一个项目列表ListBox.每个项目代表我的应用程序的不同"页面",所以我有一个应用于ItemContainerStyle属性的样式,如下所示:

<Style x:Key="navigationItemContainerStyle" TargetType="ListBoxItem">
    <Setter Property="Margin" Value="5,3"/>
    <Setter Property="FontSize" Value="16"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate>
                <Grid Cursor="Hand">
                    <VisualStateManager.VisualStateGroups>
                        <!-- code omitted --!> 
                    </VisualStateManager.VisualStateGroups>
                    <Border x:Name="contentBorder"
                            Background="{StaticResource navigationHighlightBrush}" 
                            CornerRadius="3"
                            Opacity="0"/>
                    <ContentControl x:Name="content"
                                    Margin="10,5"
                                    Content="{Binding}" 
                                    Foreground="DarkGray"/>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
Run Code Online (Sandbox Code Playgroud)

风格很简单.它仅仅是显示BorderListBoxItem的视觉状态等于'选定’.请注意,内容由a托管,ContentControl因为我希望能够Foreground在项目处于"已选择"状态时更改属性.

这可以很好地工作,如下面的屏幕截图所示:

在此输入图像描述

现在我希望所选项目调用导航,所以我的想法是创建一个DataTemplate将每个项目的内容设置为HyperLinkButton:

<DataTemplate x:Key="navigationListBoxItemTemplate">
    <HyperlinkButton Content="{Binding}" 
                     Background="Transparent"/>
</DataTemplate>
Run Code Online (Sandbox Code Playgroud)

现在这不能作为ItemTemplate主机的内容ContentControl而不是一样,ContentPresenter所以我必须更新ListBoxItem模板才能使用ContentPresenter.

<ContentPresenter x:Name="content" Margin="10,5"/>
Run Code Online (Sandbox Code Playgroud)

我现在得到以下结果:

在此输入图像描述

当我在点击HyperLinkButtonListBoxItem现在不再选择(我可以点击外刚内HyperLinkButtonListBoxItem变为选中).我真正想要的是ListBoxItemHyperLinkButton点击时被选中.该 HyperLinkButton所以我不能绑定到没有选择的概念ListBoxItemIsSelected属性.

注意:实际导航工作完美,问题纯属于外观ListBoxItems.

所以我的问题是:

  1. 我可以这样做,以便在HyperLinkButton点击时,ListBoxItem像第一张图像一样被选中吗?
  2. 我还需要一些方法来改变HyperLinkButton选择它的前景,因为我不再在项目模板中完成,因为我交换了来自ContentControla ContentPresenter.

注意:我可以通过绑定我的viewModel 的SelectedItem属性ListBox并处理那里的导航来解决这个问题,否定了HyperLinkButton每个人都有托管的要求,ListBoxItem但我有兴趣知道是否可以使用样式和模板来实现我想要的结果.

更新

我尝试了几个尝试解决这个问题,但到目前为止都没有成功.我尝试的第一件事是HyperLinkButton在我的控件中应用了一个新的样式,DataTemplate它实际上从控件中删除了所有默认的外观,但我的应用程序仍然按照上述方式运行.

我尝试的第二件事是将IsHitTestVisible属性设置为false.这允许我点击"直通" HyperLinkbutton并选择,ListBoxItem但这意味着现在不再调用导航.

Sil*_*ver 0

未选择 ListBoxItem,因为 Button(无论其类型是什么)将 MouseLeftButtonDown 事件标记为已处理。因此,所需的事件不会向上冒泡到父 ListBoxItem。

显然,您的 ListBoxItem 通过单击获得焦点(我假设这是最终图像中的边框),因此无论如何这都必须发生。

在幕后,ListBoxItem 将设置一个标准的 LeftMouseButtonDown 事件处理程序来处理选择,并且它必须调用 AddHandler 来处理设置焦点。


您可以通过为事件添加自己的处理程序来实现类似的效果,如下所示:

 listboxitem.AddHandler(UIElement.MouseLeftButtonDownEvent, new System.Windows.Input.MouseButtonEventHandler(MyMouseLeftButtonDownEventHandler), true);
Run Code Online (Sandbox Code Playgroud)

最后一个参数指示处理程序处理已处理的事件...

我将附加此处理程序留给您,但使用行为可能是最直接的。您可以从 Button 派生一个类型,并让它沿着可视化树向上查找并选择 ListBoxItem...可能性是无限的。