Listbox的SelectionChanged事件在其ItemTemplate中包含Button时无法工作

3

当我在列表框中选择项目时,下面的代码不起作用,你知道为什么吗?

<ListBox BorderBrush="Transparent" Background="Transparent" Name="listbox" HorizontalAlignment="Center" VerticalAlignment="Center" ScrollViewer.HorizontalScrollBarVisibility="Disabled" SelectionChanged="selection_changed">
    <ListBox.ItemsPanel>
        <ItemsPanelTemplate>
            <WrapPanel/>
        </ItemsPanelTemplate>
    </ListBox.ItemsPanel>
    <ListBox.ItemTemplate>
        <DataTemplate> 
            <Button Height="90" Width="150" Template="{StaticResource cbutton}"/>                
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox> 
 <ControlTemplate x:Key="cbutton" TargetType="Button">
            <Border CornerRadius="3" BorderThickness="3.5" BorderBrush="White">
                <Border.Background>
                    <LinearGradientBrush EndPoint="1,1" StartPoint="0,0">
                        <GradientStop Color="DarkOrange" Offset="0.1"/>
                        <GradientStop Color="Orange" Offset="0.85"/>
                    </LinearGradientBrush>
                </Border.Background>
                <TextBlock FontWeight="ExtraBold" Foreground="White" TextAlignment="Center" TextWrapping="Wrap" FontSize="15" Text="{Binding name}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
            </Border>
        </ControlTemplate>

1
“不起作用”是什么意思?会发生什么事情?有错误吗? - iabbott
我通过像这样显示消息来检查它是否工作 code private void selection_changed(object sender, SelectionChangedEventArgs e) { MessageBox.Show("works?");
}code,但是没有任何东西显示。
- Maximus
你尝试在DataTemplate中使用其他控件而不是按钮了吗? - cguedel
是的,我做了。我放置了文本块并且它起作用了,但我想知道按钮出了什么问题,以致于它表现出意外的方式。 - Maximus
2个回答

2
< p > 由于按钮捕获鼠标单击事件,而不是 ListBox ,因此不会触发 SelectionChanged 事件。 < p > 您可以将事件处理程序设置为按钮的单击事件。
   <Button Height="90" Width="150" Click="myClickEventHandler"/>  

无论如何,我建议您使用MVVM,而不是Code-Behind事件处理程序。

您可以设置一个命令,该命令将在按钮单击时触发,并发送命令按钮的内容,例如。

  <Button Name="myButton" Height="90" Width="150" Template="{StaticResource cbutton}">     
      <i:Interaction.Triggers>
             <i:EventTrigger EventName="SelectionChanged">
                   <i:InvokeCommandAction Command="{Binding DoSomething}"  CommandParameter="{Binding ElementName=myButton, Path=Content}"/>
            </i:EventTrigger>
      </i:Interaction.Triggers>
  </Button>

视图模型

DoSomething = new DelegateCommand<object>(content=> 
{
    // Do whatever you want 

});

如果您不熟悉MVVM,学习它可能需要一些时间,但绝对是值得的 :)


@user2396510 对不起,我的回答不够好,我已经更新了我的回答。 - Omri Btian
@user2396510,与WinForms不同,WPF事件机制有几种类型的事件 - 从最顶层的父级到子级的事件和相反方向的事件。您可以在此处了解更多信息:http://www.codeproject.com/Articles/464926/To-bubble-or-tunnel-basic-WPF-events - Omri Btian
我对MVVM了解甚少,但似乎值得学习。谢谢。 - Maximus
@user2396510 我强烈推荐你学习它。一开始可能有点难以理解,但是一旦你掌握了它,你就会明白它的真正威力。我在这里的回答中发布了一些关于MVVM的好链接。这里 - Omri Btian
有过同样的问题。我没有使用按钮的'Command'对象,而是在Button.Tag属性上设置绑定(与我绑定到Button.Content相同的内容)并在我的ViewModel中捕获了点击事件(使用Caliburn Micro进行MVVM)。仅代表个人观点。 - captonssj

2
您可以在ListBoxItem上添加PreviewMouseDown事件处理程序:
    <ListBox ItemsSource="{Binding ListBoxItemsSource}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Button Content="{Binding}" />
            </DataTemplate>
        </ListBox.ItemTemplate>
        <ListBox.ItemContainerStyle>
            <Style TargetType="{x:Type ListBoxItem}">
                <EventSetter Event="PreviewMouseDown"
                             Handler="ItemOnPreviewMouseDown" />
            </Style>
        </ListBox.ItemContainerStyle>
    </ListBox>


    private void ItemOnPreviewMouseDown(
        object sender, MouseButtonEventArgs e)
    {
        ((ListBoxItem) sender).IsSelected = true;
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接