Silverlight 4: проблема выбора элемента списка

#c# #silverlight-4.0

#c# #silverlight-4.0

Вопрос:

Мне нужно программно выбрать подмножество элементов списка в элементе управления ListBox (SelectedMode = Multiple).

 <Grid x:Name="LayoutRoot" Background="White">
    <ListBox Height="238" HorizontalAlignment="Left" Margin="26,41,0,0" Name="listBox1" VerticalAlignment="Top" Width="349" SelectionMode="Multiple" />
    <Button Content="Fill" Height="23" HorizontalAlignment="Left" Margin="26,12,0,0" Name="buttonFill" VerticalAlignment="Top" Width="75" Click="buttonFill_Click" />
    <Button Content="Randomly Select" Height="23" HorizontalAlignment="Left" Margin="116,12,0,0" Name="buttonSelectRandom" VerticalAlignment="Top" Width="104" Click="buttonSelectRandoml_Click" />
</Grid>


    private void buttonFill_Click(object sender, RoutedEventArgs e)
    {
        for (int i = 0; i < 100; i  )
            listBox1.Items.Add(new ListBoxItem { Content = i.ToString()});
    }

    private void buttonSelectRandom_Click(object sender, RoutedEventArgs e)
    {
        var rand = new Random();

        foreach (ListBoxItem item in listBox1.Items)
            if (rand.Next(2)==1) item.IsSelected = true; 
    }
  

Однако кажется, что только видимые в данный момент элементы отображаются как выбранные при запуске кода (нажмите кнопку «Заполнить», а затем кнопку «Выбрать случайным образом»). Прокрутка списка не показывает, что другие элементы списка не выбраны, даже если проверка их состояния «IsSelected» в коде покажет, что для них установлено значение «true».

Интересно, что если я сначала вручную прокручу список до конца (или частично), а затем нажму кнопку «Выбрать случайным образом», то в списке будут правильно отображены все выбранные элементы. Я перепробовал много обходных путей, но, похоже, не могу найти тот, который работает. Это ошибка? Есть обходные пути?

Спасибо за вашу помощь.

Jink

Ответ №1:

это может быть связано с тем, что в ListBox используется VirtualizingStackPanel. Можете ли вы протестировать это с помощью обычной StackPanel?

     <ListBox>
        <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel/>
            </ItemsPanelTemplate>
        </ListBox.ItemsPanel>
    </ListBox>
  

Редактировать:

Другое решение заключается в том, чтобы вместо выполнения элемента.IsSelected = true, вы делаете

         foreach (int item in listBox1.Items)
        {
            if (rand.Next(2) == 1)
            {
                this.listBox1.SelectedItems.Add(item);
            }
        }
  

Я протестировал это, и это работает. 🙂

Комментарии:

1. 1 У меня это сработало. Это также объясняет, почему прокрутка списка перед установкой параметров выбора приводит к правильному отображению элементов.

2. @Xin, я не могу принять ответ, поскольку это не мой вопрос. 🙂 Я столкнулся с этим, потому что из вашего ответа неясно, пробовали ли вы этот код самостоятельно, но он работает для устранения этой конкретной проблемы. В любом случае, на случай, если операционной системе действительно понадобится панель элементов виртуализации из-за элементов, требующих большого объема памяти, я надеюсь, что они оставят вопрос открытым на несколько дней и дадут многим людям шанс взвесить другие возможные обходные пути.

3. 1 Спасибо @Xin, это работает. Хммм, VirtualizingStackPanel — я должен взглянуть на это. Я воспользуюсь советом @ Kimberly и оставлю его открытым на некоторое время, прежде чем принять ваш ответ, чтобы посмотреть, есть ли хороший способ сделать это с помощью VirtualizingStackPanel или чего-то подобного, потому что у меня могло бы быть много элементов в списке, и это могло бы повысить производительность.

4. Привет, я обновил ответ и, надеюсь, на этот раз он будет работать даже с VirtualizingStackPanel. Интересно, я обнаружил, что ваш исходный код работает в WPF. Это означает, что как только эти невидимые элементы списка будут прокручены в поле зрения, они будут выбраны автоматически. Однако в Silverlight это не так.

5. Отлично, @Xin. Протестировал ваш второй пакет кода и могу подтвердить, что он действительно работает с VirtualizingStackPanel в моем проекте Silverlight. Мне было бы интересно узнать, что стоит за этим различием в поведении WPF Silverlight.