NopCommerce源码架构详解-产品列表相关源码分析2

上一篇我介绍了一上nop中的产品列表相关核心代码轮廓。现在我们来分析里面的详细代码,今天我们就来看看里面处理排序、分页、视图model、价格筛选及视图选择相关的代码。

NopCommerce源码架构详解概述

文章目录

概述

NopCommerce源码架构详解-产品列表相关源码分析2。

内容

上一篇我介绍了一上nop中的产品列表相关核心代码轮廓。现在我们来分析里面的详细代码,今天我们就来看看里面处理排序、分页、视图model、价格筛选及视图选择相关的代码。

//sorting
PrepareSortingOptions(model.PagingFilteringContext, command);
//view mode
PrepareViewModes(model.PagingFilteringContext, command);
//page size
PreparePageSizeOptions(model.PagingFilteringContext, command,
    category.AllowCustomersToSelectPageSize, 
    category.PageSizeOptions, 
    category.PageSize);

//price ranges
model.PagingFilteringContext.PriceRangeFilter.LoadPriceRangeFilters(category.PriceRanges, _webHelper, _priceFormatter);
var selectedPriceRange = model.PagingFilteringContext.PriceRangeFilter.GetSelectedPriceRange(_webHelper, category.PriceRanges);
decimal? minPriceConverted = null;
decimal? maxPriceConverted = null;
if (selectedPriceRange != null)
{
    if (selectedPriceRange.From.HasValue)
        minPriceConverted = _currencyService.ConvertToPrimaryStoreCurrency(selectedPriceRange.From.Value, _workContext.WorkingCurrency);

    if (selectedPriceRange.To.HasValue)
        maxPriceConverted = _currencyService.ConvertToPrimaryStoreCurrency(selectedPriceRange.To.Value, _workContext.WorkingCurrency);
}

产品的列表筛选用到了一个分页的model类CatalogPagingFilteringModel,这个类包含了所有可用筛选条件相关的信息。CatalogPagingFilteringModel相关类的继承关系如下图:

2020-04-23-20-57-07

在CatalogPagingFilteringModel构造函数里面对里面的一些字段进行了初始化:

public CatalogPagingFilteringModel()
{
    this.AvailableSortOptions = new List<SelectListItem>();
    this.AvailableViewModes = new List<SelectListItem>();
    this.PageSizeOptions = new List<SelectListItem>();

    this.PriceRangeFilter = new PriceRangeFilterModel();
    this.SpecificationFilter = new SpecificationFilterModel();
}

AvailableSortOptions、AvailableViewModes和PageSizeOptions都是类型为List的集合,是为了在页面视图中好展示。

1、Sort

protected virtual void PrepareSortingOptions(CatalogPagingFilteringModel pagingFilteringModel, CatalogPagingFilteringModel command)
{
    if (pagingFilteringModel == null)
        throw new ArgumentNullException("pagingFilteringModel");

    if (command == null)
        throw new ArgumentNullException("command");

    pagingFilteringModel.AllowProductSorting = _catalogSettings.AllowProductSorting;
    if (pagingFilteringModel.AllowProductSorting)
    {
        foreach (ProductSortingEnum enumValue in Enum.GetValues(typeof(ProductSortingEnum)))
        {
            var currentPageUrl = _webHelper.GetThisPageUrl(true);
            var sortUrl = _webHelper.ModifyQueryString(currentPageUrl, "orderby=" + ((int)enumValue).ToString(), null);

            var sortValue = enumValue.GetLocalizedEnum(_localizationService, _workContext);
            pagingFilteringModel.AvailableSortOptions.Add(new SelectListItem()
            {
                Text = sortValue,
                Value = sortUrl,
                Selected = enumValue == (ProductSortingEnum)command.OrderBy
            });
        }
    }
}

2、View model

protected virtual void PrepareViewModes(CatalogPagingFilteringModel pagingFilteringModel, CatalogPagingFilteringModel command)
{
    if (pagingFilteringModel == null)
        throw new ArgumentNullException("pagingFilteringModel");

    if (command == null)
        throw new ArgumentNullException("command");

    pagingFilteringModel.AllowProductViewModeChanging = _catalogSettings.AllowProductViewModeChanging;

    var viewMode = !string.IsNullOrEmpty(command.ViewMode)
        ? command.ViewMode
        : _catalogSettings.DefaultViewMode;
    pagingFilteringModel.ViewMode = viewMode;

    if (pagingFilteringModel.AllowProductViewModeChanging)
    {
        var currentPageUrl = _webHelper.GetThisPageUrl(true);
        //grid
        pagingFilteringModel.AvailableViewModes.Add(new SelectListItem()
        {
            Text = _localizationService.GetResource("Catalog.ViewMode.Grid"),
            Value = _webHelper.ModifyQueryString(currentPageUrl, "viewmode=grid", null),
            Selected = viewMode == "grid"
        });
        //list
        pagingFilteringModel.AvailableViewModes.Add(new SelectListItem()
        {
            Text = _localizationService.GetResource("Catalog.ViewMode.List"),
            Value = _webHelper.ModifyQueryString(currentPageUrl, "viewmode=list", null),
            Selected = viewMode == "list"
        });
    } 
}

通过查看代码viewMode为不同值返回的html是不一样的。我结合表Category和CategoryTemplate可以看到每个产品分类对应的视图文件名字。如下图:

2020-04-23-20-57-13

表CategoryTemplate:

2020-04-23-20-57-18

我们打开Nop.Web项目中的视图文件Views/Category/CategoryTemplate.ProductsInGridOrLines.cshtml可以找到下面的代码根据用户选择不同的数据展示方式,分别返回不同的html。

@if (Model.Products.Count > 0)
{
    if (Model.PagingFilteringContext.ViewMode == "list")
    {
    @*list mode*@
    <div class="product-list">
        @foreach (var product in Model.Products)
        {
            <div class="item-box">
                @Html.Partial("_ProductBox", product)
            </div>
        }
    </div>       
    }
    else
    {
    @*grid mode*@
    <div class="product-grid">
        @foreach (var product in Model.Products)
        {
            <div class="item-box">
                @Html.Partial("_ProductBox", product)
            </div>
        }
    </div>
    }
}

3、page size

protected virtual void PreparePageSizeOptions(CatalogPagingFilteringModel pagingFilteringModel, CatalogPagingFilteringModel command,
    bool allowCustomersToSelectPageSize, string pageSizeOptions, int fixedPageSize)
{
    if (pagingFilteringModel == null)
        throw new ArgumentNullException("pagingFilteringModel");

    if (command == null)
        throw new ArgumentNullException("command");

    if (command.PageNumber <= 0)
    {
        command.PageNumber = 1;
    }
    pagingFilteringModel.AllowCustomersToSelectPageSize = false;
    if (allowCustomersToSelectPageSize && pageSizeOptions != null)
    {
        var pageSizes = pageSizeOptions.Split(new char[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries);

        if (pageSizes.Any())
        {
            // get the first page size entry to use as the default (category page load) or if customer enters invalid value via query string
            if (command.PageSize <= 0 || !pageSizes.Contains(command.PageSize.ToString()))
            {
                int temp = 0;

                if (int.TryParse(pageSizes.FirstOrDefault(), out temp))
                {
                    if (temp > 0)
                    {
                        command.PageSize = temp;
                    }
                }
            }

            var currentPageUrl = _webHelper.GetThisPageUrl(true);
            var sortUrl = _webHelper.ModifyQueryString(currentPageUrl, "pagesize={0}", null);
            sortUrl = _webHelper.RemoveQueryString(sortUrl, "pagenumber");

            foreach (var pageSize in pageSizes)
            {
                int temp = 0;
                if (!int.TryParse(pageSize, out temp))
                {
                    continue;
                }
                if (temp <= 0)
                {
                    continue;
                }

                pagingFilteringModel.PageSizeOptions.Add(new SelectListItem()
                {
                    Text = pageSize,
                    Value = String.Format(sortUrl, pageSize),
                    Selected = pageSize.Equals(command.PageSize.ToString(), StringComparison.InvariantCultureIgnoreCase)
                });
            }

            if (pagingFilteringModel.PageSizeOptions.Any())
            {
                pagingFilteringModel.PageSizeOptions = pagingFilteringModel.PageSizeOptions.OrderBy(x => int.Parse(x.Text)).ToList();
                pagingFilteringModel.AllowCustomersToSelectPageSize = true;

                if (command.PageSize <= 0)
                {
                    command.PageSize = int.Parse(pagingFilteringModel.PageSizeOptions.FirstOrDefault().Text);
                }
            }
        }
    }
    else
    {
        //customer is not allowed to select a page size
        command.PageSize = fixedPageSize;
    }

    //ensure pge size is specified
    if (command.PageSize <= 0)
    {
        command.PageSize = fixedPageSize;
    }
}

4、price ranges

model.PagingFilteringContext.PriceRangeFilter.LoadPriceRangeFilters(category.PriceRanges, _webHelper, _priceFormatter);
var selectedPriceRange = model.PagingFilteringContext.PriceRangeFilter.GetSelectedPriceRange(_webHelper, category.PriceRanges);
decimal? minPriceConverted = null;
decimal? maxPriceConverted = null;
if (selectedPriceRange != null)
{
    if (selectedPriceRange.From.HasValue)
        minPriceConverted = _currencyService.ConvertToPrimaryStoreCurrency(selectedPriceRange.From.Value, _workContext.WorkingCurrency);

    if (selectedPriceRange.To.HasValue)
        maxPriceConverted = _currencyService.ConvertToPrimaryStoreCurrency(selectedPriceRange.To.Value, _workContext.WorkingCurrency);
}

5、视图选择

前面我们有提到Nop的分类对应的视图文件是放在表CategoryTemplate里面的,接下来我们来看这部分的逻辑代码:

var templateCacheKey = string.Format(ModelCacheEventConsumer.CATEGORY_TEMPLATE_MODEL_KEY, category.CategoryTemplateId);
var templateViewPath = _cacheManager.Get(templateCacheKey, () =>
    {
        var template = _categoryTemplateService.GetCategoryTemplateById(category.CategoryTemplateId);
        if (template == null)
            template = _categoryTemplateService.GetAllCategoryTemplates().FirstOrDefault();
        if (template == null)
            throw new Exception("No default template could be loaded");
        return template.ViewPath;
    });

//activity log
_customerActivityService.InsertActivity("PublicStore.ViewCategory", _localizationService.GetResource("ActivityLog.PublicStore.ViewCategory"), category.Name);

return View(templateViewPath, model);
原文出处:蓝狐软件工作室【蓝狐】

原文链接:http://m.lanhusoft.com/Article/349.html

本文观点不代表 .Net中文网 立场,转载请联系原作者。

发表评论

登录后才能评论