Как ограничить количество элементов в списке данных с наборами данных?

Вот как это происходит. У меня есть модель представления, где я вызываю веб-клиента и заполняю наблюдаемую коллекцию элементами. Мне нужно иметь два разных списка на двух разных страницах, но с одним и тем же ItemsSource из viewmodel. Как я могу ограничить количество элементов в одном из двух списков, не влияя на другой? Я попытался использовать.Take(limit) в 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 ответа

Вы можете использовать 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 не меняется

Я бы, вероятно, оставил это простым и направился бы в направлении вашего первоначального подхода, делая что-то вроде:

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

Обратите внимание, что вы можете не захотеть устанавливать что-либо на 2-й наблюдаемой коллекции, в зависимости от вас.

Преимущества в том, что вы не меняете свою логику, вы все равно можете иметь читаемый код (используя Take() и значимое имя переменной, чтобы избежать magic number это в конечном итоге будет злоупотреблено.

Другие вопросы по тегам