【问题标题】:How to limit the number of items from an observablecollection databinded listbox?如何限制 observablecollection 数据绑定列表框中的项目数?
【发布时间】:2012-07-07 13:49:13
【问题描述】:

事情是这样的。我有一个视图模型,我在其中调用一个 webclient 并用项目填充一个可观察的集合。我需要在两个不同的页面中有两个不同的列表框,但视图模型中的 ItemsSource 相同。如何限制两个列表框之一中的项目数而不影响另一个?我尝试在创建项目的视图模型中使用 .Take(limit) 但这会影响两个列表框。

更新

视图模型

public class MainViewModel : INotifyPropertyChanged
{
    public MainViewModel()
    {
        this.Items = new ObservableCollection<ItemViewModel>();
        this.Mainlist = new CollectionViewSource();

    }

    public ObservableCollection<ItemViewModel> Items { get; private set; }
    public CollectionViewSource Mainlist { get; set; }

    void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
    {
        try
        {
           ...............
            //Ignore the dummy data in foreach loop. Just for showcase.

            foreach (var item in Items)
            {
                //Items creation

                this.Items.Add(new ItemViewModel()
                { LineOne = item });
            }

            this.Mainlist.Source = App.ViewModel.Items;
            this.Mainlist.Filter += (s, a) => 
                a.Accepted = App.ViewModel.Items.IndexOf((ItemViewModel)a.Item) < 10;
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }

    } 

    .....................
}

在视图方面

    public MainPage()
    {
        InitializeComponent();
        DataContext = App.ViewModel;
        list.ItemsSource = App.ViewModel.Mainlist.View;
    }

更新 2

我发现的另一个选项(不使用CollectionViewSource)是创建一个新的public ObservableCollection&lt;ItemViewModel&gt; Mainlist { get; private set; } 并使用更多

            foreach (var item in Items.Take(limit))
            {
                //Items creation

                this.Mainlist.Add(new ItemViewModel()
                { LineOne = item });
            }

为了填充 ObservableCollection 并将列表框绑定到 Mainlist。这是有效的,但我认为这是不好的做法,因为这样我就有了重复的数据。有什么想法吗?

【问题讨论】:

    标签: c# windows-phone listbox-control


    【解决方案1】:

    您可以使用CollectionViewSource 并添加过滤逻辑来限制显示的项目数量。例如,如果您只想显示 100 个项目:

    var cvs = new CollectionViewSource();
    cvs.Source = myList;  //the raw list from the viewmodel
    cvs.Filter += (s, a) => a.Accepted = myList.IndexOf(a.Item) < 100;
    listBox2.ItemsSource = cvs.View;
    

    编辑:基于发布的代码

    当您设置Mainlist.Source 时,Mainlist.View 也会随之更改。所以在MainPage 构造函数中设置list.ItemsSource 是没有用的(此外,View 属性很可能在那个时候是null)。为了解决您的问题,您应该将以下行移至 MainViewModel 构造函数:

    this.Mainlist.Source = App.ViewModel.Items;
    this.Mainlist.Filter += (s, a) => 
                a.Accepted = App.ViewModel.Items.IndexOf((ItemViewModel)a.Item) < 10;
    

    这样,您只需设置一次SourceView 不会改变。

    【讨论】:

    • 感谢@Eren,但在我的情况下,“myList”是“App.ViewModel.Items”,它是可观察的集合,所以我在 IndeOf 表达式中遇到错误。
    • 这应该没问题,因为ObservableCollection 确实有一个IndexOf 方法。错误是什么?
    • 错误是参数1:无法从'object'转换为'ItemViewModel'
    • 我明白了。试试myList.IndexOf((ItemViewModel)a.Item)
    • 我刚刚用一些代码更新了我的第一篇文章。我试图创建一个新属性,我可以在其中存储这些项目并从视图绑定它。请看一看。
    【解决方案2】:

    我可能会保持简单,并更倾向于您原来的方法,做一些类似的事情:

    public MainViewModel()
    {
        _items = new ObservableCollection<ItemViewModel>();
    }
    
    public ObservableCollection<ItemViewModel> Items { 
        get {return _items;} 
        private set {_items = value;} 
    }
    private ObservableCollection<ItemViewModel> _items;
    
    private int _items_to_show_on_second_list = 10;
    
    public ObservableCollection<ItemViewModel> ItemsLimit { 
        get {return _items.Take(_items_to_show_on_second_list);} 
        private set {_items = value;} 
    }
    

    请注意,您可能不想在第二个 observable 集合上设置任何内容,这取决于您。

    好处是你没有改变你的逻辑,你仍然可以有可读的代码(使用Take()和一个有意义的变量名来避免magic number最终会被滥用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-17
      • 2023-03-06
      • 1970-01-01
      • 2012-05-25
      相关资源
      最近更新 更多