如何使单击ListBoxItem内的按钮选择项目?

时间:2020-08-10 06:50:41

标签: c# wpf xaml

我有一个ListBox定义如下:

<ListBox
    DisplayMember="Name"
    ItemsSource="{Binding Persons}"
    ItemTemplate="{StaticResource PeopleDataTemplate}"
    SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
    Name="listOfPeople">
</ListBox>

Person类包含两个属性:

public string FirstName { get; set; }
public string LastName { get; set; }

XAML:

<UserControl.Resources>
    <DataTemplate x:Key="PeopleDataTemplate">
        <StackPanel>
            <Image
                Width="75"
                Height="75"
                Source="{Binding Picture}">
            </Image>
            <TextBlock FontSize="14" TextWrapping="Wrap" Text="{Binding Name}" />
            <Button Command="{Binding DataContext.AddCommand , ElementName=main}" Content="Add" />
        </StackPanel>
    </DataTemplate>
</UserControl.Resources>

如果我单击Image,则ListBoxItem被选中,但是如果我单击Button,则ListBoxItem未被选中。为什么?

2 个答案:

答案 0 :(得分:1)

为什么没有选择该项目?

TL; DR:因为鼠标按下事件由Button处理,并且从未到达ListBoxItem

触发每个IsSelected的{​​{1}}属性的是ListBoxItem路由事件declared on UIElement,其事件被MouseRightButtonDownEvent here覆盖。但是,此ListBoxItembubbling routed event,这意味着它会爬到可视树上,直到被其标记为 handled 为止

  • 如果您单击MouseDownEvent,则Image会收到Image,但不会处理。同样的故事,它最多可以冒充MouseDown。最多可以冒充StackPanel。宾果游戏,在那里处理它并在父项ListBoxItem上调用一个方法,将项目标记为选中。
  • 但是,如果您单击ListBox,则Button会收到Button事件,并立即将其标记为MouseDown here。事件传播已停止,事件再也不会达到Handled为止,永远不会被选中。

如何解决这个问题?

MVVM方式

在您的ListBoxItem实现中,添加一些代码以将AddCommand属性更改为IsSelected。由于您绑定到true,因此将选择您的IsSelected

XAML方式

ListBoxItem添加Click事件处理程序,以将其父项Button手动标记为ListBoxItem

正如@Sinatr所指出的,您还可以对焦点事件做出反应,以选择任何获得焦点的项目。订阅每个Selected的{​​{1}}事件,并订阅find的父GotFocus(您在其中调用StackPanel)并找到父{{ 1}}(您将其称为ListBox)。

答案 1 :(得分:1)

最简单的解决方案是向ListBox.ItemContainerStyle添加相应的触发器以委派焦点:

<ListBox>
  <ListBox.ItemContainerStyle>
    <Style TargetType="ListBoxItem">
      <Style.Triggers>
        <Trigger Property="IsKeyboardFocusWithin" Value="True">
          <Setter Property="IsSelected" Value="True" />
        </Trigger>
      </Style.Triggers>
    </Style>
  </ListBox.ItemContainerStyle>
</ListBox>