我正在使用LongListSelector在Windows Phone 8上的XAML和C#中进行无限滚动。要显示的项目从Web订阅源加载并使用数据绑定显示,每个项目的一个字段是也从Web加载的图像。
图像尺寸各不相同,但我没有在图像控制中设置宽度或高度,只是Margin="10"
,因此它填充了屏幕的宽度,并且是图像的正确高度。 / p>
DataTemplate中的图像控件如下所示:
<Image Source="{Binding Source.ImageUrl}" Margin="10" Stretch="UniformToFill" />
但是,我得到一个System.Windows.LayoutCycleException
,上面写着:“检测到布局周期。布局无法完成。”。
这似乎是由于在下载图像之前将<Image>
控件放入LongListSelector这一事实。然后,下载图像后,<Image>
控件会调整大小,从而导致错误。如果我在Height="300"
控件上设置了<Image>
,我就不会得到例外。
我仍然希望在下载图像之前显示Feed,并且可能在Feed中有很多图像,因此需要在内存使用时高效。
这个问题有解决方案吗?
答案 0 :(得分:1)
应该使用Uniform来填充宽度而不是UniformToFill(因为填充的均匀性将尝试填充“高度”,因为没有定义高度我可以看到它在物品被回收时导致问题)
也许您可以尝试限制同时加载的图像数量,例如,以下代码将使用atached属性一次加载一个(您可以适应加载多个)。对于AsyncLock,您可以使用here中的代码(或在线搜索)
public static readonly DependencyProperty LimitedImageProperty = DependencyProperty.RegisterAttached(“LimitedImage”,typeof(string),typeof(LimitImageDownloadConverter),new PropertyMetadata(default(string),LimitedImagedChanged));
public static void SetLimitedImage(UIElement element, string value)
{
element.SetValue(LimitedImageProperty, value);
}
public static string GetLimitedImage(UIElement element)
{
return (string) element.GetValue(LimitedImageProperty);
}
AsyncLock imageLock = new AsyncLock();
private static async void LimitedImagedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Image currentImage = d as Image;
object dataContext = currentImage.DataContext;
string uri = e.NewValue as string;
if (string.IsNullOrEmpty(uri))
{
return;
}
using (await imageLock.AcquireLock())
{
if (currentImage.DataContext != dataContext)
{
//Item jhave been recycled
return;
}
await LoadImage(currentImage, uri);
}
}
private static Task<bool> LoadImage(Image image, string uri)
{
TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>();
BitmapImage bitmap = new BitmapImage(new Uri(uri));
bitmap.ImageOpened += (send, arg) =>
{
tcs.SetResult(true);
};
bitmap.ImageFailed += (send, arg) =>
{
tcs.SetResult(false);
};
return tcs.Task;
}
然后只需使用local:MyAttatchedProperty.LimitedImage
在图片上设置图片来源,而不是直接使用ImageSource。