从隔离存储装入的图像根本不具有约束力

时间:2014-02-20 18:51:11

标签: c# wpf xaml windows-phone-8

我从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中并加载了。 (硬编码图像属性,它工作)。有关如何进行装订工作的任何建议吗?

2 个答案:

答案 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);
}