如何从CollectionViewSource中获取项目数量?

18

我正在使用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”方法,其中我可以从CollectionViewSource对象中获取“initialCount”和“filteredCount”。

感谢您的关注。

6个回答

46

您还可以使用_viewSource.View.Cast<object>().Count()查看过滤列表的数量,_viewSource.View.SourceCollection.Cast<object>().Count()查看原始列表的数量。


感谢您澄清如何获取CollectionViewSource的过滤/排序内容。在您的评论之前,我无法获取CollectionViewSource中的第一项:var firstItem = this.xViewInDescendingOrder.View.Cast<Thing>().ElementAt<Thing>(0); - rfreytag

12

我认为更好的解决方案是像往常一样使用Linq!

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

...或者...

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

如果您在运行时不知道项目的类型!


7

源集合和集合视图都实现了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
请注意,filteredCount 是可见项目的数量,而不是已过滤掉的项目数量。 - apc

4
如果你正在使用MVVM模式,你可以让你的VM创建一个集合视图而不是由CollectionViewSource为你创建一个。这样,你就可以控制所创建的CVS的类型,因此你可以创建一个具有Count属性的ListCollectionViewSource,这取决于你要过滤的数据的属性。

1
抱歉,我不太明白。您能否通过使用我的代码来解释一下?谢谢。 - Manish Basantani

2
var count = DataGrid.ItemsSource.OfType<object>().Count();

通过这个方法,你可以获取itemsSource中的计数数字,例如2、3。 - EeNiArT
虽然这段代码可能回答了问题,但最好解释一下如何解决问题,并提供代码作为示例或参考。仅有代码的答案可能会令人困惑并缺乏上下文。 - Robert Columbia
感谢Robert Columbia先生指导我以好的方式提供帮助。 - EeNiArT

0
public static int Count(this ICollectionView view)
    {
        var index = 0;
        foreach (var unused in view)
        {
            index++;
        }
        return index;
    }

虽然这段代码可以回答问题,但最好是解释如何解决问题,并提供代码作为示例或参考。仅限于代码的答案可能会令人困惑并且缺乏上下文。 - Robert Columbia

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接