首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >UWP Windows-10加载图像的更好方法

UWP Windows-10加载图像的更好方法
EN

Stack Overflow用户
提问于 2016-05-27 04:44:48
回答 2查看 8.9K关注 0票数 2

我有一个针对Windows桌面的C#应用程序。该应用程序显示图像列表。当用户单击列表视图中的任何图像时,应用程序会放大(详细视图)它&显示图像(随着图像大小的增大,会显示出某种全屏)。

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

我想知道如何防止加载之前的图像,直到,新的图像是取回?

当前,每当用户单击列表视图中的项时,我首先用空白图像加载详细视图图像源,然后获取所需的图像并加载它。

我的密码在这里:

代码语言:javascript
运行
复制
 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,但从用户单击列表视图项到图像加载细节视图为止,我仍然看到了一个小的滞后。

我想减少延迟。除了加载空白图像之外,还有其他更好的方法吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-05-30 08:04:20

每当我单击列表视图中的任何图像时,详细视图中的图像首先显示以前加载的图像,然后刷新和加载当前选择的图像。

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

我的MainPage:

代码语言:javascript
运行
复制
<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>

代码背后:

代码语言:javascript
运行
复制
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);
    }
}

我的详细资料页:

代码语言:javascript
运行
复制
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Image Source="{x:Bind image}" />
</Grid>

代码背后:

代码语言:javascript
运行
复制
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类在这里非常简单:

代码语言:javascript
运行
复制
public class TestItem
{
    public BitmapImage ImageItem { get; set; }
}

您也可以参考官方的主/详细样本。我根据这个官方的例子写了我的样本,这里的要点是:

  • 创建一个并行的主/详细信息页面。
  • 在主列表和详细信息视图之间导航。
  • 当应用程序调整大小时,更改导航模型。

我已经在后台线程中运行image_fetch,但从用户单击列表视图项到图像加载细节视图为止,我仍然看到了一个小的滞后。

您是否每次单击ListViewItem时都会获取图像源(例如从文件中获取),那么您能将图像源设置为详细帧吗?在这里,使用DataBinding,当您想要向ListView添加数据时,您可以只获取所有的图像。

票数 3
EN

Stack Overflow用户

发布于 2017-01-02 22:51:42

您可以使用FFImageLoading,它使用各种方法优化图像加载(包括下载/内存缓存):

XML <ff:FFImage VerticalAlignment="Stretch" HorizontalAlignment="Stretch" TransformPlaceholders="False" LoadingPlaceholder="loading.png" ErrorPlaceholder="error.png" Height="500" Width="500" Source="http://loremflickr.com/600/600/nature?filename=simple.jpg">

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37475023

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档