我从web保存图像,将其加载到BitmapImage并尝试将图像控件与一些文本块绑定到BitmapImage。问题是即使我调用NotifyPropertyChanged也不显示图片。我可能会错过一些东西。
这是我的代码:
public class MovieData : INotifyPropertyChanged
{
public int ID { get; set; }
public bool Today { get; set; }
public string DetailsUrl { get; set; }
public string Title { get; set; }
public string Country { get; set; }
public string Year { get; set; }
public string Director { get; set; }
public string Genre { get; set; }
public string Duration { get; set; }
public string Restriction { get; set; }
public string Description { get; set; }
public string Poster { get; set; }
public BitmapImage PosterLocal;
public string LargePoster { get; set; }
public BitmapImage LargePosterLocal { get; set; }
public DateTime AirDate { get; set; }
public DateTime LastDate { get; set; }
public string Cinema { get; set; }
public string IsDetailsLoaded { get; set; }
public HttpResponseMessage HtmlRequest { get; set; }
private static CancellationTokenSource _cts = new CancellationTokenSource();
public bool IsTaskCanceled = false;
public async Task<bool> GetDetailsAsync()
{
if (this.Year == null)
{
this.IsDetailsLoaded = "visible";
NotifyPropertyChanged("IsDetailsLoaded");
Uri uri = new Uri(this.DetailsUrl);
HttpClient client = new HttpClient();
HtmlDocument htmlDocument = new HtmlDocument();
HtmlNode htmlNode = new HtmlNode(0, htmlDocument, 1);
MovieData Item = new MovieData();
string HtmlResult;
try
{
HtmlRequest = await client.GetAsync(uri, _cts.Token);
HtmlResult = await HtmlRequest.Content.ReadAsStringAsync();
}
catch (System.Net.Http.HttpRequestException e)
{
Console.Out.WriteLine(e.Message);
HtmlResult = null;
this.IsDetailsLoaded = "Collapsed";
NotifyPropertyChanged("IsDetailsLoaded");
}
catch (System.Threading.Tasks.TaskCanceledException e)
{
Console.Out.WriteLine(e.Message);
HtmlResult = null;
this.IsDetailsLoaded = "Collapsed";
NotifyPropertyChanged("IsDetailsLoaded");
}
if (!(HtmlResult == null) && HtmlRequest.IsSuccessStatusCode)
{
await this.DownloadPosterAsync();
NotifyPropertyChanged("PosterLocal");
htmlDocument.LoadHtml(HtmlResult);
this.LargePoster = htmlDocument.DocumentNode.SelectSingleNode("//div[@class='cinema_img']/a").GetAttributeValue("href", "No poster image");
NotifyPropertyChanged("LargePoster");
await this.DownloadLargePosterAsync();
NotifyPropertyChanged("LargePosterLocal");
htmlNode = htmlDocument.DocumentNode.SelectSingleNode("//div[@class='cinema_desc']");
this.Title = GetStringFromNode(htmlNode.SelectSingleNode("h1"));
NotifyPropertyChanged("Title");
this.Country = GetStringFromNode(htmlNode.SelectSingleNode("p[2]"));
NotifyPropertyChanged("Country");
this.Year = GetStringFromNode(htmlNode.SelectSingleNode("p[3]"));
NotifyPropertyChanged("Year");
this.Director = GetStringFromNode(htmlNode.SelectSingleNode("p[4]"));
NotifyPropertyChanged("Director");
this.Genre = GetStringFromNode(htmlNode.SelectSingleNode("p[6]"));
NotifyPropertyChanged("Genre");
this.Duration = GetStringFromNode(htmlNode.SelectSingleNode("p[7]"));
NotifyPropertyChanged("Duration");
this.Restriction = GetStringFromNode(htmlNode.SelectSingleNode("p[8]"));
NotifyPropertyChanged("Restriction");
this.Description = GetStringFromNode(htmlNode.SelectSingleNode("p[9]/p"));
NotifyPropertyChanged("Description");
this.AirDate = GetAirDate(htmlNode.SelectSingleNode("p[1]"));
NotifyPropertyChanged("AirDate");
this.LastDate = GetLastDate(htmlNode.SelectSingleNode("p[1]"));
NotifyPropertyChanged("LastDate");
this.IsDetailsLoaded = "Collapsed";
NotifyPropertyChanged("IsDetailsLoaded");
}
}
return true;
}
#region public async Task<bool> DownloadPosterAsync() //Method for download images from web and save them to isolated storage with same name.
public async Task<bool> DownloadPosterAsync()
{
WebClient client = new WebClient(); //Instantiate WebClient
var isoStore = IsolatedStorageFile.GetUserStoreForApplication();
string DestFileName = "small\\"+Path.GetFileName(this.Poster);
if (!isoStore.FileExists(DestFileName))
{
client.OpenReadAsync(new Uri(this.Poster));
client.OpenReadCompleted += (s, e) => //Wait for completion
{
if (!isoStore.DirectoryExists("small"))
{
isoStore.CreateDirectory("small");
}
var tempBitmap = new BitmapImage(); //Create temp bitmap container
tempBitmap.SetSource(e.Result); //Copy stream to bitmap container
var writeableBitmap = new WriteableBitmap(tempBitmap); //Create WriteableBitmap out of temp bitmap
using (var isoFileStream = isoStore.CreateFile(DestFileName)) //Create file in Isolated Storage
{
var width = writeableBitmap.PixelWidth; //Set attributes
var height = writeableBitmap.PixelHeight; // Set some more
Extensions.SaveJpeg(writeableBitmap, isoFileStream, width, height, 0, 100); //Finally save .jpeg
}
};
}
BitmapImage image = null;
using (var imageStream = await LoadImageAsync(DestFileName))
{
if (imageStream != null)
{
image = new BitmapImage();
image.SetSource(imageStream);
}
}
this.PosterLocal = image;
return true;
}
#endregion
和XAML大块:
<phone:PhoneApplicationPage.Resources>
<DataTemplate x:Key="MoviesDataTemplate">
<Grid Margin="12,7,0,5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Image Source="{Binding PosterLocal}" Width="99" Height="136" Grid.Column="0" Stretch="UniformToFill" CacheMode="BitmapCache"/>
<StackPanel Margin="0,0,0,0" Grid.Column="1">
<TextBlock Text="{Binding Title}" TextWrapping="NoWrap" Margin="12,0,0,0" Style="{StaticResource PhoneTextExtraLargeStyle}"/>
<TextBlock TextWrapping="Wrap" Margin="12,0,0,0" Style="{StaticResource PhoneTextAccentStyle}">
<Run Text="{Binding AirDate, StringFormat=MMMM dd\, yyyy}" ></Run>
</TextBlock>
<!--<TextBlock Text="{Binding AirTimes}" TextWrapping="Wrap" Margin="12,0,0,0" Style="{StaticResource PhoneTextSubtleStyle}"/>-->
<ProgressBar IsIndeterminate="True" Visibility="{Binding IsDetailsLoaded}" Margin="0,12"></ProgressBar>
</StackPanel>
</Grid>
</DataTemplate>
</phone:PhoneApplicationPage.Resources>
我搜索SO并发现了很多主题,但没有找到解决方案。我想我的问题是在Datacontext分配后加载图像,而NotifyPropertyChanged对位图图像不起作用,因为每个over属性同时分配并显示在控件中。我还检查了实际下载的图像,存储在Isolated Storage中并加载了。 (硬编码图像属性,它工作)。有关如何进行装订工作的任何建议吗?
答案 0 :(得分:2)
您应该Bind to properties,并且在您提供的代码中,PosterLocal
不是属性。在这种情况下,您可以尝试使用PosterLocal
:
public BitmapImage PosterLocal
{
get
{
BitmapImage temp = new BitmapImage();
using (IsolatedStorageFile ISF = IsolatedStorageFile.GetUserStoreForApplication())
using (IsolatedStorageFileStream file = ISF.OpenFile(posterLocal, FileMode.Open, FileAccess.Read))
temp.SetSource(file);
return temp;
}
}
private string posterLocal; // this in case you probably will need to save somewhere the file name
如果您只需要PosterLocal
绑定(单向),那么getter就足够了。您使用string posterLocal
更改的文件名。
在这种情况下,您不再需要DownloadPosterAsync
中的部分代码 - 将使用PropertyChanged激活getter。将文件保存到IS之后:
posterLocal = DestFileName;
答案 1 :(得分:0)
using(var targetFile=System.IO.IsolatedStorage.IsolatedStorageFile.GetUserStoreForApplication()
.OpenFile("fileName", FileMode.Open))
{
PosterLocal = PictureDecoder.DecodeJpeg(targetFile, 100, 100);
}