如何限制observablecollection数据类型列表框中的项目数?

时间:2012-07-07 13:49:13

标签: c# windows-phone listbox-control

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

更新

viewmodel

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<ItemViewModel> Mainlist { get; private set; }并再使用一个

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

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

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

2 个答案:

答案 0 :(得分:2)

您可以使用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。因此,在list.ItemsSource构造函数中设置MainPage是没用的(此外,View属性最有可能是null。为了解决您的问题,您应该将以下这些行移至MainViewModel构造函数:

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

这样,您只需设置Source一次,View不会更改。

答案 1 :(得分:0)

我可能会保持简单,并且更多地朝着原始方法的方向前进,做类似的事情:

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;} 
}

请注意,您可能不希望在第二个可观察集合上设置任何内容,由您决定。

好处是您不会改变逻辑,您仍然可以使用Take()和有意义的变量名称来避免最终被滥用的magic number