从ViewModel绑定到Reversed ObservableCollection

时间:2014-09-26 16:27:10

标签: c# wpf xaml mvvm reverse

首先,我想说在经过两次不同线程的研究后(如下所示),我决定发布这个问题,因为它有很大的不同。


所以,我希望将ItemsControl从我的视图绑定到属性以获得集合的反转版本。

我有这个观点(为了清晰起见而修剪):

<UserControl x:Class="NumberedMusicalScoresWriter.V.NotationGroupV" ...>
    ...
        <Grid>
            <ItemsControl ... 
                      ItemsSource="{Binding ReversedNotationVMs, Mode=OneWay}">
                ...
            </ItemsControl>
        </Grid>
    ...
</UserControl>

而且,我有这个视图模型(为了清晰起见而修剪):

public class NotationGroupVM : ...
{
    ...

    public ObservableCollection<NotationVM> ReversedNotationVMs
    {
        get { return (ObservableCollection<NotationVM>)NotationVMs.Reverse(); //ERROR!! }
    }

    public ObservableCollection<NotationVM> NotationVMs
    {
        get { return _notationVMs; }
        set { _notationVMs = value; NotifyPropertyChanged("NotationVMs"); NotifyPropertyChanged("ReversedNotationVMs"); }
    }
}

但是出现了这个错误(请参阅上面的错误评论以发现有问题的行):

  

无法投射类型的对象   &#39; {d__a0 {1}} 1 [NumberedMusicalScoresWriter.VM.NotationVM]&#39;

我还尝试在撤消之前应用1[NumberedMusicalScoresWriter.VM.NotationVM]' to type 'System.Collections.ObjectModel.ObservableCollection,并在每次主要字段更新时制作新的集合。但他们没有成功。

我还需要保持逆转与未反转的同步。不只是一次回复

我还阅读了有关herehere的问题,但它们都提供了xaml解决方案,或者我不理解它们。我需要一台VM。

感谢。

2 个答案:

答案 0 :(得分:3)

我同意上述评论,不同的方法可能会给你一个更好的结果,但要回答问题:

NotationVMs.Reverse()返回一个IEnumerable。你不能将它直接转换为ObservableCollection,因为即使ObservableCollection是IEnumerable的一个实现,它也不是这个特定函数返回的实现。你总是可以将一个ObservableCollection强制转换为IEnumerable,但反之并非总是如此(所有正方形都是矩形,但并非所有矩形都是正方形)。

要返回反向收藏,请尝试以下操作:

public ObservableCollection<NotationVM> ReversedNotationVMs
{
    get { return new ObservableCollection<NotationVM>(NotationVMs.Reverse()); }
}

为了使其与NotationVMs集合保持同步,您需要关注集合更改事件:

public ObservableCollection<NotationVM> NotationVMs
{
    get { return _notationVMs; }
    set 
    { 
        if (_notationVMs != null)
        {
            _notationVMs.CollectionChanged -= OnNotationVMsCollectionChanged;
        }
        _notationVMs = value;
        if (_notationVMs != null)
        {
            _notationVMs.CollectionChanged += OnNotationVMsCollectionChanged;
        } 
        NotifyPropertyChanged("NotationVMs"); 
        NotifyPropertyChanged("ReversedNotationVMs");
    }
}

private void OnNotationVMsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
     NotifyPropertyChanged("ReversedNotationVMs");
}

这会将NotationVMs中的更改同步到ReversedNotationVMs,但不是相反。由于您对ReversedNotationVMs的绑定是一种方式,这应该足够了。

答案 1 :(得分:3)

就在我的脑海里,也许不是你的完整答案。假设我们有一个按ID排序的集合

  public OberservableCollection<MyNotation> MySource {get;set;}

然后我可以创建默认视图和反向视图

 public ICollectionView MyViewOrderedByID {get;set;}
 public ICollectionView MyViewOrderedByIDReversed {get;set;}

 //ctor
 this.MyViewOrderedByID = CollectionViewSource.GetDefaultView(this.MySource);//default
 this.MyViewOrderedByID.SortDescriptions.Add(new SortDescription("ID", ListSortDirection.Ascending));

 this.MyViewOrderedByIDReversed= new CollectionViewSource{ Source=this.MySource}.View;//new one
 this.MyViewOrderedByIDReversed.SortDescriptions.Add(new SortDescription("ID", ListSortDirection.Descending));

XAML

<ItemsControl ItemsSource="{Binding MyViewOrderedByID}"/>
<ItemsControl ItemsSource="{Binding MyViewOrderedByIDReversed}"/>

然后在Source更改时查看更改