2

这是怎么回事。我有一个视图模型,我在其中调用一个 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<ItemViewModel> Mainlist { get; private set; }并再使用一个

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

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

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

4

2 回答 2

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.ItemsSourceMainPage构造函数中设置 是没用的(此外,无论如何,该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不会更改。

于 2012-07-07T14:18:39.457 回答
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最终会被滥用。

于 2014-08-25T03:23:49.873 回答