Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
589 views
in Technique[技术] by (71.8m points)

c# - Couldn't get selected items correctly if setting ListView ItemsContainer as VirtualizationStackPanel

I set 'VirtualizingStackPanel.IsVirtualizing' to true and 'VirtualizingStackPanel.VirtualizationMode' to 'Recycling', because the items in my ListView are too many. The SelectionMode of the ListView is Extended, the 'IsSelected' property of the ListViewItem is bound to 'IsSelected' property of my model, bind mode is two way.

When I want to use Ctrl+A to select all of the items, it only select part of the items, so I use KeyBinding to write the select all method like below:

 <KeyBinding Command="{Binding SelectAllCommand}"
                            Modifiers="Control"
                            Key="A"/>

SelectAll method will loop the ItemsSource collection and set each of the item's IsSelected property to true. But it also leads to something unexpected. When all of the items are selected, I scroll the scrollbar to the bottom and it will load more items to the ListView, I single click one item and the expected is all other items are unselected, only select this item. But, it seems not unselect other items.

Anybody can help?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

This behaviour of the Selector is to be expected, because it can operate only with loaded UI elements. Due enabling virtualization you have loaded only those elements which contains in visible area. So, Selector does not "know" about others.

For fix this you must do so, that Selector "know" about previously selected items. In other word, you must to prohibit unloading any UI element which was selected.

First, create own virtualizing panel with blackjack and hookers:

public class MyVirtualizingStackPanel : VirtualizingStackPanel
{
    protected override void OnCleanUpVirtualizedItem(CleanUpVirtualizedItemEventArgs e)
    {
        var item = e.UIElement as ListBoxItem;
        if (item != null && item.IsSelected)
        {
            e.Cancel = true;
            e.Handled = true;
            return;
        }

        var item2 = e.UIElement as TreeViewItem;
        if (item2 != null && item2.IsSelected)
        {
            e.Cancel = true;
            e.Handled = true;
            return;
        }

        base.OnCleanUpVirtualizedItem(e);
    }
}

Next, replace default panel in the ListBox, ListView, TreeView or other user controls which provide selector. For example, via style:

<Setter Property="ItemsPanel">
    <Setter.Value>
        <ItemsPanelTemplate>
            <blackjackandhookers:MyVirtualizingStackPanel/>
        </ItemsPanelTemplate>
    </Setter.Value>
</Setter>

... or, directly in your selector:

<YourSelector.ItemsPanel>
    <ItemsPanelTemplate>
        <blackjackandhookers:MyVirtualizingStackPanel/>
    </ItemsPanelTemplate>
</YourSelector.ItemsPanel>

Enjoy!

I hope my answer will help you.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...