我正在尝试使用文件系统为ASP.net Core中的页面填充模型。我的大部分工作正常,但是MusicFile集合无法正确显示-所有项目均显示应与最后一个项目相关联的MusicFiles。我不知道这是否是因为在填充模型时先前的项目被覆盖,还是由于某种原因它无法在视图中访问正确的集合。我尝试使用各种类型和各种类型的for循环都无济于事。这是我目前所拥有的:
型号:
public class MusicItem
{
public string Name { get; set; }
public List<MusicFile> MusicFiles { get; set; }
}
public class MusicFile
{
public string Url { get; set; }
public string Display { get; set; }
}
控制器(简体):
public IActionResult Files(string folder)
{
List<MusicItems> MusicList = new List<MusicItems>();
List<MusicFile> musicFiles = new List<MusicFile>();
MusicFile musicFile;
..
foreach (string folderName in folders)
{
if (musicFiles.Count>0) { musicFiles.Clear(); }
for each file in files
{
...
musicFile = new MusicFile { Display = display, Url = MakeVirtualPath(fileName) };
musicFiles.Add(musicFile);
}
MusicList.Add(new MusicItems { Name = folderName, MusicFiles = musicFiles });
}
return View(MusicList);
}
查看:
@model List<Web.Areas.Admin.Models.MusicItem>
@foreach (var Musicitem in Model)
{
int id = 0;
<h3>@Html.DisplayFor(modelItem => Musicitem.Name)</h3>
@for (int i = 0; i < Musicitem.MusicFiles.Count; i++)
{
if (id != 0)
{<span> | </span>}
<a href="@Musicitem.MusicFiles[i].Url">@Musicitem.MusicFiles[i].Display</a>
id++;
}
}
注意:我已经大大简化了控制器-假设所有变量都在某个地方定义。标题正确显示。我将不胜感激!
答案 0 :(得分:1)
此问题是由以下原因引起的:musicFiles.Clear();
和此MusicFiles = musicFiles
。您正在为每个musicFiles
分配MusicItem
变量,它是c#(列表)中的引用类型。所有这些(音乐项目)都指向列表的相同参考,因此,当您调用Clear
时,拥有参考的每个人都会“看到”更改。同样,当循环结束并填充musicFiles
时,所有MusicItems
将具有相同的值,因为它们指向相同的引用。
从本质上讲,这是C#变量的工作方式,因此,了解这一点很好。它并不太复杂,您只需要阅读/练习即可将其包裹住。
我强烈建议您阅读Jon Skeet References and Values和后来的Parameter passing in C#撰写的这两篇很棒的文章。我认为,他的解释是我在该主题上见过的最好的解释之一。它简洁明了。但是请确保您得到它,因为这对于C#的工作方式至关重要,它将使您的生活变得更轻松/更好,成为开发人员。
解决您的问题:
您可以通过将代码稍微更改为以下内容来解决该问题:
public IActionResult Files(string folder)
{
List<MusicItems> MusicList = new List<MusicItems>();
foreach (string folderName in folders)
{
// creates an item with an empty list of files
var musicItem = new MusicItems { Name = folderName, MusicFiles = new List<MusicFile>() };
foreach(var file in files)
{
// create the file
musicFile = new MusicFile { Display = display, Url = MakeVirtualPath(fileName) };
// add the file to the item, declared in the loop.
musicItem.MusicFiles.Add(musicFile);
}
MusicList.Add(musicItem);
}
return View(MusicList);
}