如何迭代 wpf TreeView 的项目,添加新项目(如果它们尚不存在)和/或作为现有项目的子项?
我正在为我的论文开发一个程序,希望完成后能够让您使用标签数据对音乐文件进行排序。目前我有一个 wpf 树视图,我想显示程序找到的所有音乐的列表,按艺术家>专辑>标题排序。我有一个使用 taglib# 收集的标签文件列表,我可以使用它为每个轨道创建 TreeViewItems,然后将它们添加到 TreeView。问题是我似乎无法避免添加艺术家/专辑的重复项,而不是将曲目添加为已添加的艺术家/专辑的子项。我一直在尝试使用 foreach 来迭代项目,如果标题(艺术家姓名)与要添加的新艺术家的标题匹配,则移至专辑并将其添加为当前项目的子项,然后执行以下操作同样检查专辑并继续检查曲目标题等。我一直没有感到高兴,因为即使标题完全匹配,它们似乎总是以不匹配的形式返回,因此添加了一个复制艺术家。
我对使用 TreeViews 完全陌生,所以我不确定我是否会以最好的方式解决这个问题,或者这是否只是我的逻辑中的一个缺陷或其他什么,所以任何帮助将不胜感激。
附件是我用来创建和检查项目的代码。
public void PopulateTreeView(TreeView searchResults)
{
foreach (TagLib.File tagFile in tagFiles)
{
TreeViewItem Artist;
TreeViewItem Album;
TreeViewItem Title;
//creating the TreeViewItems
Artist = SetArtistsName(tagFile);
Album = SetAlbumName(tagFile);
Title = SetTrackName(tagFile);
//adding them to TreeView
AddArtistToTreeView(tagFile, searchResults, Artist, Album, Title);
}
}
创建 TreeViewItems 的函数
private TreeViewItem SetArtistsName(TagLib.File tagFile)
{
TreeViewItem Artist = new TreeViewItem();
if (tagFile.Tag.AlbumArtists.Length == 0)
{
Artist.Header = "Unknown Artist";
return Artist;
}
else
{
Artist.Header = tagFile.Tag.AlbumArtists[0].ToString();
return Artist;
}
}
private TreeViewItem SetAlbumName(TagLib.File tagFile)
{
TreeViewItem Album = new TreeViewItem();
Album.Header = tagFile.Tag.Album;
return Album;
}
private TreeViewItem SetTrackName(TagLib.File tagFile)
{
TreeViewItem Track = new TreeViewItem();
Track.Header = tagFile.Tag.Title;
return Track;
}
以及添加到 TreeView/检查重复项的代码
private void AddArtistToTreeView(TagLib.File tagFile, TreeView searchResults, TreeViewItem Artist, TreeViewItem Album, TreeViewItem Title)
{
if (searchResults.Items.Count == 0)
{
searchResults.Items.Add(Artist);
Artist.Items.Add(Album);
Album.Items.Add(Title);
}
else
{
artistFlag = CheckArtist(searchResults, Artist);
switch (artistFlag)
{
case 0:
searchResults.Items.Add(Artist);
if (Artist.Items.Count == 0)
{
Artist.Items.Add(Album);
Album.Items.Add(Title);
}
break;
case 1:
albumFlag = CheckAlbum(Artist, Album);
switch (albumFlag)
{
case 0:
Artist.Items.Add(Album);
if (Album.Items.Count == 0)
{
Album.Items.Add(Title);
}
break;
case 1:
trackFlag = CheckTitle(Album, Title);
break;
case 2:
break;
}
break;
case 2:
break;
}
}
}
private int CheckArtist(TreeView searchResults, TreeViewItem Artist)
{
if (searchResults.Items.Count == 0)
{
return 0;
}
else
{
foreach (TreeViewItem tvi in searchResults.Items)
{
if (tvi.Header.ToString() != Artist.Header.ToString())
{
return 0;
}
else
{
return 1;
}
}
return 2;
}
}
private int CheckAlbum(TreeViewItem Artist, TreeViewItem Album)
{
if (Artist.Items.Count == 0)
{
return 0;
}
else
{
foreach (TreeViewItem tvi in Artist.Items)
{
if (tvi.Header.ToString() != Album.Header.ToString())
{
return 0;
}
else
{
return 1;
}
}
return 2;
}
}
private int CheckTitle(TreeViewItem Album, TreeViewItem Title)
{
if (Album.Items.Count == 0)
{
return 0;
}
else
{
foreach (TreeViewItem tvi in Album.Items)
{
if (tvi.Header.ToString() != Title.Header.ToString())
{
return 0;
}
else
{
return 1;
}
}
return 2;
}
}
抱歉,这有点冗长,但再次强调,任何帮助将不胜感激:) 谢谢
I'm working on a program for my dissertation that hopefully, when finished will enable you to sort music files using the tag data. At the moment I have a wpf tree view that I want to display a list of all the music the program has found sorted by Artist>Album>Title. I have a list of tag files collected using taglib# that I can use to create TreeViewItems for each track and can then add them to the TreeView. The problem is that I cant seem to avoid adding duplicates of artists/albums instead of adding the track as a child of the already added artist/album. I have been trying to use foreach to iterate through the items and if the header(artist name) matches the header of the new artist to be added, then move onto the album instead and add that as a child of the current item, then do the same check for albums and move on to the track title and so forth. I have been having little joy though as even if the headers match exactly they always seem to return as non-matching and thus a dupliacte artist is added.
I'm totally new to using TreeViews so I'm not sure I'm going about this in the best way, or if its just a flaw in my logic or whatever so any help would be greatly appreciated.
Attatched is the code i'm using to create and check the items.
public void PopulateTreeView(TreeView searchResults)
{
foreach (TagLib.File tagFile in tagFiles)
{
TreeViewItem Artist;
TreeViewItem Album;
TreeViewItem Title;
//creating the TreeViewItems
Artist = SetArtistsName(tagFile);
Album = SetAlbumName(tagFile);
Title = SetTrackName(tagFile);
//adding them to TreeView
AddArtistToTreeView(tagFile, searchResults, Artist, Album, Title);
}
}
The functions that create the TreeViewItems
private TreeViewItem SetArtistsName(TagLib.File tagFile)
{
TreeViewItem Artist = new TreeViewItem();
if (tagFile.Tag.AlbumArtists.Length == 0)
{
Artist.Header = "Unknown Artist";
return Artist;
}
else
{
Artist.Header = tagFile.Tag.AlbumArtists[0].ToString();
return Artist;
}
}
private TreeViewItem SetAlbumName(TagLib.File tagFile)
{
TreeViewItem Album = new TreeViewItem();
Album.Header = tagFile.Tag.Album;
return Album;
}
private TreeViewItem SetTrackName(TagLib.File tagFile)
{
TreeViewItem Track = new TreeViewItem();
Track.Header = tagFile.Tag.Title;
return Track;
}
And the code for adding to the TreeView/Checking for duplicates
private void AddArtistToTreeView(TagLib.File tagFile, TreeView searchResults, TreeViewItem Artist, TreeViewItem Album, TreeViewItem Title)
{
if (searchResults.Items.Count == 0)
{
searchResults.Items.Add(Artist);
Artist.Items.Add(Album);
Album.Items.Add(Title);
}
else
{
artistFlag = CheckArtist(searchResults, Artist);
switch (artistFlag)
{
case 0:
searchResults.Items.Add(Artist);
if (Artist.Items.Count == 0)
{
Artist.Items.Add(Album);
Album.Items.Add(Title);
}
break;
case 1:
albumFlag = CheckAlbum(Artist, Album);
switch (albumFlag)
{
case 0:
Artist.Items.Add(Album);
if (Album.Items.Count == 0)
{
Album.Items.Add(Title);
}
break;
case 1:
trackFlag = CheckTitle(Album, Title);
break;
case 2:
break;
}
break;
case 2:
break;
}
}
}
private int CheckArtist(TreeView searchResults, TreeViewItem Artist)
{
if (searchResults.Items.Count == 0)
{
return 0;
}
else
{
foreach (TreeViewItem tvi in searchResults.Items)
{
if (tvi.Header.ToString() != Artist.Header.ToString())
{
return 0;
}
else
{
return 1;
}
}
return 2;
}
}
private int CheckAlbum(TreeViewItem Artist, TreeViewItem Album)
{
if (Artist.Items.Count == 0)
{
return 0;
}
else
{
foreach (TreeViewItem tvi in Artist.Items)
{
if (tvi.Header.ToString() != Album.Header.ToString())
{
return 0;
}
else
{
return 1;
}
}
return 2;
}
}
private int CheckTitle(TreeViewItem Album, TreeViewItem Title)
{
if (Album.Items.Count == 0)
{
return 0;
}
else
{
foreach (TreeViewItem tvi in Album.Items)
{
if (tvi.Header.ToString() != Title.Header.ToString())
{
return 0;
}
else
{
return 1;
}
}
return 2;
}
}
Sorry, this is a bit of a lengthy one but again, any help would be greatly appreciated :) Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
对我来说,这似乎是一种混乱且容易出错的方法,您尝试做的事情听起来最好由
CollectionViews
,它允许您对项目进行分组,无需手动创建所有必要的父容器。在 WPF 中,您应该只在代码中最小程度地处理 UIElements,大多数事情都可以通过 模板化。因此,您可以绑定所有TreeViewItems
到CollectionViews
,每个视图按另一个属性分组。This seems like a messy and error prone approach to me, what you try to do sounds like it would be best handled by
CollectionViews
, which allow you to group your items without manually creating all the necessary parent containers. In WPF you should only deal with the UIElements to a minimum extent in code, most of the things can be handled via templating in XAML. So you could bind all yourTreeViewItems
toCollectionViews
, each grouping by another property.