从 ViewModel 绑定到反向 ObservableCollection

Mos*_*ico 2 c# wpf xaml reverse mvvm

首先,我想说,在对 2 个不同的线程(如下所示)进行了几次研究之后,我决定发布这个问题,因为它完全不同。


因此,我想将ItemsControl视图中的an 绑定到一个属性以获取集合的反向版本。

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

<UserControl x:Class="NumberedMusicalScoresWriter.V.NotationGroupV" ...>
    ...
        <Grid>
            <ItemsControl ... 
                      ItemsSource="{Binding ReversedNotationVMs, Mode=OneWay}">
                ...
            </ItemsControl>
        </Grid>
    ...
</UserControl>
Run Code Online (Sandbox Code Playgroud)

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

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"); }
    }
}
Run Code Online (Sandbox Code Playgroud)

但是有这个错误(请参阅上面的错误注释以发现有问题的行):

无法转换类型为“d__a0 1[NumberedMusicalScoresWriter.VM.NotationVM]' to type 'System.Collections.ObjectModel.ObservableCollection1[NumberedMusicalScoresWriter.VM.NotationVM]”的对象。

我还尝试.ToList<NotationVM>()在倒车之前申请,并在每次主字段更新时创建一个新集合。但他们没有成功。

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

我也在这里这里阅读了一个关于它的问题,但它们都只提供了 xaml 解决方案,或者我不理解它们。我需要一台虚拟机。

谢谢。

Dan*_*ant 5

我同意上面的评论,即不同的方法可能会给您带来更好的结果,但要回答所问的问题:

NotationVMs.Reverse() 返回一个 IEnumerable。您不能将其直接转换为 ObservableCollection,因为即使 ObservableCollection 是 IEnumerable 的一种实现,它也恰好不是此特定函数返回的实现。您始终可以将 ObservableCollection 转换为 IEnumerable,但并非总是如此(所有正方形都是矩形,但并非所有矩形都是正方形)。

要返回反向集合,请尝试以下操作:

public ObservableCollection<NotationVM> ReversedNotationVMs
{
    get { return new ObservableCollection<NotationVM>(NotationVMs.Reverse()); }
}
Run Code Online (Sandbox Code Playgroud)

为了使其与 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");
}
Run Code Online (Sandbox Code Playgroud)

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