如何在Windows商店应用程序中将延迟加载应用于bing ListView?

时间:2016-04-26 11:49:36

标签: c# windows-store-apps win-universal-app

我正在开发Windows应用商店应用的销售应用。我想为我的产品模块应用延迟加载。

当产品页面打开时,它从后端获取产品并在ListBox控件中显示。 每次加载都需要时间。我认为主要原因是当我检查给定网址上存在的图像时。

这是我的代码和类:

SysDatabaseLogWizard

类别:

private async Task getAllProductDetails()
{
    var resultproductlist = await client.PostAsync(session.Values["URL"] + "/magemobpos/product/getProductList", contents);
    if (resultproductlist.IsSuccessStatusCode)
    {
        string trys = resultproductlist.Content.ReadAsStringAsync().Result;
        List<Productlistdata> objProducts = JsonConvert.DeserializeObject<ProductlistResponse>(trys).productlistdata;
        Productlistdata Product;

        //all product are in objProducts
        foreach (var item in objProducts)
        {
            bool imageexist = false;
            //check if image exist on given url or not
            try
            {
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri(item.image.ToString()));
                using (var response = (HttpWebResponse)(await Task<WebResponse>.Factory.FromAsync(request.BeginGetResponse, request.EndGetResponse, null)))
                {

                    int imagelength = Convert.ToInt32(response.ContentLength);
                    if (imagelength > 0)
                        imageexist = true;
                    else
                        imageexist = false;
                }
            }
            catch (Exception)
            {
                imageexist = false;
            }

            //if image not exist, it get default image
            if (item.image.ToString().ToLower().Equals("n/a") || imageexist == false)
            {
                item.image = "Images/NoDataImages/ico-no-orders.png";
            }

            Product = new Productlistdata()
            {
                image = item.image,
                name = item.name,
                price = item.price,
                sku = item.sku,
                type = item.type[0],
                id = item.id
            };
            //add all product in lstProduct. lstProduct is ListBox Control
            lstProduct.Items.Add(Product);      
        }
    }
}

有人可以建议我如何应用延迟加载吗?我不完全确切,但我认为一旦列表加载就可以应用于绑定图像。

4 个答案:

答案 0 :(得分:0)

我建议您更改查询,

首先代替getAllProductDetails执行getAllProductID 所以你在哪里

        var resultproductlist = await client.PostAsync(session.Values["URL"] + "/magemobpos/product/getProductList", contents);
        if (resultproductlist.IsSuccessStatusCode)
        {
            string trys = resultproductlist.Content.ReadAsStringAsync().Result;
            List<Productlistdata> objProducts = JsonConvert.DeserializeObject<ProductlistResponse>(trys).productlistdata;
            Productlistdata Product;
你会做的

        var resultproductlist = await client.PostAsync(session.Values["URL"] + "/magemobpos/product/getProductID", contents);
        if (resultproductlist.IsSuccessStatusCode)
        {
            string trys = resultproductlist.Content.ReadAsStringAsync().Result;
            List<int> objProducts = JsonConvert.DeserializeObject<ProductlistResponse>(trys).productlistdata;
            LazyProductlistdata Product;

其次创建一个包装器

public LazyProductlistdata
{
    public string id { get; set; }
    private Lazy<Productlistdata> data = new Lazy<Productlistdata>(()=>Productlistdata.CreateFromID(id));
    public Productlistdata Data
    {
       get{return data.Value;}
    }
}

展开它,以便包装器包含排序所需的信息

最后更改构造函数或为Productlistdata创建工厂,以便从源获取单个记录

public class Productlistdata
{
    public static Productlistdata CreateFromID(int id)
    {
         //Return single Productlistdata from webservice
    }
}

注意:延迟加载会增加整体加载时间,优势在于它不是一大块时间而是几个较小的加载时间

答案 1 :(得分:0)

我建议使用Converter来提供占位符see here

您还可以使用IsAsync = True来装饰Image.Source绑定 - 这样就不会阻止主线程

答案 2 :(得分:0)

您可以使用ImageFailed事件来指定图像占位符

foreach (var item in objProducts)
{
var bitmap = new BitmapImage();
bitmap.ImageFailed += (s, e) => bitmap.UriSource = defaultImageUri;
bitmap.UriSource = new Uri(item.image);
item.Add(bitmap);
//set decodepixelwidth and dicodepixelheight correctly to avoid outofmemory exception
}

答案 3 :(得分:0)

我知道你要求它,但我强烈建议你研究Bindings我相信它会帮助你思考你想要建立什么。因此,我将首先使用绑定更改一些代码,然后转到真正的解决方案。

以下是您可以尝试做的事情:

首先删除此代码:

bool imageexist = false;
        //check if image exist on given url or not
        try
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri(item.image.ToString()));
            using (var response = (HttpWebResponse)(await Task<WebResponse>.Factory.FromAsync(request.BeginGetResponse, request.EndGetResponse, null)))
            {

                int imagelength = Convert.ToInt32(response.ContentLength);
                if (imagelength > 0)
                    imageexist = true;
                else
                    imageexist = false;
            }
        }
        catch (Exception)
        {
            imageexist = false;
        }

第二步是摆脱这段代码

//add all product in lstProduct. lstProduct is ListBox Control
lstProduct.Items.Add(Product);   

现在在page.xaml.cs上添加一个ObservableCollection

private ObservableCollection<Productlistdata> productlist = new ObservableCollection<Productlistdata>();

    public ObservableCollection<Productlistdata> Productlist
    {
        get { return productlist ?? (productlist= new ObservableCollection<Productlistdata>()); }
        set { productlist= value; }
    }

现在您可以像这样

在列表框中绑定该列表
<ListBox ItemsSource="{Binding Productlist}"/>

或在页面的承包商中

lstProduct.ItemsSource = Productlist;

这样,Productlist会绑定到ListBox,当您添加或删除项目时,它会自动更新。

现在你可以跳过以上所有内容,但我建议你研究Bindings它的强大功能,并在你了解它们的工作原理时解决你的许多问题。

现在我们将添加我们在ProductListdata中删除的第一个代码

public class Productlistdata
{
    public string id { get; set; }
    public string sku { get; set; }
    public string name { get; set; }
    public string status { get; set; }
    public string qty { get; set; }
    public string price { get; set; }
    public string image { get; set; }
    public string type { get; set; }
    public string full_productname { get; set; }

    public async void CheckImage()
    {
        bool imageexist = false;
        try
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(new Uri(image));
            using (var response = (HttpWebResponse)(await Task<WebResponse>.Factory.FromAsync(request.BeginGetResponse, request.EndGetResponse, null)))
            {

                int imagelength = Convert.ToInt32(response.ContentLength);
                if (imagelength > 0)
                    imageexist = true;
                else
                    imageexist = false;
            }
        }
        catch (Exception)
        {
            imageexist = false;
        }
        if (!imageexist)
        {
            image = "Images/NoDataImages/ico-no-orders.png";
        }
    }
}

填充您的列表

private async Task getAllProductDetails()
    {
        var resultproductlist = await client.PostAsync(session.Values["URL"] + "/magemobpos/product/getProductList", contents);
        if (resultproductlist.IsSuccessStatusCode)
        {
            string trys = resultproductlist.Content.ReadAsStringAsync().Result;
            List<Productlistdata> objProducts = JsonConvert.DeserializeObject<ProductlistResponse>(trys).productlistdata;


            //all product are in objProducts
            foreach (var item in objProducts)
            {
                Productlistdata Product = new Productlistdata()
                {
                    image = item.image,
                    name = item.name,
                    price = item.price,
                    sku = item.sku,
                    type = item.type[0],
                    id = item.id
                };
                Product.CheckImage();
                Productlist.Add(Product);
            }
        }
    }

Product.CheckImage();将不会被等待。所以列表中的项目加载速度非常快,因为在foreach循环中没有等待的东西。 Product.CheckImage();将在以后的另一个线程上运行。

最后,因为在ListBoxa上加载数据后图像可能会发生变化(当图像不是fount时),您必须通知UI属性已更改。为此,您必须使用INotifyPropertyChanged。你可以看看我的另一个答案如何做here