Question

J'ai une liste déroulante où les éléments contiennent des cases à cocher:

<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>

Le problème que je rencontre est que lorsque je clique sur la case à cocher ou sur son contenu, le parent ListBoxItem n'est pas sélectionné. Si je clique sur l'espace blanc à côté de la case à cocher, le ListBoxItem est sélectionné.

Le comportement que j'essaie d'obtenir est de pouvoir sélectionner un ou plusieurs éléments dans la liste et d'utiliser la barre d'espacement pour activer ou désactiver les cases à cocher.

Quelques informations supplémentaires:

private void Checkbox_Click(object sender, RoutedEventArgs e)
{
    CheckBox chkBox = e.OriginalSource as CheckBox;
}

Dans le code ci-dessus, lorsque je clique sur une case à cocher, e.Handled est false et chkBox.Parent est null.

La réponse de Kent m'a mis dans la bonne voie, voici ce que j'ai fini avec:

<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>

Je devais utiliser PreviewKeyDown car, par défaut, lorsque vous appuyez sur la barre d'espace dans une zone de liste, tout est désélectionné, à l'exception du dernier élément sélectionné.

Était-ce utile?

La solution

Pour commencer, placez le contenu en dehors de la CheckBox :

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

Après cela, vous devrez vous assurer que si vous appuyez sur l'espace sur un ListBoxItem , le contrôle CheckBox est activé. Il existe plusieurs façons de procéder, notamment un simple gestionnaire d’événements sur ListBoxItem . Vous pouvez également spécifier un gestionnaire pour UIElement.KeyUp ou autre dans votre DataTemplate :

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

Autres conseils

Vous pouvez également lier les propriétés IsChecked de CheckBox et IsSelected du ListBoxItem:

<ListBox>
    <ListBox.ItemTemplate>
        <DataTemplate>
            <CheckBox Content="{Binding DisplayText}" IsChecked="{Binding Path=IsSelected, RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}}"/>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

Dans votre cas d'utilisation, il serait beaucoup plus simple d'utiliser un ItemsControl au lieu d'une zone de liste. Un ItemsControl est similaire à une Listbox, sauf qu'il ne contient pas le comportement de sélection automatique. Cela signifie que son utilisation pour héberger une liste de ce qui sont essentiellement des cases à cocher est très simple et vous n'avez pas à contourner le comportement de sélection du ListBox.

En passant simplement à ItemsControl, vous obtiendrez exactement ce dont vous avez besoin:

<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>

Vous pouvez cliquer sur le texte pour cocher les cases à cocher (comportement par défaut) et vous pouvez aussi utiliser le clavier sans avoir à connecter de gestionnaire d'événement.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top