繁体   English   中英

如何获取另一个ObservableCollection列表中的ObservableCollection列表项?

[英]How to get an ObservableCollection list item which inside another ObservableCollection list?

我有一个类PlayerVM.cs ,它具有一个属性:

public ObservableCollection<PlaylistVM> PlayLists
        {
            get { return _playLists; }
            set { _playLists = value; }
        }

PlaylistVM.cs也有其自己的集合:

public ObservableCollection<CompositionVM> Songs
        {
            get
            {
                return _songs;
            }
            set
            {
                _songs = value;
            }
        }

这样,我的PlayerVM就有一个播放列表,每个播放列表都有自己的歌曲列表。 我需要显示按字母顺序排序的歌曲列表。 但是我不想更改它们在ObservableCollections中的顺序,我只想在GUI中更改它们的顺序(仅按字母顺序显示它们,而不更改实际顺序)。 我是wpf(和xaml)的新手,今天我只学习了如何显示按字母顺序排列的播放列表名称。 我正在通过代码:

<Window x:Class="Player_beta.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:Player_beta">
    <Window.Resources>
        <CollectionViewSource Source="{Binding PlayLists}"  x:Key="plView"><!--here I would like to get access to PlayLists.Songs-->
            <CollectionViewSource.SortDescriptions>
                <scm:SortDescription PropertyName="plNAME"/> <!--and here I would like to get NAME(that property of 'Songs' which contains songtitle) instead of plNAME - name of playlist)-->
            </CollectionViewSource.SortDescriptions>
        </CollectionViewSource>
 </Window.Resources>
<!-- etc...-->
            <TreeView Name="treeCategories" ItemsSource="{Binding Source={StaticResource plView}}" >
<TreeView.ItemTemplate>
                    <HierarchicalDataTemplate ItemsSource="{Binding Songs}">
                                <TextBlock Text="{Binding plNAME}"/> <!-- <-- here is where the name of PLAYLIST shows-->
                        <HierarchicalDataTemplate.ItemTemplate >
                            <DataTemplate >
                                    <TextBlock Text="{Binding NAME}"/> <!-- <-- here is where the name of song shows-->
                                </Grid>
                            </DataTemplate>
                        </HierarchicalDataTemplate.ItemTemplate>
                    </HierarchicalDataTemplate>
                </TreeView.ItemTemplate>
            </TreeView>

您可以在PlaylistVM.cs类中添加ICollectionView实例并与其绑定。 这样,原始列表也不会受到影响。

private ICollectionView songsView;
public ICollectionView SongsView
{
    get
    {
        if (songsView== null)
        {
            songsView= CollectionViewSource.GetDefaultView(Songs);
            songsView.SortDescriptions.Add(new SortDescription("Name",
                                               ListSortDirection.Ascending));
        }
        return songsView;
    }
}

在XAML中:

<HierarchicalDataTemplate ItemsSource="{Binding SongsView}">

您可以做的是,可以将CollectionView属性添加到PlaylistVM类中:

public CollectionView songsCollectionView;
public CollectionView SongsCollectionView
{
    get 
    {
        if (songsCollectionView == null)
        {
            songsCollectionView  = new CollectionView(Songs);
            songsCollectionView.SortDescriptions.Add(new SortDescription("plNAME", ListSortDirection.Ascending));
        }

        return songsCollectionView;
    }
}

然后您可以像这样绑定您的xaml:

<HierarchicalDataTemplate ItemsSource="{Binding SongsCollectionView}">

这应该满足您在GUI中显示排序后的歌曲而不更改原始集合的要求。

这不是最有效的方法,但是可以完成工作。 请注意,它不会检测任何歌曲的名称是否已更改。 每当添加或删除歌曲时,它还将在UI中重建整个列表。

public class PlaylistVM: System.ComponentModel.INotifyPropertyChanged
{
    public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;

    private ObservableCollection<CompositionVM> _songs;
    public ObservableCollection<CompositionVM> Songs
    {
        get
        {
            return _songs;
        }
        set
        {
            if(_songs != value)
            {
                //if old value not null, unhook event
                if (_songs != null)
                {
                    _songs.CollectionChanged -= FireSongsChanged;
                }
                //change the value
                _songs = value;

                //if new value !=null, then attach handlers.
                if (_songs != null)
                {
                    _songs.CollectionChanged += FireSongsChanged;
                }

                //this will fire the 
                FireSongsChanged(null, null);
            }

        }
    }

    void FireSongsChanged(object sender, EventArgs e)
    {
        //the collection of songs has changed, tell UI that it needs to requery the list of ordered songs.
        var ev = this.PropertyChanged;
        if (ev != null)
        {
            ev(this, new System.ComponentModel.PropertyChangedEventArgs("OrderedSongs"));
        }
    }

    //set the UI to bind to the following list of the songs. ordered by name.
    public IEnumerable<CompositionVM> OrderedSongs
    {
        get
        {
            return Songs.OrderBy(song => song.Name);
        }
    }


}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM