【问题标题】:How to display top 3 items in WPF bound collection?如何显示 WPF 绑定集合中的前 3 个项目?
【发布时间】:2013-02-04 19:15:37
【问题描述】:

我正在创建一个显示数据摘要的控件。在此页面上,我将控件绑定到包含许多项目的 ObservableColection。我创建了一个按时间对项目进行排序的 CollectionView,但在这个控件中我只想显示前 3 个项目。我尝试创建一个转换器来完成此操作,但我尝试过滤列表的所有方式都返回一个“新”列表,并且当将新项目添加到主 ObservableCollection 时,控件不再更新。

有没有一种干净的方法来完成这个?我将不得不为我的几个系列做类似的事情,所以我想做一些通用的东西。

【问题讨论】:

    标签: wpf


    【解决方案1】:

    如果您使用 ViewModel 模式,干净的方法是拥有另一个包含前 N 个项目的 ObservableCollection。这样绑定是直接的,您只需更改模型即可将 3 更改为您想要的任何 N。

    public class MyViewModel
    {
        private ObservableCollection<string> myList;
    
        public ObservableCollection<string> MyList 
        { 
            get { return myList; }
            set { return myList; }
        }
    
        public Collection<string> MyListTop3 
        {
            get { return new Collection<string>(MyList.Take(3).ToList()); }
        }
    
        public MyViewModel() 
        {
            myList = new ObservableCollection<string>();
    
            myList.CollectionChanged += (sender, args) =>
            { 
                RaisePropertyChanged("MyListTop3");
            }; 
        } 
    }
    

    如果您只想通过 XAML 来处理它(不是 cleaneast 方式):

    <ListBox>
    
        <ListBox.Resources>
            <ContentPresenter x:Key="value0" Content="{Binding MyList[0]}"/>
            <ContentPresenter x:Key="value1" Content="{Binding MyList[1]}"/>
            <ContentPresenter x:Key="value2" Content="{Binding MyList[2]}"/>
        </ListBox.Resources>
    
        <ListBoxItem Content="{DynamicResource value0}"/>
        <ListBoxItem Content="{DynamicResource value1}"/>
        <ListBoxItem Content="{DynamicResource value2}"/>
    
    </ListBox>
    

    此示例显示了一个 ListBox,但您可以在任何其他控件上使用它。

    【讨论】:

    • 使用第一种方法,如果某个 UI 控件绑定到 MyListTop3,它会在 MyList 更新时自动更新其内容吗?或者您是否必须在MyList 更新时明确地为MyListTop3 提出属性更改通知?只是好奇。
    • 当然,您必须以某种方式通知更改。正确的 MyListTop3 并不是真正的 ObservableCollection,因为您没有向其中添加项目,而是通过另一个集合(即可观察的集合)构建它。更新了我的完整答案。
    • 这样,每当您对主列表 MyList 进行更改时,它都会更新。
    • 这就是我的怀疑,但我不确定。很好的解决方案,感谢您的澄清!
    • 谢谢,这基本上就是我最终要做的。我刚刚在主列表的 CollectionChanged 事件中直接更新了我的控件绑定到的过滤列表。
    【解决方案2】:

    您可以使用 CollectionView 的内置过滤来执行此操作。在 Filter 谓词中,您可以使用原始集合并以与视图排序相同的方式对其进行排序并检查索引。

    FilteredList = new ObservableCollection<string> { "One", "Two", "Three", "Four", "Five" };
    
    _defaultView = CollectionViewSource.GetDefaultView(FilteredList);
    _defaultView.SortDescriptions.Add(new System.ComponentModel.SortDescription(".", System.ComponentModel.ListSortDirection.Ascending));
    _defaultView.Filter = o =>
    {
        int index = FilteredList.OrderBy(s => s).ToList().IndexOf(o as string);
        return index >= 0 && index < 3;
    };
    

    您还需要确保在添加项目时刷新视图 - 通过将其包含在执行添加的代码中或在 CollectionChanged 事件的处理程序中。

    FilteredList.Add(newItem);
    _defaultView.Refresh();
    

    【讨论】:

    • 比接受的答案更清洁的解决方案,您不需要保存附加集合,只需过滤视图,您可以在运行时在过滤/完整视图之间按需更改视图。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-04
    • 2013-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多