简体   繁体   中英

Display multiple lists in C#

I have a list of products, and the list will dynamically grow as more users add to it. I would like to have this list, say:

public class Product()
{
   public int ProductId { get; set; } 
   public string ProductName { get; set; } 
   public DateTime ProductDateCreated{ get; set; }
   //....
}

But, for every, say, five items listed, I want to display another item from a different list, so say my Advert list.

public class Advert()
{
   public int AdvertId { get; set; } 
   public string AdvertName { get; set; } 
   public int AdvertView{ get; set; } 
}

var products = db.Products.OrderBy(d=>d.ProductDateCreated).ToList();

--product1
--product2
--product3
--product4
--Advert2   <-- Insert here some how as it has a higher AdvertView than Advert1
--product5
--product6
--product7
--product8
--product9
--Advert1    <-- Insert here some how as it has a lower AdvertView than Advert2

The best way I can describe this is like adverts on Facebook where, as you scroll down, you are presented with adverts now and again.

I use lambda expressions querying my database, but I cannot think where to start with this.

I would create a base class that contains properties, which exist in both classes (name, id,..?):

public class Product: Items
{      
    public DateTime ProductDateCreated { get; set; }
    //....
}

public class Advert: Items
{

    public int AdvertView { get; set; }
}

public class Items //Advert and Products
{
    public int Id { get; set; }
    public string Name { get; set; }
}

And fill it as you asked with Advert every 5th item.

List<Advert> adverts = db.Adverts.OrderByDescending(a => a.AdvertView).ToList();
List<Product> products = db.Products.OrderBy(d => d.ProductDateCreated).ToList();
List<Items> ResultList = new List<Items>();
for (int i = 0; i < products.Count; i++)
{
    ResultList.Add(products[i]);
    if ((i + 1) % 5 == 0)
    {
        int advertsIndex = i / 5;
        if (adverts.Count + 1 >= advertsIndex)
            ResultList.Add(adverts[advertsIndex]);
    }
}

Select products page by page, and add the products in the page to a base list. After that, pick an Advert from DB and add it to the same base list.

List<object> allItems = new List<object>();
int numOfProdPerPage = 5;
int n = ... // number of products to be listed

var products = db.Products.OrderBy(d=>d.ProductDateCreated);
var adverts = db.Adverts.OrderByDescending(d=>d.AdvertView);

for(int p = 0; p< n / numOfProdPerPage ; p++)
{
    var productsPerPage = products.Skip(numOfProdPerPage * p)
                                  .Take(numOfProdPerPage ).ToList();

    allItems.AddRange(products);

    Advert advert = adverts.ElementAt<Advert>(p);

    allItems.Add(advert);
}

Here's another approach:

  1. Sort your adverts list by "AdvertView" descending
  2. After you display 5 products, show the next advert from the list
  3. If there are more than 5 * advert.Count products, start over in your advert list.

In the example I am just showing Product Name and Advert Name. Ideally you would overwrite ToString() so they display themselves properly, but your question seemed to be about how to order the Adverts and display them after every five products.

Sample code:

var products = db.Products.OrderBy(d => d.ProductDateCreated).ToList();
var adverts = db.Adverts.OrderByDescending(a => a.AdvertView).ToList();

for (int i = 0; i < products.Count; i++)
{
    Console.WriteLine(products[i].ProductName);

    if ((i + 1) % 5 == 0) 
    {
        Console.WriteLine(adverts[(i / 5) % adverts.Count].AdvertName);
    }
}

Somewhere in your code you surely have a function that renders the list to HTML, insert a counter variable and keep track of how many items where displayed already. if you encounter the fifth item, place a new Advert there.

void RenderToHTML(List<Product> Products)
{
  int AdvertCounter = 0;
  foreach (Product product in Products)
  {
    if (AdvertCounter == 5)
    {
      Advertcounter = 0;
      AddAdvertToList(); //implement somewhere else
    }
    Advertcounter++;
    AddProduct(product); //implement somwhere else too
  }
}

Try to use something like this:

 List<Product> list1;
 List<Advert> list2 ;

 //Full list1 && list 2
 int counterForList2 = 0;
 foreach (string value in list1)
 {
     Console.WriteLine(value);
     if (list1.Count() % 5 == 0)
     {
         if (counterForList2 == list2.Count)
             counterForList2 = 0;
         Console.WriteLine(list2[counterForList2]);
         counterForList2++;
     }
 }

Your question assumes design solution, which, in my opinion isn't optimal. Rather than displaying item from different list why not create following interface:

interface IEntry
{
    string Name { get; set; }
    int Id { get; set; }
}   

and then inherit it in Product and Advert adding specific functionality:

class Product : IEntry   
{
    string Name { get; set; }
    int Id { get; set; }
    DateTime DateCreated { get; set; }
}    

After that simply make class inheriting from

List<IEntry>    

to make sure advert class appears the way you want.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM