ASP.NET MVC实现横向展示购物车

2023-12-05 0 139

通常,我们看到的购物车是这样的:

ASP.NET MVC实现横向展示购物车

虽然这种购物车显示方式被广泛运用,但我个人觉得不够直观。如果换成这样呢?

ASP.NET MVC实现横向展示购物车

本篇的源码放在了:https://github.com/darrenji/ShoppingCartInMVC

以上购物车页能实现的效果包括:1、购物车明细:显示订购数量、总金额,清空购物车。2、购物车内产品:数量可调整,对应的小计和总计动态变化。点击移除按钮移除该产品。3、继续购物按钮:点击左下角的继续购物按钮,回到先前页。4、使用了Bootstrap, 页面元素自适应,页面宽度调小时,页面布局动态变化。5、每行放置4个产品,且允许高度不一致,第5个产品另起一行,且不会float到上一行的空白区域,如下图。

ASP.NET MVC实现横向展示购物车

首先,有关产品的类。

public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public string ImageUrl { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
}

产品选购页如图:

ASP.NET MVC实现横向展示购物车

以上,产品选购页是一个有关Product集合的强类型视图页,其对应的Model为:

public class ProductsListVm
{
public ProductsListVm()
{
this.Products = new List<Product>();
}
public IEnumerable<Product> Products { get; set; }
}

想像一下,我们在超市购物,在购物车内放着不同的商品对应不同的数量,在这里,可以把商品和数量抽象成一个类:

public class CartLine
{
public Product Product { get; set; }
public int Quantity { get; set; }
}

而购物车类实际上就是维护着这个CartLine集合,需要提供添加、移除、计算购物车总价、清空购物车等方法,并提供一个获取到CartLine集合的属性,另外,针对点击购物车页上的增量和减量按钮,也要提供相应的方法。

public class Cart
{
private List<CartLine> lineCollection = new List<CartLine>();
//添加
public void AddItem(Product product, int quantity)
{
CartLine line = lineCollection.Where(p => p.Product.Id == product.Id).FirstOrDefault();
if (line == null)
{
lineCollection.Add(new CartLine(){Product = product, Quantity = quantity});
}
else
{
line.Quantity += quantity;
}
}
//点击数量+号或点击数量-号或自己输入一个值
public void IncreaseOrDecreaseOne(Product product, int quantity)
{
CartLine line = lineCollection.Where(p => p.Product.Id == product.Id).FirstOrDefault();
if (line != null)
{
line.Quantity = quantity;
}
}
//移除
public void RemoveLine(Product product)
{
lineCollection.RemoveAll(p => p.Product.Id == product.Id);
}
//计算总价
public decimal ComputeTotalPrice()
{
return lineCollection.Sum(p => p.Product.Price*p.Quantity);
}
//清空
public void Clear()
{
lineCollection.Clear();
}
//获取
public IEnumerable<CartLine> Lines
{
get { return lineCollection; }
}
}

购物车页自然就是针对Cart类的一个强类型视图页,嗯,等等,购物车页还需要记录下上一个页面的url,于是,考虑到把Cart类和记录上一个页面url这2个因素,针对购物车页,给出这样的一个Model:

public class CartIndexVm
{
public Cart Cart { get; set; }
public string ReturnUrl { get; set; }
}

在HomeController中,需要用到购物车的实例,可以这样写:

private Cart GetCart()
{
Cart cart = (Cart)Session[\”Cart\”];
if (cart == null)
{
cart = new Cart();
Session[\”Cart\”] = cart;
}
return cart;
}

Cart实例保存到Session中,并从Session中获取。当然,也可以放到ASP.NET MVC绑定机制中,需要做的就是实现IModelBinder接口。

public class CartModelBinder : IModelBinder
{
private const string sessionKey = \”Cart\”;
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
Cart cart = (Cart)controllerContext.HttpContext.Session[sessionKey];
if (cart == null)
{
cart = new Cart();
controllerContext.HttpContext.Session[sessionKey] = cart;
}
return cart;
}
}

自定义的ModelBinder需要在全局中注册。

public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
……
ModelBinders.Binders.Add(typeof(Cart), new CartModelBinder());
}
}

在Home控制器中,首先提供了一个返回Product集合的方法。

private List<Product> GetAllProducts()
{
return new List<Product>()
{
new Product(){Id = 1, Description = \”产品描述产品描述产品描述产品描述产品描述产品描述产品描述\”,ImageUrl = \”/images/1.jpg\”,Name = \”产品1\”,Price = 85M},
new Product(){Id = 2, Description = \”产品描述产品描述产品描述产品描述产品描述产品描述产品描述\”,ImageUrl = \”/images/2.jpg\”,Name = \”产品2\”,Price = 95M},
new Product(){Id = 3, Description = \”产品描述产品描述产品描述\”,ImageUrl = \”/images/2.jpg\”,Name = \”产品3\”,Price = 55M},
new Product(){Id = 4, Description = \”产品描述产品描述产品描述产品描述产品描述产品描述产品描述\”,ImageUrl = \”/images/1.jpg\”,Name = \”产品4\”,Price = 65M},
new Product(){Id = 5, Description = \”产品描述产品描述产品描述产品描述产品描述产品描述产品描述\”,ImageUrl = \”/images/2.jpg\”,Name = \”产品5\”,Price = 75M}
};
}

在HomeController中,有关产品选购页的如下:

//产品选购页
public ActionResult Index()
{
ProductsListVm productsListVm = new ProductsListVm();
productsListVm.Products = GetAllProducts();
return View(productsListVm);
}

Homme/Index.cshtml是一个ProductsListVm的强类型视图页。

@model MvcApplication1.Models.ProductsListVm
@{
ViewBag.Title = \”Index\”;
Layout = \”~/Views/Shared/_Layout.cshtml\”;
}
<style type=\”text/css\”>
.item {
border-bottom: solid 1px gray;
}
</style>
<div class=\”container\”>
<div class=\”row\”>
@foreach (var item in Model.Products)
{
Html.RenderPartial(\”ProductSummary\”, item);
}
</div>
</div>

其中,遍历Product集合的时候,又去加载Views/Shared/ProductSummary.cshtml这个强类型部分视图。

@model MvcApplication1.Models.Product
<div class=\”item\”>
<h3>@Model.Name</h3>
<p><img src=\”@Model.ImageUrl\” style=\”width: 100px;height: 100px;\”/></p>
<p>@Model.Description</p>
<h4>@Model.Price.ToString(\”c\”)</h4>
@using (Html.BeginForm(\”AddToCart\”, \”Home\”))
{
@Html.HiddenFor(p => p.Id)
@Html.Hidden(\”returnUrl\”, Request.Url.PathAndQuery)
<input type=\”submit\” value=\”+放入购物车\”/>
}
</div>

点击"+放入购物车"按钮,调用HomeController中的AddToCart方法,并且需要把选购产品页的url以query string的形式传递给控制器方法。

//购物车页
public ActionResult CartIndex(Cart cart, string returnUrl)
{
return View(new CartIndexVm
{
Cart = cart,
ReturnUrl = returnUrl
});
}
//添加到购物车
public ActionResult AddToCart(Cart cart, int id, string returnUrl)
{
Product product = GetAllProducts().Where(p => p.Id == id).FirstOrDefault();
if (product != null)
{
cart.AddItem(product, 1);
}
return RedirectToAction(\”CartIndex\”, new {returnUrl});
}

购物车页Home/CartIndex.cshtml是一个CartIndexVm的强类型视图页。

@model MvcApplication1.Models.CartIndexVm
@{
ViewBag.Title = \”CartIndex\”;
Layout = \”~/Views/Shared/_Layout.cshtml\”;
}
@section styles
{
<link href=\”~/Content/shopitem.css\” rel=\”external nofollow\” rel=\”stylesheet\” />
<link href=\”~/Content/jquery.bootstrap-touchspin.min.css\” rel=\”external nofollow\” rel=\”stylesheet\” />
}
<div class=\”container\”>
<div class=\”row\”>
@for (int i = 0; i < Model.Cart.Lines.Count(); i++)
{
var item = (Model.Cart.Lines.ToList())[i];
if (i != 0 && i%4 == 0) //每行有4个div
{
<div style=\”clear:both;\”></div>
}

<div class=\”col-md-3 column productbox\”>

<img src=\”@item.Product.ImageUrl\” style=\”width: 460px; height: 250px;\” class=\”img-responsive\”>
<div class=\”producttitle\”>
<div class=\”productname\”>@item.Product.Name</div>
<div class=\”productdes\”>@item.Product.Description</div>
<div>
<table>
<tr>
<td style=\”width:50px;\”>单价:</td>
<td>@item.Product.Price</td>
</tr>
<tr>
<td>数量:</td>
<td>
<input class=\”demo2\” type=\”text\” value=\”@item.Quantity\” name=\”demo2\” />
</td>
</tr>
<tr>
<td>小计:</td>
<td>@((item.Quantity * item.Product.Price).ToString(\”c\”))</td>
</tr>
</table>
</div>
</div>
<div class=\”productprice\”>
<div class=\”text-center\”>
@using (Html.BeginForm(\”RemoveFromCart\”, \”Home\”))
{
@Html.Hidden(\”Id\”, item.Product.Id)
@Html.HiddenFor(x => x.ReturnUrl)
<input class=\”btn btn-default btn-sm\” type=\”submit\” value=\”移除\”/>
<a href=\”#\” rel=\”external nofollow\” class=\”btn btn-danger btn-sm\” role=\”button\”>查看</a>
}

</div>
</div>
</div>
}

</div>
</div>
<hr/>
<div class=\”container\”>
<div class=\”row\”>
<div class=\”text-center\” style=\”font-size: 55px;font-weight: bold;color: red;\”>
<span>总计:</span> @Model.Cart.ComputeTotalPrice().ToString(\”c\”)
</div>
<p align=\”left\” class=\”actionButtons\” style=\”width: 100%; clear: both\”>
<a href=\”@Model.ReturnUrl\” rel=\”external nofollow\” >继续购物</a>
</p>
</div>
</div>
@section scripts
{
<script src=\”~/Scripts/jquery.bootstrap-touchspin.min.js\”></script>
<script type=\”text/javascript\”>
$(function () {
var i = $(\”input[class=\’demo2\’]\”);
i.TouchSpin({
min: 1,
max: 100,
step: 1//增量或减量
});
i.on(\”touchspin.on.stopupspin\”, function () {
$.post(\’@Url.Action(\”IncreaseOrDecreaseOne\”, \”Home\”)\’, { \”id\”: $(this).closest(\”div.productbox\”).find(\’#Id\’).val(), \”quantity\”: $(this).val() }, function (data) {
if (data.msg) {
location.reload();
}
});
//var temp = $(this).val();
//alert(temp);
//var temp = $(this).closest(\”div.productbox\”).find(\’#Id\’).val();
//alert(temp);
});
i.on(\”touchspin.on.stopdownspin\”, function () {
$.post(\’@Url.Action(\”IncreaseOrDecreaseOne\”, \”Home\”)\’, { \”id\”: $(this).closest(\”div.productbox\”).find(\’#Id\’).val(), \”quantity\”: $(this).val() }, function (data) {
if (data.msg) {
location.reload();
}
});
});
});
</script>
}

在购物车页,用了Bootstrap TouchSpin这款插件,点击其中的数量的增量和减量按钮,就向Home控制器中的IncreaseOrDecreaseOne方法发送一个异步post请求,得到返回数据刷新购物车页。

//点击数量+号或点击数量-号或自己输入一个值
[HttpPost]
public ActionResult IncreaseOrDecreaseOne(Cart cart, int id, int quantity)
{
Product product = GetAllProducts().Where(p => p.Id == id).FirstOrDefault();
if (product != null)
{
cart.IncreaseOrDecreaseOne(product, quantity);
}
return Json(new
{
msg = true
});
}

在购车页,点击"移除"按钮,就向Home控制器的RemoveFromCart方法提交表单。

//从购物车移除
public ActionResult RemoveFromCart(Cart cart, int id, string returnUrl)
{
Product product = GetAllProducts().Where(p => p.Id == id).FirstOrDefault();
if (product != null)
{
cart.RemoveLine(product);
}
return RedirectToAction(\”CartIndex\”, new {returnUrl});
}

购物车摘要是通过在Views/Shared/_Layout.cshtml中加载部分视图而来。

<head>
<meta charset=\”utf-8\” />
<meta name=\”viewport\” content=\”width=device-width\” />
<title>@ViewBag.Title</title>
@Styles.Render(\”~/Content/css\”)
<link href=\”~/bootstrap/css/bootstrap.min.css\” rel=\”external nofollow\” rel=\”stylesheet\” />
@RenderSection(\”styles\”, required: false)
@Scripts.Render(\”~/bundles/jquery\”)
<script src=\”~/bootstrap/js/bootstrap.min.js\”></script>
</head>
<body>
@{Html.RenderAction(\”Summary\”, \”Home\”);}
@RenderBody()
@RenderSection(\”scripts\”, required: false)
</body>

在Home控制器中,对应的Summary方法为:

//清空购物车
public ActionResult EmptyCart(Cart cart, string returnUrl)
{
cart.Clear();
return View(\”Index\”,new ProductsListVm{Products = GetAllProducts()});
}
//显示购物车摘要
public ActionResult Summary(Cart cart)
{
return View(cart);
}

Home/Summary.cshtml是一个有关Cart的强类型部分视图:

@model MvcApplication1.Models.Cart
@{
Layout = null;
}
<div id=\”cart\” style=\”background-color: #e3e3e3;padding: 10px; text-align:center;\”>
<span class=\”caption\”>
<b>购物车明细:</b>
@if (Model != null)
{
@Model.Lines.Sum(x => x.Quantity) <span>件,</span>
@Model.ComputeTotalPrice().ToString(\”c\”)
}

</span>

@Html.ActionLink(\”结算\”, \”CartIndex\”, \”Home\”, new {returnUrl = Request.Url.PathAndQuery}, null)
&nbsp;
@Html.ActionLink(\”清空\”, \”EmptyCart\”, \”Home\”, new {returnUrl = Request.Url.PathAndQuery}, null)
</div>

注意:需要把Layout设置为null,否则会报错,因为产品选购页和购物车摘要同时加载Views/Shared/_Layout.cshtml就反复调用了。

到此这篇关于ASP.NET MVC实现横向展示购物车的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持悠久资源网。

您可能感兴趣的文章:

  • asp.net基于HashTable实现购物车的方法
  • asp.net基于session实现购物车的方法
  • ASP.NET购物车实现过程详解
  • asp.net 购物车的实现浅析
  • asp.net 购物车实现详细代码

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

悠久资源 ASP.NET ASP.NET MVC实现横向展示购物车 https://www.u-9.cn/biancheng/aspnet/94183.html

常见问题

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务