【问题标题】:Binding data from harddrive in Windows Store App在 Windows 应用商店应用中从硬盘绑定数据
【发布时间】:2014-03-04 21:09:43
【问题描述】:

使用 c#、VS 2013、Windows Store App

我有一些 Json 文件,其中包含有关某些事件的信息,在此文件中,用户可以存储一些数据,以及其中一个数据 - 事件图像的路径,例如:

{"Events":
[
  {
    "UniqueId": "Day-1-Item-1",
    "Name": "Item Title: 1",
    "Place": "Item Subtitle: 1",
    "Description": "Event 1",
    "Start" : "2,25,2014,2,14",
    "End" : "2,25,2014,16,44",
    "ImagePath" : "Assets/appbar.calendar.png"
  },
  {
    "UniqueId": "Day-1-Item-2",
    "Name": "Item Title: 1",
    "Place": "Item Subtitle: 1",
    "Description": "Event 1",
    "Start" : "2,25,2014,2,14",
    "End" : "2,25,2014,16,44",
    "ImagePath" : "D:\\Pictures\\Abstract\\8.jpg"
  }
]

}

所以我将所有这些信息绑定到 UI(使用 XAML)并得到如下图所示的内容:

因此,对于我将图片从 Assets 文件夹中放入项目中的那些项目(意思是 "ImagePath" : "Assets/appbar.calendar.png"),我得到了正确的结果(在图片上是日历),但对于事件,我从硬盘驱动器中选择图片 - 我什么也没得到。

问题:是否可以将 UI 绑定到硬盘中的数据?或者我需要在 App 的 assets 文件夹(或LocalState 文件夹)中创建一些图片副本?


编辑

所以现在我有下一个:

    public object Convert(object value, Type targetType, object parameter, string language)
    {
        string filePath = value.ToString(); //get path to picture
        BitmapImage image = new BitmapImage(); //create bitmap image blank

        if (filePath.Contains("Assets")) //if standart picture
        {
            return LoadImageFromAssetsLibrary(image);
        }
        else
        {
            return LoadImageFromString(image, filePath);
        }
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        throw new NotImplementedException();
    }

    private async Task<ImageSource> LoadImageFromString(BitmapImage image, string path)
    {
        StorageFolder folder = KnownFolders.PicturesLibrary; //get folder
        StorageFile file = await folder.GetFileAsync(path); //find and read file
        //set source of file to image
        using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.Read))
        {
            await image.SetSourceAsync(stream);
        }

        return ...// i dont know how to return ImageSource from image that i create in code above
    }

所以我有点堆栈 - 如何从图像返回 ImageSource,尝试 (ImageSource)image 但得到(targetType - ImageSource):


编辑 2

经过小的更改(来自上次更新),可以使用 Converter 显示来自应用文件夹的图片,但来自图片库 - 不 - 认为问题在于访问...

改变了:

 public object Convert(object value, Type targetType, object parameter, string language)
    {
        string filePath = value.ToString(); //get path to picture
        BitmapImage image = new BitmapImage(); //create bitmap image blank
        if (filePath.Contains("Assets")) //if standart picture
        {
            LoadImageFromAssetsLibrary(image, filePath);
            return image;
        }
        else
        {
            LoadImageFromString(image, filePath);
            return image;
        }
    }
    //for this method required access
    private async Task LoadImageFromString(BitmapImage image, string path)
    {
        StorageFolder folder = KnownFolders.PicturesLibrary; //get folder
        StorageFile file = await folder.GetFileAsync(path); //find and read file
        //set source of file to image
        using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.Read))
        {
            await image.SetSourceAsync(stream);
        }
    }
    //this work correctly
    private async Task LoadImageFromAssetsLibrary(BitmapImage image, string path)
    {
        StringBuilder builder = new StringBuilder();
        builder.Append("ms-appx:///");
        builder.Append(path);
        string localPath = builder.ToString();

        Uri requestedFileUri = new Uri(localPath); //set default folder
        StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(requestedFileUri); //read file
        //set source of file to image
        using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.Read))
        {
            await image.SetSourceAsync(stream);
        }
    }

另外,我允许访问 pic 文件夹:


EDIT3

【问题讨论】:

  • 对于像这样的简单图像,放弃 pic/image 文件并将其转换为 xaml 作为模板并将其放入您的资源中。
  • 它只是一个示例,图像可以是用户可以选择的任何人,例如选择(未显示)它的照片
  • 我认为您应该复制用户选择的图像。也许您可以使用默认的图像文件夹,可能会有所帮助。

标签: c# .net xaml data-binding windows-store-apps


【解决方案1】:

您可以在有或没有用户许可的情况下访问不同的地方(这是您所要求的)。首先,我会给出一个解释,然后我会给出一个答案。如果您愿意,请跳至答案部分。

无需用户许可即可访问的位置


阅读

  • 安装文件夹
  • 漫游数据文件夹
  • 本地数据文件夹
  • [设置](技术上你只是写值,但仍然值得列出)

  • 漫游数据文件夹
  • 本地数据文件夹
  • [设置]


在您的应用清单(功能)中声明时可访问的位置


读/写

Known Folders

  • 音乐库
  • 文档库
  • 图片库
  • 视频库
  • 可移动存储

您必须直接要求用户为您选择的所有其他文件。您可以使用FileOpenPickerFolderPicker 类来执行此操作。然后,您可以将这些对象存储在FutureAccessList 中,以便将来使用。



回答


如果

  • 有问题的文件夹在Pictures Library 中(如果您或用户在D:\Pictures\... 的情况下手动将其包含在他们的库中),

  • 您已在App ManifestCapabilities 中包含对图片库的访问权限。

那么您确实可以“绑定”到这些文件。

“绑定”文件

创建一个IValueConverter。此转换器将接受路径字符串,对其进行解析以查找图片库中的文件名和位置,并使用KnownFolders.PicturesLibrary 访问图片库。

这是一个async 进程。转换器不能异步,所以基本流程是这样的:

在转换器中

  • 解析图像,确保它是正确的。
  • 创建一个空白的BitmapImage 对象。
  • 将字符串和BitmapImage 传递给异步LoadImageFromString 方法

LoadImageFromString 方法中

  • KnownFolders.PicturesLibrary 中检索有问题的StorageFolder
  • 找到文件。
  • 可选:检索文件缩略图。
  • 可选:将传递的BitmapImage参数的Source(使用BitmapImage.SetSource)设置为缩略图。
  • 读入文件 (await)。
  • BitmapImage 参数的Source(使用BitmapImage.SetSource)设置为文件的内容,必要时使用BitmapDecoder 对其进行解码。

您现在将从 ViewModel 异步加载数据(它应该解析您的 JSON),找到有问题的数据,并将您的 Image 控件的源设置为其内容。



最后一点

如果这不是为用户设计的应用程序,并且您的所有图像都在该文件夹中,您也可以让您的应用程序手动存储该文件夹的访问点并从那里检索所有图像。对于消费者驱动的应用程序,这显然不是建议的方法,但可以做到。

编辑:鉴于您上面的示例,这就是您所缺少的。从这个例子中读取文件可能需要做一些额外的工作(使用上面提到的BitmapDecoder),但也可能不需要。

public object Convert(object value, Type targetType, object parameter, string language)
{
    string filePath = value.ToString(); //get path to picture
    BitmapImage image = new BitmapImage(); //create bitmap image blank

    if (filePath.Contains("Assets")) //if standart picture
    {
        // Have it start processing the image in the background
        LoadImageFromAssetsLibrary(image);
        // Return the image. Even though it may not be done processing,
        // When it's done, it will fill the image with the source automatically
        return image;
    }
    else
    {
        // Same as above
        LoadImageFromString(image, filePath);
        return image;
    }
}

public object ConvertBack(object value, Type targetType, object parameter, string language)
{
    throw new NotImplementedException();
}

private async Task LoadImageFromString(BitmapImage image, string path)
{
    StorageFolder folder = KnownFolders.PicturesLibrary; //get folder
    StorageFile file = await folder.GetFileAsync(path); //find and read file
    //set source of file to image
    using (IRandomAccessStream stream = await file.OpenAsync(FileAccessMode.Read))
    {
        await image.SetSourceAsync(stream);
    }

    // You don't need to return anything here. It is in effect using the 'image'
    // reference as an 'out' variable, and filling it with the data retrieved.
}

【讨论】:

  • 感谢您提供如此好的答案 - 让您更加了解我。现在尝试创建描述的.. 我将发布所有我的代码
  • 在我的回答中为您的示例添加了修复
  • 如果您只是使用示例中的直接路径,那么您没有遵循我给出的建议。你不给它一个绝对路径,你查询文件夹。如果你的图片库包含D:/Pictures,并且图片是D:/Pictures/MyPicts/pic.png,那么你要Query for the file
  • 我发现了问题 - 在 Json 文件中我留下了像 D:\\Pictures\\Abstract\\8.jpg 这样的旧路径。现在我清除文件并添加新项目,因此文件的路径类似于"ImagePath":"111.jpg" - 表示在 pic 文件夹中,“ImagePath”:“Assets/appbar.calendar.png” - 表示安装文件夹。感谢重播 - 我会再次检查文件并发现这个错误。所以现在没关系 - 你可以在edit3中看到打印
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-05
  • 1970-01-01
  • 2014-01-06
相关资源
最近更新 更多