Заполнение модели, содержащей коллекцию, вручную - PullRequest
0 голосов
/ 22 марта 2019

Я пытаюсь заполнить модель для страницы в ASP.net Core, используя файловую систему.То, что у меня есть, в основном работает, но коллекция MusicFile не отображается правильно - все элементы показывают MusicFiles, которые должны быть связаны с последним элементом.Я не знаю, происходит ли это из-за того, что предыдущие элементы перезаписываются при заполнении модели или по какой-то причине не удается получить доступ к правильной коллекции в представлении.Я пытался использовать различные типы и различные типы циклов безрезультатно.Вот что у меня сейчас:

Модель:

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++;

        }

}

NBЯ довольно сильно упростил контроллер - предположим, что все переменные где-то определены.Заголовки отображаются правильно.Буду признателен за любую помощь!

1 Ответ

1 голос
/ 23 марта 2019

Проблема вызвана этим: musicFiles.Clear(); и это MusicFiles = musicFiles.Вы присваиваете переменную musicFiles, которая является ссылочным типом в c # (список), каждому MusicItem.Все они (музыкальные элементы) указывают на одну и ту же ссылку в списке, поэтому при вызове Clear каждый, у кого есть ссылка, «увидит» изменения.Точно так же, когда ваш цикл заканчивается и заполняет musicFiles, все MusicItems будут иметь одинаковые значения, так как они указывают на одну и ту же ссылку.

По сути, как работают переменные C #, так что хорошо, что вы понимаете это.Это не слишком сложно, вам просто нужно немного почитать / попрактиковаться, чтобы обдумать это.

Я настоятельно рекомендую вам прочитать эти две замечательные статьи, написанные Джоном Скитом Ссылки и значения и позже Передача параметров в 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);  
}
...