我正在搞乱一些Windows手机开发,因为我刚从Android背景来看它。
我正在使用" theCatAPI"加载猫的随机图片并显示它,然后当点击图片时,或屏幕底部的按钮,图像刷新到新的。
到目前为止,我有以下内容:
XAML:
<Page
x:Class="CatFactsPics.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:CatFactsPics"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid x:Name="LayoutRoot">
<Grid.ChildrenTransitions>
<TransitionCollection>
<EntranceThemeTransition/>
</TransitionCollection>
</Grid.ChildrenTransitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- TitlePanel -->
<StackPanel Grid.Row="0" Margin="24,17,0,28">
<TextBlock Text="My Application" Style="{ThemeResource TitleTextBlockStyle}" Typography.Capitals="SmallCaps"/>
<TextBlock Text="page title" Margin="0,12,0,0" Style="{ThemeResource HeaderTextBlockStyle}"/>
</StackPanel>
<!--TODO: Content should be placed within the following grid-->
<Grid Grid.Row="1" x:Name="ContentRoot">
<Image HorizontalAlignment="Center" Stretch="UniformToFill" VerticalAlignment="Center" x:Name="KittyPic" Tapped="KittyPic_Tapped"/>
<Button HorizontalAlignment="Center" VerticalAlignment="Bottom" x:Name="newPic" Click="newPic_Click" >New Kitty</Button>
</Grid>
</Grid>
</Page>
并在page.cs中:
...
protected override void OnNavigatedTo(NavigationEventArgs e)
{
this.navigationHelper.OnNavigatedTo(e);
Uri myUri = new Uri("http://thecatapi.com/api/images/get?format=src&type=jpg", UriKind.Absolute);
KittyPic.Source = new BitmapImage(myUri);
}
...
private void newPic_Click(object sender, RoutedEventArgs e)
{
Uri myUri = new Uri("http://thecatapi.com/api/images/get?format=src&type=jpg", UriKind.Absolute);
BitmapImage bmi = new BitmapImage();
bmi.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
bmi.UriSource = myUri;
KittyPic.Source = bmi;
}
我有几个问题:
1)这是正确的做事方式吗?在Android中,我尝试异步操作以避免拖延UI线程。话虽这么说,我似乎对他们现在的问题没有任何问题。我不熟悉Windows的做事方式,并且没有找到任何资源给出任何解释或建议。
2)在新图像重新出现之前,显示新图像会导致图像视图变黑的短(几秒)周期延迟。有没有办法设置它,所以要么旧图片保持不变,直到新的图片可以显示,或者显示占位符&#34; loading&#34;图像直到新的可以替换它。
关于如何做事的任何其他建议或提示都会很棒,谢谢。
答案 0 :(得分:5)
1)使用当前代码,您不会阻止UI线程,因为您在UI线程上设置URI
,但实际加载的图像是在另一个线程上自动完成的。 (对于手动下载图像,字符串等,您可能会使用async/await来避免锁定UI线程。)
2)图像变黑,因为您在加载新图像之前更改了ImageSource
。你提到了几种解决这个问题的方法。但大多数情况下常见的是,您需要在Image控件上使用ImageOpened
和ImageFailed
事件,每当图像加载完成时触发(或发生错误,例如没有互联网连接) )。下面是一个在加载时显示加载栏的示例,它只是隐藏/显示加载进度:
在page.xaml
文件中:
<Grid Grid.Row="1" x:Name="ContentRoot">
<Image x:Name="KittyPic" Tapped="KittyPic_Tapped" ImageOpened="KittyPic_ImageOpened" ImageFailed="KittyPic_ImageFailed" />
<StackPanel x:Name="LoadingPanel" VerticalAlignment="Center">
<ProgressBar IsIndeterminate="True" IsEnabled="True" />
<TextBlock Text="Loading image..." HorizontalAlignment="Center" />
</StackPanel>
</Grid>
并在page.xaml.cs文件中
private void KittyPic_Tapped(object sender, TappedRoutedEventArgs e)
{
LoadingPanel.Visibility = Visibility.Visible;
Uri myUri = new Uri("http://thecatapi.com/api/images/get?format=src&type=jpg", UriKind.Absolute);
BitmapImage bmi = new BitmapImage();
bmi.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
bmi.UriSource = myUri;
KittyPic.Source = bmi;
}
private void KittyPic_ImageOpened(object sender, RoutedEventArgs e)
{
LoadingPanel.Visibility = Visibility.Collapsed;
}
private async void KittyPic_ImageFailed(object sender, ExceptionRoutedEventArgs e)
{
LoadingPanel.Visibility = Visibility.Collapsed;
await new MessageDialog("Failed to load the image").ShowAsync();
}
而不是TextBlock
和ProgressBar
,您当然可以显示您想要的任何内容,或者例如在两个图像之间交换以继续显示旧图像。
对于其他建议,我认为当你习惯了基础知识时,请查看data bindings,这是非常有用和强大的。另请查看有关MVVM pattern。
的文章答案 1 :(得分:2)
1)这是正确的做事方式吗?
没有。不是。您绝对应该采用MVVM模式并从您的视图中分离您的业务逻辑 - 这意味着您不应该在视图的代码隐藏中创建位图图像或请求/分配此类远程图像URL。您应该在ViewModel中执行此类操作并将它们绑定到View。
因此,在您的情况下,您的ViewModel(实现INotifyPropertyChanged)中将会有一个Uri(或您将指定远程URL的字符串)属性,然后在您的View中,您将绑定它:
<!--TODO: Content should be placed within the following grid-->
<Grid Grid.Row="1" x:Name="ContentRoot">
<BitmapImage UriSource="{Binding BackGroundImage}" CreateOptions="BackgroundCreation" />
<Button HorizontalAlignment="Center" VerticalAlignment="Bottom" x:Name="newPic" Click="newPic_Click" >New Kitty</Button>
</Grid>
每当你设置BackGroundImage属性时,你将引发一个名为的事件;
RaisePropertyChanged("BackGroundImage")
- &gt;这是传统的MVVM方法。
这样您的视图就会意识到BackGroundImage已更改,并且会自动加载它。 (但请注意,如果你只为这个BackGroundImage提供一个字符串 - 你将不得不使用转换器,一个字符串到Uri转换器,因为它只接受Uri用于远程图像)
2)&#34; ...是否有一种设置方式,以便旧图片保持不变,直到新图片保持准备好显示,或者显示占位符&#34; loading&#34;图像,直到新的可以替换它。&#34;
我建议你去展示一个&#39; loading&#39;图片。我遇到了与此处完全相同的问题,我的解决方法是插入加载图像并将其不透明度值设置为0.1 - 以及实际图像。当您在远程URL之间切换时,当前一个图像消失时,会出现不透明的加载图像,并且当加载下一个实际图像时,不会显示加载图像,因为新图像会覆盖它。