如何在 c# windows phone 中为每个文件名动态创建按钮?

how do you create buttons dynamically in c# windows phone one per file name?

我让我的应用程序在 SD 卡上创建一个名为 "RpgApp" 的文件夹 每当它创建一个字符时,它都会将该字符保存为该文件夹中的 html 文件(所有这些都有效,我在清单中具有 sdcard 访问权限,并且我已将 .html 添加到文件关联中)。这是重要信息,因为如果没有 sdcard 访问或文件关联,我会遇到未经授权的访问异常。

我现在想在堆栈面板中为每个文件创建一个按钮,这是我使用的代码

private async Task readFiles()
    {
        z.test.Clear();
        StorageFolder externalDevices = Windows.Storage.KnownFolders.RemovableDevices;
        StorageFolder folder = (await externalDevices.GetFolderAsync("RpgApp"));
        IReadOnlyList<StorageFile> fileList = await folder.GetFilesAsync();
        foreach (StorageFile file in fileList)
        {
            z.test.Add(file.Name);
        }
    }


    public async void buttonTest()
    {
        await readFiles();
        foreach (string name in z.test)
        {
            Button button1 = new Button();
            button1.Height = 75;
            button1.Content = name;
            button1.Name = name;
            testStackPanal.Children.Add(button1);
        }
    }

就ide而言没有错误。但是当我尝试 运行 buttonTest() 我得到两个 Systen.UnauthorizedAccessExceptions 这是我之前在创建文件时遇到的错误(通过将 .html 添加到文件关联来修复) RpgApp文件夹中没有其他文件,只有forename-surname.html

我一天中的大部分时间都在做这个工作,我坚持了任何 ide非常感谢

windows phone 通用应用程序(windows phone 8.1 及更高版本)

编辑 注释掉 await readFiles();然后向 z.test 添加字符串就可以完全正常工作,因此它与文件的读取相关联,但我们知道该应用程序可以访问文件夹和 html 文件,因为它可以创建文件夹和文件。

编辑2 抛出检查每一行,正是这一行导致了错误

StorageFolder folder = (await externalDevices.GetFolderAsync("RpgApp"));

在 readFiles 方法中,但那正是文件夹名称

在您的方法中,您正在调用在后台线程上执行的异步任务。当您尝试从后台线程访问在 UI 线程上创建的对象时,将抛出异常 Systen.UnauthorizedAccessExceptions 异常。

我会修改您的代码,以便在您读完文件后所有后续操作都在 UI 线程上完成。如(注未测试)

public async void buttonTest()
{
    await readFiles();
    Deployment.Current.Dispatcher.BeginInvoke(() =>
    {
        foreach (string name in z.test)
        {
            Button button1 = new Button();
            button1.Height = 75;
            button1.Content = name;
            button1.Name = name;
            testStackPanal.Children.Add(button1);
        }
    });
}

方法Deployment.Current.Dispatcher.BeginInvoke() { ... });旨在执行一个方法来操作UI。 UI 只能从 UI 线程进行操作。

上面的代码适用于 Windows Phone 8,但是 8.1 已经替换了一些方法,您可以使用从 WP8 访问 Dispatcher。

public async void buttonTest()
{
    await readFiles();
    CoreDispatcher dispatcher = CoreWindow.GetForCurrentThread().Dispatcher;
    await dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
    {
        foreach (string name in z.test)
        {
            Button button1 = new Button();
            button1.Height = 75;
            button1.Content = name;
            button1.Name = name;
            testStackPanal.Children.Add(button1);
        }
    });
}

编辑

好的..所以我创建了自己的测试环境来解决这个问题,但我没有走上正确的道路。原来问题是正确读取 SD 卡文件。这是通过以下步骤在模拟器上完成的。

1) 打开包清单并进入 Declarations 选项卡。从这里我创建了一个新的文件类型关联(如下图所示)

2) 转到Capabilities 选项卡并确保您选择了Removable Storage(以便我们可以读取存储)。

现在,只有当我更改了从设备读取文件的方式时,下一部分才有效。我们没有尝试加载一个文件夹,而是遍历所有文件夹,但在尝试查询特定文件夹时遇到了相同的“访问被拒绝”错误(不确定原因)。我修改了读取文件的代码,以遍历所有文件夹和文件,并根据需要添加这些文件夹和文件。

async Task readAllFiles(StorageFolder folder)
{
    var files =await folder.GetFilesAsync();
    foreach (var file in files)
    {
        test.Add(file.Name);
    }

    var folders = await folder.GetFoldersAsync();
    foreach (var child in folders)
        await readAllFiles(child);
}


public async void buttonTest()
{
    test.Clear();
    StorageFolder externalDevices = Windows.Storage.KnownFolders.RemovableDevices;
    var folders = await externalDevices.GetFoldersAsync();
    foreach (var folder in folders)
    {
        await readAllFiles(folder);
    }
    CoreDispatcher dispatcher = CoreWindow.GetForCurrentThread().Dispatcher;
    await dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
    {
        foreach (string name in test)
        {
            Button button1 = new Button();
            button1.Height = 75;
            button1.Content = name;
            button1.Name = name;

            testStackPanal.Children.Add(button1);
        }
    });
}

您会注意到 readAllFiles 方法是从父文件夹递归调用自身的。另外,我刚刚为文件名创建了一个简单的 List<string> test。这似乎有效。

现在,如果您真的只想读取 RpgApp 文件夹,您可以按以下方式修改代码。请注意,如果文件夹为 Null 或文件夹名称为 RpgApp,我现在 return false。如果您确定 RpgApp 文件夹将始终位于可移动存储的根目录中,我们甚至可以对此进行更多更改。

async Task<bool> continueToReadAllFiles(StorageFolder folder)
{
    if (folder == null)
        return false;
    if (folder.Name.Equals("RpgApp", StringComparison.CurrentCultureIgnoreCase))
    {
        var files = await folder.GetFilesAsync();
        foreach (var file in files)
        {
            test.Add(file.Name);
        }
        return false;
    }
    var folders = await folder.GetFoldersAsync();
    foreach (var child in folders)
        if (!await continueToReadAllFiles(child))
            return false;

    return true;
}


public async void buttonTest()
{
    test.Clear();
    StorageFolder externalDevices = Windows.Storage.KnownFolders.RemovableDevices;
    var folders = await externalDevices.GetFoldersAsync();
    foreach (var folder in folders)
    {
        if (!await continueToReadAllFiles(folder))
            break;
    }
    //.... commented out
}