WPF ListBoxItem 选择问题

19

我有一个包含复选框的列表框:

<ListBox Style="{StaticResource CheckBoxListStyle}" Name="EditListBox">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <CheckBox Click="Checkbox_Click" IsChecked="{Binding Path=IsChecked, Mode=TwoWay}" Content="{Binding Path=DisplayText}" />
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

我遇到的问题是,当我点击复选框或其内容时,父ListBoxItem不会被选中。如果我单击复选框旁边的空白处,则ListBoxItem会被选中。

我尝试实现的行为是,在列表中选择一个或多个项目,并使用空格键打开和关闭复选框。

更多信息:

private void Checkbox_Click(object sender, RoutedEventArgs e)
{
    CheckBox chkBox = e.OriginalSource as CheckBox;
}
在上面的代码中,当我点击复选框时,e.Handled为false,chkBox.Parent为null。
Kent的答案让我找到了正确的方向,下面是我的最终结果:
<ListBox Style="{StaticResource CheckBoxListStyle}" Name="EditListBox" PreviewKeyDown="ListBox_PreviewKeyDown">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <CheckBox IsChecked="{Binding Path=IsChecked, Mode=TwoWay}" />
                <TextBlock Text="{Binding DisplayText}"/>
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

我不得不使用PreviewKeyDown,因为默认情况下,在列表框中按空格键时,它会取消选择除最近选择的项之外的所有项。

4个回答

10

首先,将内容放在CheckBox之外:

<StackPanel Orientation="Horizontal">
    <CheckBox IsChecked="{Binding IsChecked}"/>
    <TextBlock Text="{Binding DisplayText}"/>
</StackPanel>

接下来,您需要确保在按下 ListBoxItem 上的空格键时会选中 CheckBox。有许多方法可以做到这一点,包括在 ListBoxItem 上简单地添加事件处理程序。或者您可以在 DataTemplate 中指定 UIElement.KeyUp 或其他处理程序:

<CheckBox IsChecked="{Binding IsChecked}" UIElement.KeyUp="..."/>

3
在您的使用场景中,使用ItemsControl比使用列表框要简单得多。ItemsControl类似于ListBox,但它不包含自动选择行为。这意味着将其用于托管实质上是复选框的列表非常简单,而且您不必解决ListBox的选择行为问题。
简单地切换到ItemsControl将为您提供所需的功能:
<ItemsControl Style="{StaticResource CheckBoxListStyle}" Name="EditListBox">
    <ItemsControl .ItemTemplate>
        <DataTemplate>
            <CheckBox Click="Checkbox_Click" IsChecked="{Binding Path=IsChecked, Mode=TwoWay}" Content="{Binding Path=DisplayText}" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

您可以单击文本来检查复选框(默认行为),您也可以使用键盘而无需连接任何事件处理程序。

3
您也可以绑定CheckBox的IsChecked属性和ListBoxItem的IsSelected属性:
<ListBox>
    <ListBox.ItemTemplate>
        <DataTemplate>
            <CheckBox Content="{Binding DisplayText}" IsChecked="{Binding Path=IsSelected, RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}}"/>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

1
这是我最初的方式。缺陷在于复选框状态绑定到列表控件选择状态,这对于包含复选框的列表控件来说不是正常行为。 - 17 of 26

0
另一种方法是为CheckBox的Checked和Unchecked事件创建事件处理程序,并在模板化的ListBoxItem上设置IsSelected。
<ListBox>
    <ListBox.ItemTemplate>
        <DataTemplate>
            <CheckBox Content="{Binding Path=DisplayText}"
                      IsChecked="{Binding IsChecked}"
                      Checked="SelectListBoxItem"
                      Unchecked="SelectListBoxItem" />
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

private void SelectListBoxItem(object sender, RoutedEventArgs e)
{
    var checkBox = sender as CheckBox;
    var parent = VisualTreeHelper.GetParent(checkBox);
    while (!(parent is ListBoxItem))
    {
        parent = VisualTreeHelper.GetParent(parent);
    }

    var item = parent as ListBoxItem;
    item.IsSelected = true;
}

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