【问题标题】:Select and display xamarin.form.Image in windows phone在 windows phone 中选择并显示 xamarin.form.Image
【发布时间】:2016-01-07 11:33:49
【问题描述】:

我正在使用 mvvmCross 在 Xamarin 中开发适用于 Windows phone 8.1 的应用程序。我需要从电话库中选择多个图像并显示它们。我正在使用 FileOpenPicker.SelectMultipleFilesAndContinue 这样做。现在我需要能够在视图中显示所有这些图像。一个问题是图像的最小数量必须是 20,并且图像可能非常大。 首先,我尝试将它们制作成字节数组并使用转换器来显示它们。

 public async void SelectFotosCallback(FileOpenPickerContinuationEventArgs args) {

        if (args.Files.Count > 0) {

            foreach (StorageFile file in args.Files) {

                IRandomAccessStream fileStream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read);

                byte[] bytes = null;
                using (var reader = new DataReader(fileStream.GetInputStreamAt(0))) {
                    bytes = new byte[fileStream.Size];
                    await reader.LoadAsync((uint)fileStream.Size);
                    reader.ReadBytes(bytes);
                }

                callback(bytes);
            }              
        }
        else {

        }
    }

这种方法在第一次尝试时似乎确实有效,但是当我尝试使用 5 张图像时,它就停止了工作。回调完成后,应用程序就退出了。没有错误信息或任何东西。 (我的猜测是内存过载。)

在此之后,我找到了一个小解决方案,我将字节数组制作成 Xamarin.Form 图像。

public async void SelectFotosCallback(FileOpenPickerContinuationEventArgs args) {
        if (args.Files.Count > 0) {
            foreach (StorageFile file in args.Files) {
                IRandomAccessStream fileStream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read);

                byte[] bytes = null;
                using (var reader = new DataReader(fileStream.GetInputStreamAt(0))) {
                    bytes = new byte[fileStream.Size];
                    await reader.LoadAsync((uint)fileStream.Size);
                    reader.ReadBytes(bytes);
                }
                Image image = new Image();
                image.Source = ImageSource.FromStream(() => new MemoryStream(bytes));
                var iets = image.Source.BindingContext;

                callback(image);
            }              
        }
        else {

        }

这似乎解决了内存过载的问题。现在唯一的另一个问题是我似乎找不到任何显示这些图像的方式。

<GridView ItemsSource="{Binding SelectedImages}">
                    <GridView.ItemTemplate>
                        <DataTemplate>
                            <Grid>
                                <Image Style="{StaticResource imageListImage}" Source="{Binding Source}"/>
                                <Button Style="{StaticResource imageListXButton}">
                                    <Button.Background>
                                        <ImageBrush ImageSource="ms-appx:///Resources/XButton.png"/>
                                    </Button.Background>
                                </Button>
                            </Grid>
                        </DataTemplate>
                    </GridView.ItemTemplate>

我尝试使用简单的绑定来显示它们。我还没有找到任何可行的方法。有谁知道显示这些图像的方法,如果不知道,在不使用太多内存的情况下使用字节的最佳选择是什么。

【问题讨论】:

    标签: c# image mvvmcross xamarin.forms fileopenpicker


    【解决方案1】:

    经过一番深入挖掘,我找到了答案。这比我想象的要简单得多。我开始使用 BitmapImage 中的 decodepixel。我使用转换器设置值。

    public object Convert(object value, Type targetType, object parameter, string language) {
    
            BitmapImage image = (BitmapImage)value;
    
            image.DecodePixelType = DecodePixelType.Logical;
    
            if (image.PixelHeight >= image.PixelWidth) {
                image.DecodePixelHeight = 100;
            }
            else {
                image.DecodePixelWidth = 100;
            }
            return image;
        }
    

    奇怪的是它在某些时候确实有效。但由于某种原因,它并不能处理所有图像,有时甚至将它们扔掉。 但经过大量测试后,我终于找到了我要找的东西。

                        BitmapImage bitmap = new BitmapImage();
                        BitmapImage temp = new BitmapImage();
    
                        bitmap.DecodePixelType = DecodePixelType.Logical;
    
                        using (IRandomAccessStream fileStream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read)) {
                           IRandomAccessStream secondStream = fileStream.CloneStream();
                            BitmapImage temp = new BitmapImage();
                            temp.SetSource(fileStream);
                            if (temp.PixelHeight >= temp.PixelWidth) {
                                bitmap.DecodePixelHeight = 150;
                            }
                            else {
                                bitmap.DecodePixelWidth = 150;
                            }
                            bitmap.SetSource(secondStream);
                        }
    

    由于某种原因,在设置源之后设置 decodepixel 会使其不一致,但在设置源之前设置这些值实际上会立即裁剪图像。

    这个方法效果很好,完全解决了我的内存不足问题

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-05-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多