Как получить количество элементов из CollectionViewSource? - PullRequest
14 голосов
/ 17 августа 2010

Я использую CollectionViewSource для фильтрации записей, отображаемых в ListBox. Xaml следует.

   <Window x:Class="WPFStarter.ListBoxItemsFilter.ListBoxFilterUsingCollectionViewSource"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        x:Name="userControl"
        Title="ListBoxFilterUsingCollectionViewSource" Height="300" Width="300">
        <Window.Resources>
        <CollectionViewSource Source="{Binding ElementName=userControl, Path=DataContext.Items}"
                              x:Key="cvs" Filter="CollectionViewSource_Filter"/>
        </Window.Resources>
    <StackPanel Orientation="Vertical">
        <TextBox x:Name="txtSearch" TextChanged="txtSearch_TextChanged"/>
        <TextBlock x:Name="txtSummary" Grid.Column="0" HorizontalAlignment="Right" VerticalAlignment="Bottom"  FontSize="8"></TextBlock>
        <ListBox ItemsSource="{Binding Source={StaticResource cvs}}" DisplayMemberPath="First"/>
    </StackPanel>

</Window>

А вот и мой код (пожалуйста, не обращайте внимания на этот код, в реальном приложении я использую лучшие MVVM для этого сценария).

 public partial class ListBoxFilterUsingCollectionViewSource : Window
    {
        private string _text="";
        private readonly CollectionViewSource _viewSource;

        public ListBoxFilterUsingCollectionViewSource()
        {
            InitializeComponent();
            _viewSource = this.FindResource("cvs") as CollectionViewSource;
        }

        private void CollectionViewSource_Filter(object sender, FilterEventArgs e)
        {
            var character = e.Item as Character;
            e.Accepted = character != null && character.First.ToLower().Contains(_text.ToLower());
        }

        private void txtSearch_TextChanged(object sender, TextChangedEventArgs e)
        {
            _text = txtSearch.Text;
            _viewSource.View.Refresh();

            SetSummary();
        }

        private void SetSummary()
        {                
            var initialCount = 10; //HELP????
            var filteredCount = 10; //HELP????
            txtSummary.Text = String.Format("{0} of {1}", filteredCount, initialCount);
        }
    }

ВОПРОС: Мне нужна помощь в написании метода «SetSummary», в котором я могу получить «initialCount» и «FilterCount» из объекта CollectionViewSource.

Спасибо за ваш интерес.

Ответы [ 6 ]

38 голосов
/ 05 января 2011

Вы также можете сделать _viewSource.View.Cast<object>().Count() для отфильтрованного списка и _viewSource.View.SourceCollection.Cast<object>().Count() для оригинала.

10 голосов
/ 09 июля 2012

Я думаю, что лучшим решением, как обычно, является Linq!

_viewSource.View.Cast<[your_type]>().Count();

... или ...

_viewSource.View.Cast<object>().Count();

... если вы не знаететип предметов во время выполнения!

6 голосов
/ 18 августа 2010

Исходная коллекция и представление коллекции реализуют IEnumerable, так что вы всегда можете перебирать их и подсчитывать, сколько в них.Но я бы рекомендовал делать это только в том случае, если у вас нет доступа к фактической коллекции, которую вы использовали в качестве источника.

private void SetSummary() 
{
    int initialCount = 0;
    foreach(var item in _viewSource.View.SourceCollection)
    {
        initialCount++;
    }

    int filteredCount = 0;
    foreach (var item in _viewSource.View)
    {
        filteredCount++;
    }
}
2 голосов
/ 11 декабря 2016
var count = DataGrid.ItemsSource.OfType<object>().Count();
2 голосов
/ 17 августа 2010

Если вы работаете с MVVM, ваша виртуальная машина может создать представление коллекции, а не создание от вашего имени с помощью CollectionViewSource.Затем вы можете контролировать, какой тип CVS создается, поэтому вы можете создать ListCollectionViewSource, который имеет свойство Count.Это действительно зависит от свойств данных, которые вы фильтруете.

0 голосов
/ 20 мая 2018
public static int Count(this ICollectionView view)
    {
        var index = 0;
        foreach (var unused in view)
        {
            index++;
        }
        return index;
    }
...