Xaml 异步显示来自internet的图像

Xaml 异步显示来自internet的图像,xaml,uwp,Xaml,Uwp,在我的UWP应用程序中,我有一个带有增量加载的列表视图。现在,我还需要在列表视图项中包含一个图像。我试着直接给它URI 其中ThumbnailImage在我的视图模型中只是一个字符串。问题是,由于增量加载,当我向下滚动一点,而之前的图像仍在加载时,应用程序只是挂起。然而,如果我让所有的图像显示,然后向下滚动,它的工作很好 我还尝试了工具箱中的ImageEx控件,它也有同样的问题 我做了一些搜索,唯一找到的是在XAML中执行IsAsync=True。但似乎IsAsync在UWP中不可用 我的Vie

在我的UWP应用程序中,我有一个带有增量加载的
列表视图。现在,我还需要在
列表视图项中包含一个图像。我试着直接给它URI

其中
ThumbnailImage
在我的视图模型中只是一个字符串。问题是,由于增量加载,当我向下滚动一点,而之前的图像仍在加载时,应用程序只是挂起。然而,如果我让所有的图像显示,然后向下滚动,它的工作很好

我还尝试了工具箱中的
ImageEx
控件,它也有同样的问题

我做了一些搜索,唯一找到的是在XAML中执行IsAsync=True
。但似乎
IsAsync
在UWP中不可用

我的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;
    }

}
公共类项显示:ObservableCollection,ISupportIncrementalLoading
{
private SearchResponse ResponseObject{get;set;}=new SearchResponse();
MyViewModel viewModel=null;
公共物品
{
得到
{
if((string.IsNullOrEmpty(SearchResultDataStore.NextPageToken)和&!SearchResultDataStore.IsFirstRequest)| | SearchResultDataStore.StopIncrementalLoading)
返回false;
if(SearchResultDataStore.IsFirstRequest)
{
使用(var db=new DbContext())
{
var json=db.UpdateResponse.First(r=>r.LanguageId==DataStore.Language).JsonResponse;
Metadata=Newtonsoft.Json.JsonConvert.DeserializeObject(Json).response.Metadata.reply;
}
var returnObject=SearchResultDataStore.SearchResponse;
ResponseObject=returnObject.response;
//这将在一个名为SearchResultPage的xaml页面上显示一个包含一些消息的网格,持续3秒钟。
Toast.ShowToast(ResponseObject.message,SearchResultPage.Current.ToastGrid);
}
其他的
{
SearchApiResponse returnObject=null;
尝试
{
returnObject=new SearchApiCall().CallSearchApiAsync(param1,param2,param3).Result;
}
抓住
{  
返回false;
}
ResponseObject=returnObject.response;
}
尝试
{
返回响应object.documents.Count>0;
}
catch{return false;}
}
}
公共IAsyncOperation LoadMoreItemsAsync(uint计数)
{
corespatcher corespatcher=Window.Current.Dispatcher;