2017-09-19 7 views
2

私のUWPアプリケーションでは、私はインクリメンタルロードのListViewを持っています。今私はListViewItemに画像を含める必要があります。私は直接URIを与えようとしました。インターネットからの画像を非同期的に表示

ThumbnailImageは、私のビューモデルの単なる文字列です。この問題は、インクリメンタルロードのために、以前の画像がまだ読み込まれている間に少しスクロールするとアプリがハングするだけです。一方、すべての画像を表示してからスクロールダウンすると、正常に動作します。

また、ツールキットからImageExコントロールを試しましたが、同じ問題があります。

XAMLで見つかった唯一のものを検索しました。doing IsAsync = Trueです。しかし、UWPではIsAsyncが利用できないようです。

私のViewModel:

public class MyViewModel 
{ 
    ... 
    public string ThumbnailImage { get; set; } 
    ... 
} 

私のXAML ListViewここに私の増分ロードクラスの漸進

<ListView Grid.Row="0"    
     SelectionMode="Single" 
     IsItemClickEnabled="True" 
     ItemClick="SearchResultListView_ItemClick" > 

    <ListView.ItemContainerStyle> 
     <Style TargetType="ListViewItem"> 
      <Setter Property="HorizontalContentAlignment" Value="Stretch"/> 
      <Setter Property="BorderBrush" Value="Gray"/> 
      <Setter Property="BorderThickness" Value="0, 0, 0, 1"/> 
      <Setter Property="Template"> 
       <Setter.Value> 
        <ControlTemplate TargetType="ListViewItem"> 
         <ListViewItemPresenter 
          ContentTransitions="{TemplateBinding ContentTransitions}" 
          SelectionCheckMarkVisualEnabled="True" 
          CheckBrush="{ThemeResource SystemControlForegroundBaseMediumHighBrush}" 
          CheckBoxBrush="{ThemeResource SystemControlForegroundBaseMediumHighBrush}" 
          DragBackground="{ThemeResource ListViewItemDragBackgroundThemeBrush}" 
          DragForeground="{ThemeResource ListViewItemDragForegroundThemeBrush}" 
          FocusBorderBrush="{ThemeResource SystemControlForegroundAltHighBrush}" 
          FocusSecondaryBorderBrush="{ThemeResource SystemControlForegroundBaseHighBrush}" 
          PlaceholderBackground="{ThemeResource ListViewItemPlaceholderBackgroundThemeBrush}" 
          PointerOverBackground="{ThemeResource SystemControlDisabledTransparentBrush}" 
          SelectedBackground="{ThemeResource SystemControlDisabledTransparentBrush}" 
          SelectedForeground="{ThemeResource SystemControlDisabledTransparentBrush}" 
          SelectedPointerOverBackground="{ThemeResource SystemControlDisabledTransparentBrush}" 
          PressedBackground="{ThemeResource SystemControlDisabledTransparentBrush}" 
          SelectedPressedBackground="{ThemeResource SystemControlDisabledTransparentBrush}" 
          DisabledOpacity="{ThemeResource ListViewItemDisabledThemeOpacity}" 
          DragOpacity="{ThemeResource ListViewItemDragThemeOpacity}" 
          ReorderHintOffset="{ThemeResource ListViewItemReorderHintThemeOffset}" 
          HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" 
          VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" 
          ContentMargin="{TemplateBinding Padding}" 
          CheckMode="Inline"/> 
        </ControlTemplate> 
       </Setter.Value> 
      </Setter> 
     </Style> 
    </ListView.ItemContainerStyle> 

    <ListView.ItemTemplate> 
     <DataTemplate x:DataType="viewModel:MyViewModel"> 
      <UserControl > 
       <Grid Style="{StaticResource SomeStyle}"> 
        <VisualStateManager.VisualStateGroups> 
         <VisualStateGroup x:Name="VisualStateGroup"> 
          <VisualState x:Name="VisualStatePhone"> 
           <VisualState.StateTriggers> 
            <AdaptiveTrigger MinWindowWidth="0"/> 
           </VisualState.StateTriggers> 
           <VisualState.Setters> 
            <Setter Target="ThumbnailImage.Width" Value="50"/> 
            <Setter Target="ThumbnailImage.Height" Value="50"/>           
           </VisualState.Setters> 
          </VisualState> 

          <VisualState x:Name="VisualStateTablet"> 
           <VisualState.StateTriggers> 
            <AdaptiveTrigger MinWindowWidth="600" /> 
           </VisualState.StateTriggers> 
           <VisualState.Setters> 
            <Setter Target="ThumbnailImage.Width" Value="70"/> 
            <Setter Target="ThumbnailImage.Height" Value="70"/> 
           </VisualState.Setters> 
          </VisualState> 

          <VisualState x:Name="VisualStateDesktop"> 
           <VisualState.StateTriggers> 
            <AdaptiveTrigger MinWindowWidth="1200" /> 
           </VisualState.StateTriggers> 
           <VisualState.Setters> 
            <Setter Target="ThumbnailImage.Width" Value="90"/> 
            <Setter Target="ThumbnailImage.Height" Value="90"/> 
           </VisualState.Setters> 
          </VisualState> 
         </VisualStateGroup> 
        </VisualStateManager.VisualStateGroups> 

        <Grid.RowDefinitions> 
         <RowDefinition MaxHeight="30"></RowDefinition> 
         <RowDefinition MaxHeight="30"></RowDefinition> 
         <RowDefinition MaxHeight="30"></RowDefinition> 
         <RowDefinition MaxHeight="30"></RowDefinition> 
         <RowDefinition MaxHeight="30"></RowDefinition> 
         <RowDefinition MaxHeight="10"></RowDefinition> 
        </Grid.RowDefinitions> 
        <Grid.ColumnDefinitions> 
         <ColumnDefinition Width="Auto"/> 
         <ColumnDefinition Width="*"/> 
        </Grid.ColumnDefinitions> 

        <Image Source="{x:Bind ThumbnailImage}"            
          Visibility="{x:Bind ThumbnailImage, Converter={StaticResource BoolToVisibilityImage}}" 
          Name="ThumbnailImage"/> 

        <TextBlock Text="{x:Bind Name}" .../>        

        <Grid Grid.Row="1" 
          Grid.Column="1" 
          Visibility="{x:Bind Source, Converter={StaticResource ConverterNameHere}}"> 

         <Grid.ColumnDefinitions> 
          <ColumnDefinition Width="Auto"/> 
          <ColumnDefinition Width="*"/> 
         </Grid.ColumnDefinitions> 

         <TextBlock Text="{x:Bind lblSource, Mode=OneWay}" .../> 

         <TextBlock Text="{x:Bind Source}" .../> 
        </Grid> 

        <Grid Grid.Row="2" 
          Grid.Column="1" 
          Visibility="{x:Bind Author, Converter={StaticResource ConverterNameHere}}"> 

         <Grid.ColumnDefinitions> 
          <ColumnDefinition Width="Auto"/> 
          <ColumnDefinition Width="*"/> 
         </Grid.ColumnDefinitions> 

         <TextBlock Text="{x:Bind lblAuthor, Mode=OneWay}" .../> 
         <TextBlock Text="{x:Bind Author}" .../> 
        </Grid> 

        <TextBlock Text="{x:Bind EducationalLevel}" .../> 

        <StackPanel Orientation="Horizontal" 
           Grid.Row="4" 
           Grid.Column="1"> 

         <ItemsControl ItemsSource="{x:Bind AccessRights}"> 
          <ItemsControl.ItemsPanel> 
           <ItemsPanelTemplate> 
            <StackPanel Orientation="Horizontal"/> 
           </ItemsPanelTemplate> 
          </ItemsControl.ItemsPanel> 
          <ItemsControl.ItemTemplate> 
           <DataTemplate> 
            <Image Source="{Binding}"/> 
           </DataTemplate> 
          </ItemsControl.ItemTemplate> 
         </ItemsControl> 

         <ItemsControl ItemsSource="{x:Bind Languages}"> 
          <ItemsControl.ItemsPanel> 
           <ItemsPanelTemplate> 
            <StackPanel Orientation="Horizontal"/> 
           </ItemsPanelTemplate> 
          </ItemsControl.ItemsPanel> 
         </ItemsControl> 

         <ItemsControl ItemsSource="{x:Bind TypeImages}"> 
          <ItemsControl.ItemsPanel> 
           <ItemsPanelTemplate> 
            <StackPanel Orientation="Horizontal"/> 
           </ItemsPanelTemplate> 
          </ItemsControl.ItemsPanel> 
          <ItemsControl.ItemTemplate> 
           <DataTemplate> 
            <Image Source="{Binding}"/> 
           </DataTemplate> 
          </ItemsControl.ItemTemplate> 
         </ItemsControl>        

        </StackPanel> 

       </Grid> 
      </UserControl> 
     </DataTemplate> 
    </ListView.ItemTemplate> 
</ListView> 

満たされます:デフォルトでは

public class ItemsToShow : ObservableCollection<MyViewModel>, ISupportIncrementalLoading 
{ 
    private SearchResponse ResponseObject { get; set; } = new SearchResponse(); 
    MyViewModel viewModel = null; 


    public bool HasMoreItems 
    { 
     get 
     { 
      if ((string.IsNullOrEmpty(SearchResultDataStore.NextPageToken) && !SearchResultDataStore.IsFirstRequest) || SearchResultDataStore.StopIncrementalLoading) 
       return false; 

      if(SearchResultDataStore.IsFirstRequest) 
      { 
       using (var db = new DbContext()) 
       { 
        var json = db.UpdateResponse.First(r => r.LanguageId == DataStore.Language).JsonResponse; 
        Metadata = Newtonsoft.Json.JsonConvert.DeserializeObject<UpdateApiResponse>(json).response.metadata.reply; 
       } 

       var returnObject = SearchResultDataStore.SearchResponse; 
       ResponseObject = returnObject.response; 

       //This will show a grid with some message for 3 seconds on a xaml page named SearchResultPage. 
       Toast.ShowToast(ResponseObject.message, SearchResultPage.Current.ToastGrid); 
      } 
      else 
      { 
       SearchApiResponse returnObject = null; 
       try 
       { 
        returnObject = new SearchApiCall().CallSearchApiAsync(param1, param2, param3).Result; 
       } 
       catch 
       { 
        return false; 
       } 
       ResponseObject = returnObject.response; 
      } 

      try 
      { 
       return ResponseObject.documents.Count > 0;           
      } 
      catch { return false; } 
     } 
    } 

    public IAsyncOperation<LoadMoreItemsResult> LoadMoreItemsAsync(uint count) 
    { 
     CoreDispatcher coreDispatcher = Window.Current.Dispatcher; 

     return Task.Run<LoadMoreItemsResult>(async() => 
     {   
      await coreDispatcher.RunAsync(CoreDispatcherPriority.Normal,() => 
      { 
       foreach (var item in ResponseObject.documents) 
       {    
        this.Add(PrepareViewModel(item)); 
       } 
      }); 

      await Task.Delay(350);     
      return new LoadMoreItemsResult() { Count = count }; 

     }).AsAsyncOperation<LoadMoreItemsResult>(); 
    } 

    public MyViewModel PrepareViewModel(Document document) 
    { 
     viewModel = new MyViewModel(); 

     viewModel.property1 = document.value1; 
     viewModel.property2 = document.value2; 

     ... 
     ... 

     if(SearchResultDataStore.ShowImage) 
     {    
      //thumbnailUrl is a string. 
      viewModel.ThumbnailImage = document.thumbnailUrl; 
     } 
     else 
     { 
      viewModel.ThumbnailImage = "somegarbage.png"; 
     } 

     ... 
     ... 

     return viewModel; 
    } 

} 
+0

ソースはBitmapImageを使用する必要があります。 – lindexi

+0

私もそれを試してみましたが、助けにはならない、同じ結果 –

+0

UWPコミュニティツールキットは 'ImageEx'コントロールを持っています。あなたはそれを見てください。 – AVK

答えて

0

あなたがのためにx:Bindを使用しているときソースはバインディングが自動的に更新されません。 これが実際に問題の根本的な原因であることを確認するには、バリューコンバータにブレークポイントを設定し、何回呼び出されたかを確認します。

私はあなたが背後にあるコード内でINotifyPropertyChangedのを実装する必要がある場合がありますx:Bind ThumbnailImage, Mode=OneWay

を使用してお勧めしたいです。

0

は、いくつかの手順を行います

  1. Imageコントロールにx:Phase属性を追加します。他の値よりも大きく設定してください(たとえば、すべてが "0"、 "1"など)

  2. からImageを追加すると、プロパティが変更されるタイミングを知る必要があるためです。

  3. Imageコントロールに依存プロパティーImagePathを追加します。プロパティが変更されるとき - >画像を非同期的にネットから読み込み始めます(例:HttpClient)。要求が完了すると - >コンテンツを入手してBitmapSourceに入れてSourceプロパティのImageに入れます。

それが本当かどうので、Imageコントロールのサイズよりも、元の画像のサイズがはるかにないことを確認してください - > UIがハングアップになります。

関連する問題