2

UWP と XAML はかなり新しく、これをデバッグする方法がわかりません。

Template10 ハンバーガー テンプレートと Template10 インクリメンタル ロード サンプルに基づいた UWP アプリに加えて、サンプル フォト ビューアー ( Windows 8: Making a Simple Photo Viewer in C# and XAML ) からのいくつかのビットがあります。

メイン ページを変更して、Pictures フォルダーからの画像の Gridview を表示し、画像が段階的に読み込まれるようにしました。また、サンプル フォト ビューアー ( Windows 8: Making a Simple Photo Viewer in C# and XAML ) からもいくつか引用しました。

アプリを起動すると、画像が期待どおりに表示され、下にスクロールすると、画像が読み込まれてオンデマンドで表示されます。問題は、リストを上にスクロールすると、画像が表示されなくなることです。ファイル名と色付きのアイテムの背景を表示するグリッドビュー アイテムはまだ存在しますが、画像は描画されなくなりました。

メモリ フットプリントを小さく保つために、実際のビットマップ イメージをコレクションの一部として保存するのではなく、代わりに StorageItemThumbnail を保存します。私はもともと画像パスだけを保存したかったのですが、それは写真ライブラリの何に対しても機能しません。

public class Picture
{
    public StorageItemThumbnail  ImageThumbNail {get; set;}
    public string Name {get; set;}
}

これを表示するには、コンバーター クラスを使用してストリームを作成し、画像ソースを設定します。

public object Convert(object value, Type targetType, object parameter, string language)
{

    BitmapImage image = null;

    if (value != null)
    {
        if (value.GetType() != typeof(StorageItemThumbnail))
        {
            throw new ArgumentException("Expected a StorageItemThumbnail as binding input.");
        }
        if (targetType != typeof(ImageSource))
        {
            throw new ArgumentException("Expected ImageSource as binding output.");
        }

        if (Windows.ApplicationModel.DesignMode.DesignModeEnabled)
        {
            image = new BitmapImage();
            image.UriSource = new Uri("ms-appx:///Assets/DesignModeThumbnailPlaceholder.png");
        }
        else
        {
            StorageItemThumbnail ThumbNailFile = (StorageItemThumbnail)value;

            if (ThumbNailFile == null)
                return image;

            image = new BitmapImage();
            IRandomAccessStream thumbnailStream = ThumbNailFile as IRandomAccessStream;
            image.SetSource(thumbnailStream);
        }

    }

    return (image);

}

そして、これは私の XAML で次のようにバインドされています。

    <DataTemplate x:Name="PictureGridTemplate2">
    <Grid Height="150" Width="150">
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <Border Grid.RowSpan="2" Background="Black" Opacity="0.8" />
        <Image Width ="130" HorizontalAlignment="Center"
               Stretch="Uniform" Source="{Binding ImageThumbNail, Converter={StaticResource ThumbnailFileToImageSourceConverter}}"/>
        <TextBlock Grid.Row="1" MaxHeight="30" Text="{Binding Name}"
                   Foreground="White" TextTrimming="CharacterEllipsis"/>
    </Grid>
</DataTemplate>

誰かが私がこれで間違った方向に私を向けることができますか?

シェリ

*解決済み*

私はついにこの問題の原因を突き止めることができました。

これは、グリッドビューの仮想化、データ モデル、およびコンバーターを介して画像を提供する方法の副作用でした。

テストとして、コンバーターを削除し、データ モデルを変更して、サムネイルの BitmapImage インスタンスを格納し (画像全体を格納するよりも小さい)、そのプロパティに直接バインドしました。これは機能し、グリッドビューを上下にスクロールすると、画像が画面に表示されました。

次に、データ モデルを変更して、BitmapImage プロパティ ゲッターが StorageItemThumbnail プロパティからオンザフライで BitmapImage ビルドを返すようにしました。これは、コンバーターを使用する場合と同じ問題です。

getter にいくつかのデバッグ ステートメントを追加すると、2 番目のリクエストで BitmapImage の高さと幅が 0 であることがわかりました。では、なぜ 0 なのですか?

2 番目のリクエストで StorageItemThumbnail プロパティを見ると、ストリームの位置が EOF にあることがわかりました (最初のリクエストのように 0 ではありません)。これにより、幅と高さが 0 であることが説明され、画面上の空の画像コントロールが説明されました。

コードを変更して StorageItemThumbnail.CloneStream を使用すると、すべての画像が表示されるようになりました。

これが今のコンバーターメソッドです:

    public object Convert(object value, Type targetType, object parameter, string language)
    {

        BitmapImage image = null;

        if (value != null)
        {
            if (value.GetType() != typeof(StorageItemThumbnail))
            {
                throw new ArgumentException("Expected a StorageItemThumbnail as binding input.");
            }
            if (targetType != typeof(ImageSource))
            {
                throw new ArgumentException("Expected ImageSource as binding output.");
            }

            if ((StorageItemThumbnail)value == null)
            {
                System.Diagnostics.Debug.WriteLine("Thumbnail is null.");
                return image;
            }

            image = new BitmapImage();

            using (var thumbNailClonedStream = ((StorageItemThumbnail)value).CloneStream())
            {
                System.Diagnostics.Debug.WriteLine("Setting image source from cloned stream.");
                image.SetSource(thumbNailClonedStream);
            } 
        }

        return (image);

    }

時間を割いて回答し、私を正しい方向に導く手助けをしてくれたすべての人に感謝します.

4

1 に答える 1

0

Binding の代わりにコンパイル済みバインディングx:Bind
を使用してみることができ ます。この場合、アプリケーションのパフォーマンスははるかに高速になります。

フェーズを使用してデータ テンプレートを最適化し、GridView アイテムを段階的に更新します。

    <Grid Height="150" Width="150">
    <Grid.RowDefinitions>
        <RowDefinition Height="*" />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>
    <Border Grid.RowSpan="2" Background="Black" Opacity="0.8" />
    <Image Width ="130" HorizontalAlignment="Center"
           Stretch="Uniform" Source="{Binding ImageThumbNail, Converter={StaticResource ThumbnailFileToImageSourceConverter}}" x:Phase="2"/>
    <TextBlock Grid.Row="1" MaxHeight="30" Text="{Binding Name}" x:Phase="1"
               Foreground="White" TextTrimming="CharacterEllipsis"/>
   </Grid> 

このトピックをお読みください:
ListView および GridView UI の最適化
ListView および GridView のデータ仮想化

于 2016-04-29T13:51:40.377 に答える