UWP Windows-10 更好的图片加载方式 [英] UWP Windows-10 Better way to load images

查看:41
本文介绍了UWP Windows-10 更好的图片加载方式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个面向 Windows UWP 桌面的 C# 应用程序.该应用程序显示图像列表.当用户点击列表视图中的任何图像时,应用程序将放大(详细视图)它&显示图像(由于图像尺寸较大,因此显示为全屏).
每当我单击列表视图中的任何图像时,详细视图中的图像首先显示之前加载的图像 &然后它刷新 &从当前选择加载图像
我想知道如何防止加载以前的图像,直到获取新图像?
目前,每当用户单击列表视图中的项目时,我都会先加载带有空白图像的详细视图图像源 &然后获取所需的图像 &加载它.
我的代码在这里:

I have a C# app targeting Windows UWP Desktop. The app displays list of images. When user clicks on any of the image in the List View, app would enlarge(detailed view) it & show the image(kind of full screen as the image size is bigger).
Whenever I click any image in the list view, the image in the detailed view first shows the previously loaded image & then it refreshes & load's the image from the current selection
I want to know how to prevent loading the previous image until, new image is fetched?
Currently, whenever user clicks an item in list view, I load the detail view image source with a blank image first & then fetch the required image & load it.
My code is here:

 await CallOnUiThreadAsync(() =>
 {
    /*Load empty image first*/
    imgBitmap = new BitmapImage();
    var uri = new System.Uri("ms-appx:///Assets/emptyImage.png");
    imgBitmap.UriSource = uri;
    img.Source = imgBitmap;
  });

  if (("/Assets/emptyImage.png" != url) || (url != String.Empty))
  {
      await Task.Run(async () =>
      {
        /*image_fetch is our proprietary api. It returns a byte array*/
        byte[] imageBytes = image_fetch;
        MemoryStream stream = new MemoryStream(imageBytes, 0, imageBytes.Length, true);
        var randomAccessStream = new MemoryRandomAccessStream(stream);
        await CallOnUiThreadAsync(async () =>
        {
            imgBitmap = new BitmapImage();
            await imgBitmap.SetSourceAsync(randomAccessStream);
            img.Source = imgBitmap;
         });
       });
   }


我已经在后台线程中运行 image_fetch,但我仍然看到从用户单击列表视图项到在详细视图中加载图像之间的一小段延迟.
我想减少延迟.除了加载空白图片之外,还有更好的方法吗?


I am already running image_fetch in a background thread, still I see a small lag from the time user clicks list view item until the image loads in detail view.
I would like to reduce the lag. Is there a better way of doing that other than loading blank image?

推荐答案

每当我单击列表视图中的任何图像时,详细视图中的图像首先显示之前加载的图像 &然后它刷新 &从当前选择加载图像.

Whenever I click any image in the list view, the image in the detailed view first shows the previously loaded image & then it refreshes & load's the image from the current selection.

我认为问题在于您的 Mater/Detail 结构是如何实现的.从您的代码中我可以看到您可能从文件中读取图像并将 BitmapImage 设置为 ListView 中的 Image 源,在这里我创建了一个示例,当窗口宽度超过720时,Detail会显示在Master的右侧,如果宽度小于720,则Detail会被放大(全屏).

I think the problem is how your Mater/Detail structure implemented is. From your code I can see that you probably read images from file and set BitmapImage to the source of Image in the ListView, here I created a sample, when the window's width is over 720, the Detail will be shown at the right of the Master, and if the width is less than 720, the Detail will be enlarged(full screen).

我的主页:

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup x:Name="AdaptiveStates">
            <VisualState x:Name="DefaultState">
                <VisualState.StateTriggers>
                    <AdaptiveTrigger MinWindowWidth="720" />
                </VisualState.StateTriggers>
            </VisualState>

            <VisualState x:Name="NarrowState">
                <VisualState.StateTriggers>
                    <AdaptiveTrigger MinWindowWidth="0" />
                </VisualState.StateTriggers>

                <VisualState.Setters>
                    <Setter Target="MasterColumn.Width" Value="*" />
                    <Setter Target="DetailColumn.Width" Value="0" />
                    <Setter Target="MasterListView.SelectionMode" Value="None" />
                </VisualState.Setters>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>

    <Grid.ColumnDefinitions>
        <ColumnDefinition x:Name="MasterColumn" Width="320" />
        <ColumnDefinition x:Name="DetailColumn" Width="*" />
    </Grid.ColumnDefinitions>

    <ListView x:Name="MasterListView" Grid.Column="0" ItemContainerTransitions="{x:Null}"
        IsItemClickEnabled="True" ItemClick="MasterListView_ItemClick" ItemsSource="{x:Bind itemcollection}">
        <ListView.ItemContainerStyle>
            <Style TargetType="ListViewItem">
                <Setter Property="HorizontalContentAlignment" Value="Stretch" />
            </Style>
        </ListView.ItemContainerStyle>
        <ListView.ItemTemplate>
            <DataTemplate x:DataType="local:TestItem">
                <Image Source="{x:Bind ImageItem}" />
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>

    <ContentPresenter x:Name="DetailContentPresenter" Grid.Column="1" BorderThickness="1,0,0,0"
        Padding="24,0" BorderBrush="{ThemeResource SystemControlForegroundBaseLowBrush}"
        Content="{x:Bind MasterListView.SelectedItem, Mode=OneWay}">
        <ContentPresenter.ContentTemplate>
            <DataTemplate x:DataType="local:TestItem">
                <Image Source="{x:Bind ImageItem}" />
            </DataTemplate>
        </ContentPresenter.ContentTemplate>
    </ContentPresenter>
</Grid>

背后的代码:

private ObservableCollection<TestItem> itemcollection = new ObservableCollection<TestItem>();

public MainPage()
{
    this.InitializeComponent();
}

protected override async void OnNavigatedTo(NavigationEventArgs e)
{
    StorageFolder picLib = KnownFolders.PicturesLibrary;
    var picfiles = await picLib.GetFilesAsync();
    foreach (var pic in picfiles)
    {
        BitmapImage bmp = new BitmapImage();
        IRandomAccessStream stream = await pic.OpenReadAsync();
        bmp.SetSource(stream);
        itemcollection.Add(new TestItem { ImageItem = bmp });
    }
}

private void MasterListView_ItemClick(object sender, ItemClickEventArgs e)
{
    var clickedItem = (TestItem)e.ClickedItem;

    if (AdaptiveStates.CurrentState == NarrowState)
    {
        Frame.Navigate(typeof(DetailPage), clickedItem);
    }
}

我的详细信息页面:

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Image Source="{x:Bind image}" />
</Grid>

背后的代码:

private BitmapImage image;

public DetailPage()
{
    this.InitializeComponent();
}

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    base.OnNavigatedTo(e);

    var testitem = e.Parameter as TestItem;
    image = testitem.ImageItem;

    var backStack = Frame.BackStack;
    var backStackCount = backStack.Count;

    if (backStackCount > 0)
    {
        var masterPageEntry = backStack[backStackCount - 1];
        backStack.RemoveAt(backStackCount - 1);

        // Doctor the navigation parameter for the master page so it
        // will show the correct item in the side-by-side view.
        var modifiedEntry = new PageStackEntry(
            masterPageEntry.SourcePageType,
            e.Parameter,
            masterPageEntry.NavigationTransitionInfo
            );
        backStack.Add(modifiedEntry);
    }

    // Register for hardware and software back request from the system
    SystemNavigationManager systemNavigationManager = SystemNavigationManager.GetForCurrentView();
    systemNavigationManager.BackRequested += DetailPage_BackRequested;
    systemNavigationManager.AppViewBackButtonVisibility = AppViewBackButtonVisibility.Visible;
}

protected override void OnNavigatedFrom(NavigationEventArgs e)
{
    base.OnNavigatedFrom(e);

    SystemNavigationManager systemNavigationManager = SystemNavigationManager.GetForCurrentView();
    systemNavigationManager.BackRequested -= DetailPage_BackRequested;
    systemNavigationManager.AppViewBackButtonVisibility = AppViewBackButtonVisibility.Collapsed;
}

private void OnBackRequested()
{
    Frame.GoBack();
}

private void DetailPage_BackRequested(object sender, BackRequestedEventArgs e)
{
    e.Handled = true;
    OnBackRequested();
}

我的 TestItem 类在这里非常简单:

And my TestItem class is quite simple here:

public class TestItem
{
    public BitmapImage ImageItem { get; set; }
}

您也可以参考官方主/细节示例.我是根据这个官方的sample写的,这里的重点是:

You can also refer to the official Master/detail sample. I wrote my sample according to this official sample, the key-points here are:

  • 创建并排的母版/详细信息页面.

  • Creating a side-by-side master/detail page.

在主列表和详细视图之间导航.

Navigating between the master list and detail view.

在调整应用大小时更改导航模型.

Changing the navigation model when the app is resized.

我已经在后台线程中运行 image_fetch,但我仍然看到从用户单击列表视图项到在详细视图中加载图像的时间有一点延迟.

I am already running image_fetch in a background thread, still I see a small lag from the time user clicks list view item until the image loads in detail view.

您是否每次单击 ListViewItem 时都获取图像源(例如从文件中),那么您可以将图像源设置为详细信息框架吗?这里使用 DataBinding,当您想向 ListView 添加数据时,您可以获取所有图像.

Did you fetch Image source(from file for example) each time you clicked the ListViewItem, so can you set the image source to the detail frame? Here using DataBinding, you can just fetch all the images when you want to add data to your ListView.

这篇关于UWP Windows-10 更好的图片加载方式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆