.net 如何使一个类保存两种类型的文件,使它们相互链接?

6psbrbz9  于 2022-12-05  发布在  .NET
关注(0)|答案(2)|浏览(83)

我试图制作一个表,列出两种类型的链接在一起的文件。一种是.mp3,另一种是.txt文件。我希望这些文件链接在一起,这样当foreach循环通过它们时,共享相同名称的文件共享一行。这样可以播放mp3文件,并打开相应的文本文件。

App.razor页面有一个表,显示了文件夹中的所有文件,但它没有考虑两种类型的文件是否共享相同的名称。有人能帮助如何创建一个类,将文件链接在一起,以便在表中调用它们吗?

下面是代码。

<table class="table table-striped mb-0">
    <thead>
    <tr>
        <th scope="col">Name</th>
        <th scope="col">Actions</th>
    </tr>
    </thead>
    <tbody>
        @foreach (var fileGroup in myFilesGroupedAndSorted)
        {
            <Mp3 FileGroup=fileGroup />
        }
    </tbody>
</table>

@code {
    readonly List<TextFile> textList = new();
    private string audioUrl { get; set; }
    readonly string audioFolderName = "textFiles";

    protected override void OnInitialized()
    {
        var path = $"{env.WebRootPath}\\{audioFolderName}\\"; //System.IO.Path.ChangeExtension(@"wwwroot\textFiles\", null); 
        var files = new DirectoryInfo(path).GetFiles();

        foreach (var file in files)
        {
            textList.Add(new TextFile
            {
                Name = file.Name,
                Url = $"/textFiles/{file.Name}",
                Path = file.FullName
            });
        }
    }

    IEnumerable<IGrouping<string, TextFile>> myFilesGroupedAndSorted
            => textList.GroupBy(file => GetPathWithoutExtension(file.Path))
                     .OrderBy(group => group.Key);

    private string GetPathWithoutExtension(string path)
    {
        return System.IO.Path.ChangeExtension(path, null);
    }
}

Mp3.razor

<tr>
    <td>
        @FileGroup.Key
    </td>
    <td>
        @if (Mp3 is not null)
        {
            <span @onclick="() => PlayAudio(Mp3.Url)"
              class="text-primary oi oi-play-circle me-2" aria-hidden="true" role="button">
            </span>
            
        }
        @if (Text is not null)
        {
            <span @onclick="() => openTextFile(Text)">
                <button>Open</button>
            </span>
        }
    </td>
</tr>
@code {
    readonly List<TextFile> textList = new();
    private string audioUrl { get; set; }

    [Parameter]
    public IGrouping<string, TextFile> FileGroup { get; set; } = default!;

    TextFile? Text => FileGroup.FirstOrDefault(file => Path.GetExtension(file.Path).ToLower() == "txt");
    TextFile? Mp3 => FileGroup.FirstOrDefault(file => Path.GetExtension(file.Path).ToLower() == "mp3");

    private void PlayAudio(string url)
    {
        audioUrl = url;
        InvokeAsync(StateHasChanged);
    }

    private async Task DeleteAudio(TextFile text)
    {
        ...
    }

    public void openTextFile(TextFile text)
    {
        ...
    }
}

如果我删除TextFile? Text => fileGroup.FirstOrDefault(file => Path.GetExtension(file.Path).ToLower() == "txt");TextFile? Mp3 => fileGroup.FirstOrDefault(file => Path.GetExtension(file.Path).ToLower() == "mp3");以及它们在表中的提及,它的功能。

@using System.Linq
@inject IWebHostEnvironment env

<table class="table table-striped mb-0">
    <thead>
    <tr>
        <th scope="col">Name</th>
        <th scope="col">Actions</th>
    </tr>
    </thead>    
    <tbody>
        @foreach (var fileGroup in myFilesGroupedAndSorted)
        {
            <tr>
                <td>
                    @fileGroup.Key
                </td>
                <td>
                    @if (Mp3 is not null)
                    {
                        <span @onclick="() => PlayAudio(Mp3.Url)"
                            class="text-primary oi oi-play-circle me-2" aria-hidden="true" role="button">
                        </span>
                        
                    }
                    @if (Text is not null)
                    {
                            <span @onclick="() => openTextFile(Text)"
                            ><button>Open</button>
                            </span>
                    }
                </td>
            </tr> 
        }
  </tbody>
</table>

@code {
    List<TextFile> textList = new();
    readonly string audioFolderName = "textFiles";

    public IGrouping<string, TextFile> fileGroup { get; set; } = default!;

    TextFile? Text => fileGroup.FirstOrDefault(file => Path.GetExtension(file.Path).ToLower() == "txt");
    TextFile? Mp3 => fileGroup.FirstOrDefault(file => Path.GetExtension(file.Path).ToLower() == "mp3");

    protected override void OnInitialized()
    {
        var path = $"{env.WebRootPath}\\{audioFolderName}\\"; 
        var files = new DirectoryInfo(path).GetFiles();

        foreach (var file in files)
        {
            textList.Add(new TextFile
                {
                    Name = file.Name,
                    Url = $"/textFiles/{file.Name}",
                    Path = file.FullName
                });
        }
    }

    IEnumerable<IGrouping<string, TextFile>> myFilesGroupedAndSorted
        => textList.GroupBy(file => GetPathWithoutExtension(file.Path))
                 .OrderBy(group => group.Key);

    private string GetPathWithoutExtension(string path)
    {
        return System.IO.Path.ChangeExtension(path, null);
    }

    private string audioUrl { get; set; }

    private void PlayAudio(string url)
    {
        audioUrl = url;
        InvokeAsync(StateHasChanged);
    }

    List<EditTextFiles> items = new();

    public void openTextFile(TextFile text){ }
}
46scxncf

46scxncf1#

使用LinqGroupBy

@foreach(var fileGroup in myFilesGroupedAndSorted)
{
    <h3>@fileGroup.Key</h3>
    @foreach(var file in fileGroup.OrderBy( file => file.Path))
    {
        <div>@file.Path</div>
    }
}

@code {
    // without access to your folder I generated random data.
    List<TextFile> myList = new List<TextFile>
    {
        new TextFile { Name = "", Path = "some-path\\SomeFile1.txt", Url = "" },
        new TextFile { Name = "", Path = "some-path\\SomeFile2.txt", Url = "" },
        new TextFile { Name = "", Path = "some-path\\SomeFile3.txt", Url = "" },
        new TextFile { Name = "", Path = "some-path\\SomeFile4.txt", Url = "" },
        new TextFile { Name = "", Path = "some-path\\SomeFile5.txt", Url = "" },
        new TextFile { Name = "", Path = "some-path\\SomeFile6.txt", Url = "" },
        new TextFile { Name = "", Path = "some-path\\SomeFile1.mp3", Url = "" },
        new TextFile { Name = "", Path = "some-path\\SomeFile2.mp3", Url = "" },
        new TextFile { Name = "", Path = "some-path\\SomeFile3.mp3", Url = "" },
        new TextFile { Name = "", Path = "some-path\\SomeFile4.mp3", Url = "" },
        new TextFile { Name = "", Path = "some-path\\SomeFile5.mp3", Url = "" },
        new TextFile { Name = "", Path = "some-path\\SomeFile6.mp3", Url = "" },
    };

    IEnumerable<IGrouping<string, TextFile>> myFilesGroupedAndSorted
        => myList.GroupBy(file => GetPathWithoutExtension(file.Path))
                 .OrderBy(group => group.Key);

    private string GetPathWithoutExtension(string path)
    {
        return System.IO.Path.ChangeExtension(path, null);
    }
}

通过测试每个文件扩展名,处理每个组应该是微不足道的。我会做一个子组件来传递IGrouping<string, TextFile>作为参数,以简化逻辑...
Mp3.Razor
第一次

oyxsuwqo

oyxsuwqo2#

你需要“透视”表,也就是说,把一个列表转换成一个表。LINQ可以用来做这个。看看this answer。你会有属性bool HasMp3bool HasTxt,而不是“Jan”和“Feb”,以及相应的Where子句。类似于:

var files = new DirectoryInfo(path).GetFiles();

textList.AddRange(files
    .GroupBy(c => Path.ChangeExtension(c.Name, null))
    .Select(g => new TextFile() {
        Name = g.Key,
        Url = $"/textFiles/{g.Key}",
        HasMp3 = g.Any(c => Path.GetExtension(c) == ".mp3"),
        HasTxt = g.Any(c => Path.GetExtension(c) == ".txt"),
    }));

使用这两个bool属性,您可以在相应文件不存在时隐藏按钮。Url属性没有扩展名。您必须在每个相应函数中附加每个相应的扩展名。

相关问题