2017-09-19 40 views
2

在我的UWP應用程序中,我有一個帶有增量加載的ListView。現在我需要在ListViewItem中加入一張圖片。我試着直接給它的URI。異步顯示來自互聯網的圖像

其中ThumbnailImage只是我的視圖模型中的一個字符串。這個問題是由於增量加載,當我向前滾動一點點,而以前的圖像仍在加載時,應用程序只是掛起。而如果我讓所有的圖像出現,然後向下滾動,它工作正常。

我也試過從工具包中的ImageEx控件,它也有同樣的問題。

我做了一些搜索,我發現唯一的東西是在XAML中的doing IsAsync = True。但似乎IsAsync在UWP中不可用。

我的視圖模型:

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爲綁定的源不會自動更新。 要驗證這實際上是問題的根本原因,可以在值轉換器中設置斷點,並查看調用了多少時間。

我建議使用x:Bind ThumbnailImage, Mode=OneWay

你可能在你的代碼來實現INotifyPropertyChanged的後面。

0

讓幾個步驟:

  1. 添加x:Phase屬性Image控制。設置最大比其他值(例如所有都是「0」,設置「1」等)

  2. Mode=OneWay添加到Image因爲你應該知道什麼時候財產將被改變。

  3. 將控制擴展名添加到Image控制與依賴屬性ImagePath。當屬性將被改變時 - >開始以異步方式從網絡加載圖像(例如HttpClient)。當請求完成時 - >獲取內容並將其寫入BitmapSource,並將其放入的Image屬性中。

確保原始圖像的大小沒有太大的超過Image控件的大小,因爲如果這是真的 - > UI會掛起。