【问题标题】:Is it possible to not add a new line in a listbox with each input?是否可以不在每个输入的列表框中添加新行?
【发布时间】:2014-01-15 10:49:20
【问题描述】:

我有一个 winforms 应用程序,它接受用户输入并将其添加到列表中。然后这个列表会显示在一个列表框中。

我的问题是我希望列表框仅在一行上显示单个项目一次。 目前它看起来像这样:

Product    Price    Quantity
Bread      1.20     1
Bread      2.40     2
Bread      3.60     3
Eggs       1.50     1
Eggs       3.00     2

我希望它显示:

Product    Price    Quantity
Bread      3.60     3
Eggs       3.00     2

有可能实现吗?

private void btnAdd_Click(object sender, EventArgs e)
    {
        lbBasket.DisplayMember = "ProductName";
        try
        {
            string name = textBoxProduct.Text.ToString();
            decimal price = Convert.ToDecimal(textBoxPrice.Text);
            int quantity = Convert.ToInt32(textBoxQuantity.Text);

            if (string.IsNullOrWhiteSpace(textBoxQuantity.Text))
            {
                shoppingBasket.AddProduct(name, price);
                lbBasket.Items.Add(textBoxProduct.Text);
                lbPrice.Items.Add(shoppingBasket.BasketTotal);
                lbQuantity.Items.Add(shoppingBasket.NumberOfTotalQuantities);
            }
            else
            {
                shoppingBasket.AddProduct(name, price, quantity);
                lbPrice.Items.Add(shoppingBasket.BasketTotal);
                lbQuantity.Items.Add(shoppingBasket.NumberOfTotalQuantities);

                foreach (OrderItem item in shoppingBasket)
                {
                    if (item.ProductName == name)
                    {
                        lbBasket.Items.Add(item.ProductName);
                    }
                }
            }
        }

【问题讨论】:

  • 显示代码如何将值添加到列表框
  • 您能否不使用字典来添加项目,并为每个唯一项目保留运行总价格。然后每次添加新项目时重新绑定列表
  • @RayB151 - 您似乎在使用三个不同的列表框。所以不,我不认为你可以简单地实现你想要的。如果您使用的是单个列表框,那么可以。但是,如果您要求显示具有最高值或最高数量的项目(从您的示例推断),则显示此数据的两个列表框之间没有实际链接。
  • 啊,好吧。我认为使用三个列表框会更容易,但如果可以的话,我将只更改为一个。
  • 我会尽快添加一个完整的解决方案。

标签: c# winforms listbox


【解决方案1】:

这是一个完整的示例,向您展示如何使用单个 ListBox。

using System;
using System.Linq;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            lbBasket.Items.Add(new Basket("Name 1", (decimal) 1.00, 1));
            lbBasket.Items.Add(new Basket("Name 2", (decimal) 2.00, 2));
        }

        private void btnAdd_Click(object sender, EventArgs e)
        {
            var newItem = new Basket(txtName.Text, Convert.ToDecimal(txtPrice.Text), Convert.ToInt32(txtQuantity.Text));

            var existingItem =
                lbBasket.Items.Cast<Basket>()
                    .FirstOrDefault(li => li.Name.Equals(newItem.Name, StringComparison.OrdinalIgnoreCase));
            // There is something there 
            if (existingItem != null)
            {
                // You already have the best one
                if (existingItem.Price > newItem.Price)
                {
                    // Do nothing
                    return;
                }
                // Price is the same
                if (existingItem.Price == newItem.Price)
                {
                    lbBasket.Items.Remove(existingItem);
                    newItem.Quantity += existingItem.Quantity;
                    lbBasket.Items.Add(newItem);
                }
                // Remove the old item and add the new one
                else if (existingItem.Price < newItem.Price)
                {
                    lbBasket.Items.Remove(existingItem);
                    lbBasket.Items.Add(newItem);
                }
            }
            else
            {
                lbBasket.Items.Add(newItem);
            }
        }
    }

    public class Basket
    {
        public string Name { get; set; }
        public decimal Price { get; set; }
        public int Quantity { get; set; }

        public Basket(string name, decimal price, int quantity)
        {
            Name = name;
            Price = price;
            Quantity = quantity;
        }

        public override string ToString()
        {
            return Name + " £" + Price + " " + Quantity;
        }
    }
}

当您不指定 DisplayMember 时,将调用 ToString,因此我在 Basket 类中重写了该方法以显示您可能希望它显示的方式。根据您自己的需要对其进行编辑,但这具有您需要的基本登录,并且应该可以帮助您。如果您有任何问题,请随时问... :)

逻辑是,如果名称已经存在,则检查价格,如果新商品中的价格相同,则检查数量,如果数量较高,则更新。如果价格更高,它将更新。在所有其他情况下,将不会进行更新。

【讨论】:

  • 这看起来可能对我有用。我需要调整一些东西,因为我有一个带有方法和属性的单独 dll,但我认为我的想法是正确的,非常感谢!
  • 没问题。如果您还有其他问题,请告诉我们! :)
  • 一切正常,除了我想更新数量和价格。目前,如果我指定数量为 4,它会将其设置为 4。(我在表单上有一个添加按钮)。如果我再次按下它,没有任何变化,我希望它读取 8 的数量(以及相应的价格)。我能做到吗?
  • 给我的 cmets 投票,我会接受作为贿赂为你做这件事 ;)
  • 甚至不知道这是可能的! :P
【解决方案2】:

只需添加类似如下的代码:

foreach(listboxitem itm in lbBasket)
{
  if(itm.toString()!=textBoxProduct.Text)
  {
    lbBasket.Items.Add(textBoxProduct.Text);
  }
}

同样为您拥有的所有 3 个列表框保持循环。

【讨论】:

    【解决方案3】:

    你可以用 LINQ 做到这一点:

    class Program
    {
        static void Main(string[] args)
        {
            List<ShoppingBasket> bag = new List<ShoppingBasket>();
    
            bag.Add(new ShoppingBasket("Bread", 1.20M, 1));
            bag.Add(new ShoppingBasket("Bread", 2.40M, 2));
            bag.Add(new ShoppingBasket("Bread", 3.60M, 3));
    
            bag.Add(new ShoppingBasket("Eggs", 1.50M, 1));
            bag.Add(new ShoppingBasket("Eggs", 3.000M, 2));
    
    
            var result = from x in bag
                        group x by x.Product into g
                       select new ShoppingBasket(g.Key, g.Max(x => x.Price),
                       g.Max(x => x.Quantity));
        }
    }
    public class ShoppingBasket
    {
        public string Product { get; set; }
        public decimal Price { get; set; }
        public int Quantity { get; set; }
    
        public ShoppingBasket(string product, decimal price, int quantity)
        {
            this.Product = product;
            this.Price = price;
            this.Quantity = quantity;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-10-21
      • 2016-04-02
      • 2015-03-22
      • 2016-11-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多