WPF: привязка к ListBoxItem.IsSelected не работает для элементов вне экрана

В моей программе у меня есть набор объектов модели представления для представления элементов в ListBox (разрешен множественный выбор). Модель просмотра имеет свойство IsSelected, которое я хотел бы привязать к ListBox, чтобы состояние выбора управлялось в модели просмотра, а не в самом списке.

Однако очевидно, что ListBox не поддерживает привязки для большинства отключенных элементов. элементы экрана, поэтому в целом свойство IsSelected не синхронизируется правильно. Вот код, демонстрирующий проблему. Первый XAML:

<StackPanel>
    <StackPanel Orientation="Horizontal">
        <TextBlock>Number of selected items: </TextBlock>
        <TextBlock Text="{Binding NumItemsSelected}"/>
    </StackPanel>
    <ListBox ItemsSource="{Binding Items}" Height="200" SelectionMode="Extended">
        <ListBox.ItemContainerStyle>
            <Style TargetType="{x:Type ListBoxItem}">
                <Setter Property="IsSelected" Value="{Binding IsSelected}"/>
            </Style>
        </ListBox.ItemContainerStyle>
    </ListBox>
    <Button Name="TestSelectAll" Click="TestSelectAll_Click">Select all</Button>
</StackPanel>

Обработчик C # Select All:

private void TestSelectAll_Click(object sender, RoutedEventArgs e)
{
    foreach (var item in _dataContext.Items)
        item.IsSelected = true;
}

Модель просмотра C #:

public class TestItem : NPCHelper
{
    TestDataContext _c;
    string _text;
    public TestItem(TestDataContext c, string text) { _c = c; _text = text; }

    public override string ToString() { return _text; }

    bool _isSelected;
    public bool IsSelected
    {
        get { return _isSelected; }
        set {
            _isSelected = value; 
            FirePropertyChanged("IsSelected");
            _c.FirePropertyChanged("NumItemsSelected");
        }
    }
}
public class TestDataContext : NPCHelper
{
    public TestDataContext()
    {
        for (int i = 0; i < 200; i++)
            _items.Add(new TestItem(this, i.ToString()));
    }
    ObservableCollection<TestItem> _items = new ObservableCollection<TestItem>();
    public ObservableCollection<TestItem> Items { get { return _items; } }

    public int NumItemsSelected { get { return _items.Where(it => it.IsSelected).Count(); } }
}
public class NPCHelper : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    public void FirePropertyChanged(string prop)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(prop));
    }
}

Можно наблюдать две отдельные проблемы.

  1. Если щелкнуть первый элемент, а затем нажать Shift + End, должны быть выделены все 200 элементов; однако в заголовке указано, что выбран только 21 элемент.
  2. Если вы нажмете «Выбрать все», то действительно будут выбраны все элементы. Если затем щелкнуть элемент в ListBox, можно ожидать, что другие 199 элементов будут отменены, но этого не происходит. Вместо этого снимаются только те элементы, которые находятся на экране (и некоторые другие). Выбор всех 199 элементов не будет отменен, если вы сначала не прокрутите список от начала до конца (и даже тогда, как ни странно, это не сработает, если вы выполните прокрутку с помощью маленького поля прокрутки).

Мои вопросы:

  1. Может кто-нибудь объяснить, почему это происходит?
  2. Могу ли я избежать проблемы или обойти ее?
8
задан Qwertie 17 August 2011 в 18:58
поделиться