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