Listbox IsSelected with SelectionMode=Extended

2019-02-18 02:43发布

问题:

Sorry for the vague title, I couldn't come up with a good way to summarize what is happening.

I have a bound WPF listbox:

<UserControl.Resources>
    <DataTemplate DataType="{x:Type local:MyBoundObject}">
        <TextBlock Text="{Binding Label}" />
    </DataTemplate>
</UserControl.Resources>

<ListBox ItemsSource="{Binding SomeSource}" SelectionMode="Extended">
    <ListBox.ItemContainerStyle>
        <Style TargetType="{x:Type ListBoxItem}">
            <Setter Property="IsSelected Value="{Binding Path=IsSelected, Mode=TwoWay}"/>
        </Style>
    </ListBox.ItemContainerStyle>
</ListBox>

I want to operate on ONLY the selected items. I do this by iterating through a list of all items and checking each object to see if it's IsSelected property is set.

This works except for when I have many items in the list (enough so they are not all visible) and I press CTRL-A to select all items. When I do this, all the visible items have their IsSelected property set to true, and all the rest are left false. As soon as I scroll down, the other items come into view and their IsSelected properties are then set to true.

Is there any way to fix this behaviour so that every object's IsSelected property is set to true when I press CTRL-A?

回答1:

Try set the

ScrollViewer.CanContentScroll="False"

on the ListBox, it should fix the ctrl+a problem.



回答2:

If you want get all selected items you can use SelectedItems property from ListBox. You don't need to add IsSelected property to your object.

Check below example.

XAML file:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="30" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>

    <StackPanel Orientation="Horizontal">
        <Button Content="Selected items" Click="Button_Click" />
        <Button Content="Num of IsSelected" Click="Button_Click_1" />
    </StackPanel>

    <ListBox Name="lbData" SelectionMode="Extended" Grid.Row="1">
        <ListBox.ItemContainerStyle>
            <Style TargetType="{x:Type ListBoxItem}">
                <Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay}"/>
            </Style>
        </ListBox.ItemContainerStyle>
    </ListBox>
</Grid>

Code-behind file:

using System.Collections.Generic;
using System.Windows;
using System.Windows.Documents;

namespace ListBoxItems
{   
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            List<MyBoundObject> _source = new List<MyBoundObject>();
            for (int i = 0; i < 100000; i++)
            {
                _source.Add(new MyBoundObject { Label = "label " + i });
            }
            lbData.ItemsSource = _source;
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show(lbData.SelectedItems.Count.ToString());
        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            int num = 0;
            foreach (MyBoundObject item in lbData.Items)
            {
                if (item.IsSelected) num++;
            }

            MessageBox.Show(num.ToString());
        }
    }

    public class MyBoundObject
    {
        public string Label { get; set; }
        public bool IsSelected { get; set; }
    }
}


标签: c# wpf listbox