简体   繁体   English

如何加载图像缩略图以从IsolatedStorage查看

[英]How to Load Image Thumbnails to View from IsolatedStorage

I currently have several hundred images in IsolatedStorage of my application (which may turn to thousands), and the loading time is rediculously slow. 目前,我的应用程序的IsolatedStorage中有数百个映像(可能会变成数千个),并且加载时间非常慢。 Often times my application freezes and fails. 通常,我的应用程序冻结并失败。 The user is allowed to use the CameraCaptureTask to take pictures, and then each picture is saved to IsolatedStorage as well as shown in the View using a LongListSelector. 允许用户使用CameraCaptureTask拍照,然后将每张图片保存到IsolatedStorage中,并使用LongListSelector在视图中显示。 I've tried using a ViewBox and setting the GridCellSize of the LongListSelector to a small size (max width or height depending on aspect ratio of 108), but this does not help in reducing the time or actual image size when loading from IsolatedStorage. 我尝试过使用ViewBox并将LongListSelector的GridCellSize设置为较小的大小(最大宽度或高度取决于108的纵横比),但这在减少从IsolatedStorage加载时的时间或实际图像大小没有帮助。 I was wondering if there was a quick way to speed up the loading/rendering time by loading a thumbnail sized version of an image from IsolatedStorage to populate the view? 我想知道是否有一种通过从IsolatedStorage加载图像的缩略图大小版本来填充视图的方法来加快加载/渲染时间? Then once an image in the view is selected, I will pull only that image from IsolatedStorage. 然后,一旦选择了视图中的图像,我将仅从IsolatedStorage中拉出该图像。

MainPage.xaml MainPage.xaml

<phone:PhoneApplicationPage.Resources>

<Style x:Key="PhoneButtonBase" TargetType="ButtonBase">
    <Setter Property="Background" Value="Transparent"/>
    <Setter Property="BorderBrush" Value="{StaticResource PhoneForegroundBrush}"/>
    <Setter Property="Foreground" Value="{StaticResource PhoneForegroundBrush}"/>
    <Setter Property="BorderThickness" Value="{StaticResource PhoneBorderThickness}"/>
    <Setter Property="FontFamily" Value="{StaticResource PhoneFontFamilySemiBold}"/>
    <Setter Property="FontSize" Value="{StaticResource PhoneFontSizeMedium}"/>
    <Setter Property="Padding" Value="10,5,10,6"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="ButtonBase">
                <Grid Background="Transparent">
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="CommonStates">
                            <VisualState x:Name="Normal"/>
                            <VisualState x:Name="MouseOver"/>
                            <VisualState x:Name="Pressed">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentContainer">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneButtonBasePressedForegroundBrush}"/>
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="ButtonBackground">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneAccentBrush}"/>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="Disabled">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentContainer">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneDisabledBrush}"/>
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="ButtonBackground">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneDisabledBrush}"/>
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="ButtonBackground">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="Transparent"/>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                    <Border x:Name="ButtonBackground" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" CornerRadius="0" Margin="{StaticResource PhoneTouchTargetOverhang}">
                        <ContentControl x:Name="ContentContainer" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" Padding="{TemplateBinding Padding}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
                    </Border>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
<Style x:Key="PhoneRadioButtonCheckBoxBase" BasedOn="{StaticResource PhoneButtonBase}" TargetType="ToggleButton">
    <Setter Property="Background" Value="{StaticResource PhoneRadioCheckBoxBrush}"/>
    <Setter Property="BorderBrush" Value="{StaticResource PhoneRadioCheckBoxBorderBrush}"/>
    <Setter Property="FontSize" Value="{StaticResource PhoneFontSizeMedium}"/>
    <Setter Property="FontFamily" Value="{StaticResource PhoneFontFamilyNormal}"/>
    <Setter Property="HorizontalContentAlignment" Value="Left"/>
    <Setter Property="VerticalContentAlignment" Value="Center"/>
    <Setter Property="Padding" Value="0"/>
</Style>
<Style x:Key="RadioButtonStyle1" BasedOn="{StaticResource PhoneRadioButtonCheckBoxBase}" TargetType="RadioButton">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="RadioButton">
                <Grid Background="Transparent">
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="CommonStates">
                            <VisualState x:Name="Normal"/>
                            <VisualState x:Name="MouseOver"/>
                            <VisualState x:Name="Pressed"/>
                            <VisualState x:Name="Disabled">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentContainer">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneDisabledBrush}"/>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                        <VisualStateGroup x:Name="CheckStates">
                            <VisualState x:Name="Checked"/>
                            <VisualState x:Name="Unchecked"/>
                            <VisualState x:Name="Indeterminate"/>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                    <ContentControl x:Name="ContentContainer" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" FontSize="{TemplateBinding FontSize}" FontFamily="{TemplateBinding FontFamily}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" Padding="{TemplateBinding Padding}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

.. ..

            <phone:LongListSelector.ItemTemplate>
                <DataTemplate>
                    <ContentControl HorizontalAlignment="Stretch" HorizontalContentAlignment="Left">
                        <ContentControl.Resources>
                            <Storyboard x:Name="CheckedStoryboard">
                                <ColorAnimation Duration="0" To="#FF1BA1E2" Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)" Storyboard.TargetName="brd" d:IsOptimized="True"/>
                            </Storyboard>
                        </ContentControl.Resources>
                        <RadioButton x:Name="radioButton" HorizontalAlignment="Stretch" Margin="0,0,0,0" GroupName="A" Background="Black" Style="{StaticResource RadioButtonStyle1}" >
                            <i:Interaction.Triggers>
                                <i:EventTrigger EventName="Click">
                                    <eim:ControlStoryboardAction Storyboard="{StaticResource CheckedStoryboard}"/>
                                </i:EventTrigger>
                                <i:EventTrigger EventName="Unchecked">
                                    <eim:ControlStoryboardAction ControlStoryboardOption="Stop" Storyboard="{StaticResource CheckedStoryboard}"/>
                                </i:EventTrigger>
                            </i:Interaction.Triggers>
                            <Border x:Name="MyBorder" Background="Transparent">
                                <Border x:Name="brd" CornerRadius="10" Width="Auto" BorderThickness="3" BorderBrush="Transparent">
                                    <toolkit:ContextMenuService.ContextMenu>
                                        <toolkit:ContextMenu x:Name="imgListContextMenu" Background="{StaticResource PhoneChromeBrush}">                                                                                                        <toolkit:MenuItem Foreground="{StaticResource PhoneForegroundBrush}" Header="{Binding Path=LocalizedResources.MainPage_ContextMenu_Delete, Source={StaticResource LocalizedStrings}}" Click="deleteContextMenuItem_Click"/>
                                        </toolkit:ContextMenu>
                                    </toolkit:ContextMenuService.ContextMenu>
                                    <Viewbox Width="108" Height="108">
                                        <Image x:Name="recentImage" Source="{Binding Source}" Margin="6,6" Width="108"/>
                                    </Viewbox>
                                </Border>
                            </Border>
                        </RadioButton>
                    </ContentControl>
                </DataTemplate>
            </phone:LongListSelector.ItemTemplate>

        </phone:LongListSelector>

MainPage.xaml.cs MainPage.xaml.cs

protected override void OnNavigatedTo(NavigationEventArgs e)
{   
    if (Settings.AscendingSort.Value)
    {
        App.PictureList.Pictures = new ObservableCollection<Models.Picture>(App.PictureList.Pictures.OrderBy(x => x.DateTaken)); 
        Recent.ItemsSource = App.PictureList.Pictures;
    }
    else
    {
        App.PictureList.Pictures = new ObservableCollection<Models.Picture>(App.PictureList.Pictures.OrderByDescending(x => x.DateTaken));
        Recent.ItemsSource = App.PictureList.Pictures;
    }    
}

... ...

private void cameraTask_Completed(object sender, PhotoResult e)
{
    if (e.TaskResult == TaskResult.OK)
    {
        var capturedPicture = new CapturedPicture(e.OriginalFileName, stream);
    }
}

private void recent_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    var item = (sender as LongListSelector).SelectedItem;
    if (item == null)
        return;

    capturedPicture = null; 
    //Get picture
    capturedPicture = (sender as LongListSelector).SelectedItem as CapturedPicture;

    if (capturedPicture != null)
    {                
        fileName = capturedPicture.FileName;
    }
}

App.xaml.cs App.xaml.cs

public static PictureRepository PictureList
{
    get
    {
        return PictureRepository.Instance;
    }
}

PictureRepository.cs PictureRepository.cs

#region Constants

public const string IsolatedStoragePath = "Pictures";

#endregion

#region Fields

private ObservableCollection<Picture> _pictures = new ObservableCollection<Picture>();

#endregion

#region Properties

public ObservableCollection<Picture> Pictures
{
    get { return _pictures; }
    set{ pictures = value; }
}

#endregion

#region Singleton Pattern

private PictureRepository()
{
    LoadAllPicturesFromIsolatedStorage();
}

public static readonly PictureRepository Instance = new PictureRepository();

#endregion

/// <summary>        
/// Saves to local storage
/// This method gets two parameters: the captured picture instance and the name of the pictures folder in the isolated storage
/// </summary>
/// <param name="capturedPicture"></param>
/// <param name="directory"></param>
public void SaveToLocalStorage(CapturedPicture capturedPicture, string directory)
{
    //call IsolatedStorageFile.GetUserStoreForApplication to get an isolated storage file
    var isoFile = IsolatedStorageFile.GetUserStoreForApplication();
    //Call the IsolatedStorageFile.EnsureDirectory extension method located in the Common IsolatedStorageFileExtensions class to confirm that the pictures folder exists.
    isoFile.EnsureDirectory(directory);

    //Combine the pictures folder and captured picture file name and use this path to create a new file 
    string filePath = Path.Combine(directory, capturedPicture.FileName);
    using (var fileStream = isoFile.CreateFile(filePath))
    {
        using (var writer = new BinaryWriter(fileStream))
        {
            capturedPicture.Serialize(writer);
        }
    }
}

/// <summary>
/// To load all saved pictures and add them to the pictures list page
/// </summary>
public CapturedPicture LoadFromLocalStorage(string fileName, string directory)
{
    //To open the file, add a call to the IsolatedStorageFile.GetUserStoreForApplication
    var isoFile = IsolatedStorageFile.GetUserStoreForApplication();

    //Combine the directory and file name
    string filePath = Path.Combine(directory, fileName);
    //use the path to open the picture file from the isolated storage by using the IsolatedStorageFile.OpenFile method
    using (var fileStream = isoFile.OpenFile(filePath, FileMode.Open, FileAccess.Read))
    {
        //create a BinaryReader instance for deserializing the CapturedPicture instance
        using (var reader = new BinaryReader(fileStream))
        {
            var capturedPicture = new CapturedPicture();
            //create a new instance of the type CapturedPicture called CapturedPicture.Deserialize to deserialize the captured picture and return it
            capturedPicture.Deserialize(reader);
            return capturedPicture;
        }
    }
}

/// <summary>
/// To load all the pictures at start time
/// </summary>
private void LoadAllPicturesFromIsolatedStorage()
{
    //add call to the IsolatedStorageFile.GetUserStoreForApplication to open an isolated storage file
    var isoFile = IsolatedStorageFile.GetUserStoreForApplication();
    //Call the IsolatedStorageFile.EnsureDirectory extension method located in the Common IsolatedStorageFileExtensions class to confirm that the pictures folder exists
    isoFile.EnsureDirectory(IsolatedStoragePath);

    //Call the IsolatedStorageFile.GetFileNames using the pictures directory and *.jpg as a filter to get all saved pictures
    var pictureFiles = isoFile.GetFileNames(Path.Combine(IsolatedStoragePath, "*.jpg"));
    //var pictureFiles = isoFile.GetFileNames(Path.Combine(IsolatedStoragePath, ""));

    //Iterate through all the picture files in the list and load each using the LoadFromLocalStorage you created earlier
    foreach (var pictureFile in pictureFiles)
    {
        var picture = LoadFromLocalStorage(pictureFile, IsolatedStoragePath);
        _pictures.Add(picture);
    }
}

LoadAllPicturesFromIsolatedStorage is where the images from IsolatedStorage are being loaded, what would be the best and most efficient way to reduce the image size to a max width or height of 108 to decrease loading/rendering time? LoadAllPicturesFromIsolatedStorage是从IsolatedStorage加载图像的地方,将图像尺寸减小到最大宽度或最大高度108以减少加载/渲染时间的最佳,最有效的方法是什么? And is this the best way to go about this in the first place? 这是首先解决此问题的最佳方法吗? Any help, suggestions, or thoughts would be greatly appreciated. 任何帮助,建议或想法将不胜感激。

EDIT: added CapturedPicture.cs, Picture.cs 编辑:添加了CapturedPicture.cs,Picture.cs

CapturedPicture.cs CapturedPicture.cs

[DataContract]
public class CapturedPicture : Picture
{
    [DataMember]
    public byte[] ImageBytes
    {
        get;
        set;
    }

    [DataMember]
    public string FileName
    {
        get;
        set;
    }

    protected override BitmapSource CreateBitmapSource()
    {
        BitmapSource source = null;
        if (ImageBytes != null)
        {
            using (var stream = new MemoryStream(ImageBytes))
            {
                source = PictureDecoder.DecodeJpeg(stream);
                //source = PictureDecoder.DecodeJpeg(stream, 500, 500);
            }
        }
        return source;
    }

    public CapturedPicture()
    {
    }

    public CapturedPicture(string capturedFileName, Stream capturedImageStream)
    {
        ImageBytes = ReadImageBytes(capturedImageStream);
        //DateTaken = DateTime.Now.ToLongDateString();
        //DateTaken = DateTime.Now.ToString();
        //DateTaken = DateTime.Now.ToString("o");
        DateTaken = DateTime.UtcNow;
        FileName = System.IO.Path.GetFileName(capturedFileName);
    }

    private byte[] ReadImageBytes(Stream imageStream)
    {
        byte[] imageBytes = new byte[imageStream.Length];
        imageStream.Read(imageBytes, 0, imageBytes.Length);
        return imageBytes;
    }

    public override void Serialize(BinaryWriter writer)
    {
        base.Serialize(writer);
        writer.Write(ImageBytes.Length);
        writer.Write(ImageBytes);
        writer.Write(FileName);//writer.WriteString(FileName);
    }

    public override void Deserialize(BinaryReader reader)
    {
        base.Deserialize(reader);
        int bytesCount = reader.ReadInt32();
        ImageBytes = reader.ReadBytes(bytesCount);
        FileName = reader.ReadString();
    }

Picture.cs Picture.cs

[DataMember]
public string Address
{
    get { return GetValue(() => Address); }
    set { SetValue(() => Address, value); }
}

[DataMember]
public string Note
{
    get { return GetValue(() => Note); }
    set { SetValue(() => Note, value); }
}

[DataMember]
public DateTime DateTaken
{
    get { return GetValue(() => DateTaken); }
    set { SetValue(() => DateTaken, value); }
}

[IgnoreDataMember]
public BitmapSource Source
{
    get
    {
        return CreateBitmapSource();
    }
}

protected abstract BitmapSource CreateBitmapSource();

//In the Serialize method, store the Position, Address, Note, and DateTaken properties
public virtual void Serialize(BinaryWriter writer)
{            
    writer.Write(DateTaken.ToString()); //writer.WriteString(DateTaken);
}

//In the Deserialize method, read the data in the same order you’ve written it
public virtual void Deserialize(BinaryReader reader)
{
    DateTaken = DateTime.Parse(reader.ReadString());
}

If I had to guess from looking at the code, your problem is that you are not allowing the phone framework to load the images on demand when their container is scrolled into view. 如果我不得不通过查看代码来猜测,那么您的问题是,当其容器滚动到视图中时,您不允许电话框架按需加载图像。 Your code is going to decode every one of those files immediately on page load rather than as they become visible. 您的代码将在页面加载时立即解码这些文件中的每个文件,而不是在它们可见时对其进行解码。 You're also using the deprecated isolated storage API instead of the new asynchronous Windows.Storage namespace, which is likely going to block your UI thread. 您还将使用不推荐使用的隔离存储API,而不是新的异步Windows.Storage命名空间,这可能会阻塞UI线程。

You can refactor this however you'd prefer, but consider something similar to the following: 您可以根据自己的意愿进行重构,但可以考虑以下内容:

Code Behind 背后的代码

public partial class MyPage : PhoneApplicationPage
{
    public MyPage()
    {
        InitializeComponent();

        this.Loaded += async (sender, e) =>
        {
            var folder = await ApplicationData.Current.LocalFolder.GetFolderAsync("Pictures");
            var images = await folder.GetFilesAsync();
            Recent.ItemsSource = images.ToList();
        };
    }
}

XAML XAML

<phone:LongListSelector x:Name="Recent" Margin="0,0,0,72" LayoutMode="Grid" GridCellSize="108,108">
    <phone:LongListSelector.ItemTemplate>
        <DataTemplate>
            <Image Source="{Binding Path}" Margin="6" Stretch="UniformToFill" VerticalAlignment="Center" HorizontalAlignment="Center"/>
        </DataTemplate>
    </phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>

This is an overly simplistic example, but the upshot is that you can build a list of StorageFile and bind your LongListSelector.ItemSource property to it. 这是一个过于简单的示例,但是最终结果是,您可以构建一个StorageFile列表,并将LongListSelector.ItemSource属性绑定到该列表。 The Image.Source dependency property is pretty malleable, so you can pass it the image file's path string directly and it will do the heavy lifting of creating an image source object for you, scaled and cropped to the specifications of the image container. Image.Source依赖项属性具有很好的延展性,因此您可以直接将图像文件的路径字符串传递给它,它将为您创建图像源对象,按比例缩放并裁剪为图像容器的规范进行繁重的工作。 This process only occurs as the image is scrolled into view so you'll only ever have a handful of images loaded at a time. 该过程仅在图像滚动到视图中时发生,因此一次只能加载少量图像。 The LongListSelector will do the work of rendering the item templates on demand for you as the user scrolls the list, generating the new Image controls and its Source at that time. 当用户滚动列表时,LongListSelector将根据需要呈现项目模板的工作,此时将生成新的Image控件及其Source。

If for whatever reason you feel the need to transform these records to your CapturedPicture class, feel free. 如果出于任何原因,您觉得有必要将这些记录转换为CapturedPicture类,请放心。 The one most important piece of information you'll need to map is the Path property from these file objects, as it is a valid URI to provide to the image control as the Source binding. 您需要映射的最重要的一条信息是这些文件对象的Path属性,因为它是有效的URI,可以作为Source绑定提供给图像控件。

--EDIT-- - 编辑 -

I've added code that demonstrates, if nothing else, the changed loading process. 我添加了代码,这些代码演示了更改的加载过程(如果没有其他说明)。 I've wired up the INotifyPropertyChanged interface for this repo so that the UI will be notified of changes to the Pictures collection and changed the setter to private (this is an assumption on my part about your desired behavior). 我已为此回购连接了INotifyPropertyChanged接口,以便UI会收到有关Pictures集合更改的通知,并将setter更改为private(这是我对您所需行为的假设)。

For read and write operations, you can check out extensions for the StorageFile class in the System.IO namespace. 对于读写操作,您可以在System.IO名称空间中签出StorageFile类的扩展名。 Just import it in a using directive and you'll have access to the following: 只需将其导入using指令中,您就可以访问以下内容:

Implementation of the save method may be much more complex depending on what you accept as a parameter for the save directory. save方法的实现可能要复杂得多,具体取决于您接受的save目录参数。 If you allow for specifying a directory parameter with a full path of multiple subdirectories, that would change the code substantially from just allowing saving to a first-level subdirectory. 如果允许指定具有多个子目录的完整路径的目录参数,则将大大改变代码,从仅允许保存到第一级子目录开始。 You'd have to check for the existence of each subfolder and create it if not. 您必须检查每个子文件夹是否存在,如果没有,请创建它。 Otherwise, the code sample below for accessing the Pictures folder should suffice to demonstrate how to obtain the target folder. 否则,下面用于访问“图片”文件夹的代码示例就足以演示如何获取目标文件夹。

Sample PictureRepository.cs 示例PictureRepository.cs

using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Threading.Tasks;
using Windows.Storage;
using Windows.Storage.Search;

namespace MyApp.Media
{
    public class PictureRepository : INotifyPropertyChanged
    {
        #region Constants

        public const string IsolatedStoragePath = "Pictures";

        #endregion

        #region Fields

        private ObservableCollection<StorageFile> _pictures = new ObservableCollection<StorageFile>();

        #endregion

        #region Properties

        public ObservableCollection<StorageFile> Pictures
        {
            get { return _pictures; }
            private set
            {
                RaisePropertyChanged("Pictures");
                _pictures = value;
            }
        }

        #endregion

        #region INotifyPropertyChanged

        public event PropertyChangedEventHandler PropertyChanged;

        private void RaisePropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion

        #region Singleton Pattern

        private PictureRepository()
        {
            // This call will warn that execution of the method will continue without waiting on completion
            // This is unimportant because the remainder of the constructor is not dependent on its initialization
            // and the UI will be notified of the change in the collection and respond at that time
            LoadAllPicturesFromIsolatedStorageAsync();
        }

        public static readonly PictureRepository Instance = new PictureRepository();

        #endregion

        /// <summary>
        /// To load all the pictures at start time
        /// </summary>
        private async Task LoadAllPicturesFromIsolatedStorageAsync()
        {
            // Create or open the target folder
            var folder = await ApplicationData.Current.LocalFolder.CreateFolderAsync(IsolatedStoragePath, CreationCollisionOption.OpenIfExists);

            // Create a query for files with the JPEG extension
            var query = folder.CreateFileQueryWithOptions(new QueryOptions(CommonFileQuery.OrderByName, new string[] { ".jpg" }));

            // Update the Pictures collection, which will raise the PropertyChanged event and cause the UI to bind
            Pictures = new ObservableCollection<StorageFile>(await query.GetFilesAsync());
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM