如何在 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
}
我让我的应用程序在 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
}