You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

479 lines
16 KiB
C#

9 months ago
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using POSV.Entity;
using System.Diagnostics;
using POSV.Utils;
using DevComponents.DotNetBar.Metro;
using DevComponents.DotNetBar;
namespace POSV.Component
{
[ToolboxItem(true)]
public partial class ProductXControl : BaseUserControl
{
/// <summary>
/// 商品控件默认宽度
/// </summary>
public const int PRODUCT_DEFAULT_WIDTH = 104;
/// <summary>
/// 商品控件默认高度
/// </summary>
public const int PRODUCT_DEFAULT_HEIGHT = 76;
/// <summary>
/// 数据源
/// </summary>
private List<ProductExt> _dataSource = null;
/// <summary>
/// 显示价格类型
/// </summary>
private PriceTypeEnum _priceType = PriceTypeEnum.;
//这样可以加快多次创建item速度否则每次要耗时2毫秒
private Image _defaultImage = global::POSV.Properties.Resources._2x;
public ProductXControl()
{
InitializeComponent();
this.itemPanel.ResizeItemsToFit = false;
this.itemPanel.BackgroundStyle.Class = "MetroTileGroupTitle";//很关键
}
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if (this.DesignMode) return;
ReCalSize();
this.Resize += OnResize;
}
private void OnResize(object sender, EventArgs e)
{
switch (this.FindForm().WindowState)
{
case FormWindowState.Normal:
case FormWindowState.Maximized:
{
ReCalSize();
}
break;
}
}
private void ReCalSize()
{
//计算能显示的列数
var _width = this.ItemWidth + this.ItemSpace - 1;
if (_width != 0)
{
this.Columns = ((this.Width - this.Padding.Left - this.Padding.Right) / _width);
}
//根据行数,重新规划高度
var _height = this.ItemHeight + this.ItemSpace - 1;
if (_height != 0)
{
this.Rows = ((this.Height - this.Padding.Top - this.Padding.Bottom) / _height);
}
this.ItemHeight = (this.Height - this.Padding.Top - this.Padding.Bottom) / this.Rows - this.ItemSpace;
BindDataSource(this._dataSource, this._priceType);
}
public void BindDataSource(List<ProductExt> dataSource, PriceTypeEnum priceType)
{
try
{
if (dataSource == null)
{
this._dataSource = new List<ProductExt>();
}
//加入分页,避免污染源数据,新建集合
List<ProductExt> list = new List<ProductExt>();
list.AddRange(dataSource);
this._dataSource = list;
this._priceType = priceType;
//可以考虑更优化的分摊机制?张莹
int deltaX = this.Width - this.Padding.Left - this.Padding.Right - (this.ItemWidth + this.ItemSpace) * this.Columns - this.ItemSpace;
int deltaY = this.Height - this.Padding.Top - this.Padding.Bottom - (this.ItemHeight + this.ItemSpace) * this.Rows - this.ItemSpace;
this.TotalCount = this._dataSource.Count;
this.PageSize = this.Columns * this.Rows;
//清空历史数据
this.itemPanel.Items.Clear();
//复制新的数据源,进行分页运算
var merge = ProductXMerge.Merge(this.Rows, this.Columns, this._dataSource, false);
var pager = ListPager(merge);
ItemContainer mainContainer = new ItemContainer();
mainContainer.Name = "productContainer";
mainContainer.MultiLine = (this.Rows > 1);
mainContainer.ItemSpacing = this.ItemSpace;
mainContainer.LayoutOrientation = eOrientation.Horizontal;
for (int i=0;i < pager.Count;i++)
{
ProductExt entity = pager[i];
MetroTileItem item = new MetroTileItem();
item.TileStyle.PaddingLeft = item.TileStyle.PaddingRight = 0;
item.EnableMarkup = true;
item.OptionGroup = "product";
item.TileStyle.BorderWidth = 0;
item.TileStyle.BackColor = Color.Transparent;
item.TileStyle.BackColor2 = Color.Transparent;
item.TileStyle.BorderColor = Color.Transparent;
item.TileStyle.BorderColor2 = Color.Transparent;
//判断商品背景
item.TileStyle.BackgroundImage = _defaultImage;
item.TileStyle.BackgroundImagePosition = eStyleBackgroundImage.Stretch;
item.TitleTextAlignment = ContentAlignment.MiddleCenter;
item.Checked = false;
//将宽度进行补偿
int _width = this.ItemWidth + (this.Columns > 0 ? (deltaX / this.Columns) : 0);
int _offsetWidth = this.Columns > 0 ? (deltaX % this.Columns) : 0;
//if (i % _offsetWidth == 0)
//{
// _width += _offset;
//}
//将高度误差补入第一行
int _height = this.ItemHeight + deltaY;
//if (this.Columns - mainContainer.SubItems.Count > 0)
//{
// _height += deltaY;
//}
//显示大小
item.TileSize = new Size(_width, _height);
//显示编码后,调整呈现位置
item.TileStyle.TextAlignment = DevComponents.DotNetBar.eStyleTextAlignment.Center;
item.TileStyle.TextLineAlignment = DevComponents.DotNetBar.eStyleTextAlignment.Near;
item.TitleTextAlignment = System.Drawing.ContentAlignment.BottomRight;
var price = decimal.Zero;
switch (this._priceType)
{
case PriceTypeEnum.:
{
price = entity.Price;
}
break;
case PriceTypeEnum.:
{
price = entity.MinPrice;
}
break;
case PriceTypeEnum.:
{
price = entity.OtherPrice;
}
break;
case PriceTypeEnum.:
{
price = entity.MemberPrice;
}
break;
}
//品名
item.TileStyle.TextColor = ColorTranslator.FromHtml("#444444");
//售价
item.TitleTextColor = ColorTranslator.FromHtml("#F45B63");
//绑定商品Tag属性
item.Tag = ObjectUtils.Copy(entity);
switch (entity.Name)
{
case Constant.PREV_PAGER:
{
item.TileStyle.BackgroundImage = _defaultImage;
item.Image = global::POSV.Properties.Resources._2x;
item.ImageTextAlignment = ContentAlignment.MiddleCenter;
item.Text = string.Empty;
}
break;
case Constant.NEXT_PAGER:
{
item.TileStyle.BackgroundImage = _defaultImage;
item.Image = global::POSV.Properties.Resources._2x;
item.ImageTextAlignment = ContentAlignment.MiddleCenter;
item.Text = string.Empty;
}
break;
default:
{
//显示编码后,调整呈现位置
item.TitleText = string.Format("¥{0}", price.ToString());
//绑定商品名称到Text属性
item.Text = entity.Name;
}
break;
}
item.MouseDown -= OnProductMouseDown;
item.MouseDown += OnProductMouseDown;
mainContainer.SubItems.Add(item);
}
this.itemPanel.Items.Insert(0, mainContainer);
this.itemPanel.Invalidate();
}
catch (Exception ex)
{
LOGGER.Error(ex, "构建商品控件内容异常");
}
}
private void OnProductMouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
MetroTileItem item = (MetroTileItem)sender;
var product = item.Tag as ProductExt;
switch (product.Name)
{
case Constant.PREV_PAGER:
{
this.PageNumber = product.Pager;
this.BindDataSource(this._dataSource, this._priceType);
}
break;
case Constant.NEXT_PAGER:
{
this.PageNumber = product.Pager;
this.BindDataSource(this._dataSource, this._priceType);
}
break;
default:
{
OnProductXClick(new ProductXEventArgs((ProductExt)item.Tag));
}
break;
}
}
}
public event ProductXEventHandler ProductXClick;
protected virtual void OnProductXClick(ProductXEventArgs e)
{
ProductXClick?.Invoke(this, e);
}
/// <summary>
/// 分页List数据
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public List<T> ListPager<T>(List<T> data)
{
var result = new List<T>();
result.AddRange(data.Skip((this.PageNumber - 1) * this.PageSize).Take(this.PageSize));
return result;
}
private MetroTileItem _selectedItem = null;
public MetroTileItem SelectedItem
{
get { return this._selectedItem; }
private set { this._selectedItem = value; }
}
/// <summary>
/// 每页数量
/// </summary>
public int PageSize { get; private set; }
/// <summary>
/// 总页数
/// </summary>
public int PageCount => this.PageSize <= 0 ? 0 : ((TotalCount + this.PageSize - 1) / this.PageSize);
/// <summary>
/// 当前页码
/// </summary>
public int PageNumber { get; set; }
/// <summary>
/// 总数量
/// </summary>
public int TotalCount { get; private set; }
private int _columns = 1;
/// <summary>
/// 显示的列数
/// </summary>
public int Columns
{
get
{
return _columns;
}
set
{
_columns = (value < 0 ? 1 : value);
}
}
private int _rows = 1;
/// <summary>
/// 显示行数
/// </summary>
public int Rows
{
get
{
return _rows;
}
set
{
_rows = (value < 0 ? 1 : value);
}
}
public int ItemHeight { get; set; } = PRODUCT_DEFAULT_HEIGHT;
public int ItemWidth { get; set; } = PRODUCT_DEFAULT_WIDTH;
/// <summary>
/// 控件间距
/// </summary>
public int ItemSpace { get; set; } = 2;
}
/// <summary>
/// 价格类型
/// </summary>
public enum PriceTypeEnum
{
,
,
,
,
,
,
}
public delegate void ProductXEventHandler(object sender, ProductXEventArgs e);
public class ProductXEventArgs : EventArgs
{
public ProductExt Product;
public ProductXEventArgs(ProductExt data)
{
this.Product = data;
}
}
public class ProductXMerge
{
private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
public static List<ProductExt> Merge(int rows, int cols, List<ProductExt> dataSource, bool touchEnabled)
{
Stopwatch sw = Stopwatch.StartNew();
//启用触摸屏,不分页
if (touchEnabled)
{
return dataSource;
}
//移除可能存在的分页标识
dataSource.RemoveAll(x => Constant.PREV_PAGER.Equals(x.Name) || Constant.NEXT_PAGER.Equals(x.Name));
int pageSize = rows * cols;
int totalCount = dataSource.Count;
//启用分页
int pageCount = ((totalCount - 1) + (pageSize - 2) - 1) / (pageSize - 2);
if (pageCount > 1)
{
int offset = 0;
for (int page = 1; page <= pageCount; page++)
{
if (page == 1)
{
offset = page * pageSize - 1;
var entity = new ProductExt();
entity.Id = IdWorkerUtils.Instance.NextId();
entity.Name = Constant.NEXT_PAGER;
entity.Pager = (page + 1);
dataSource.Insert(offset, entity);
}
else if (page < pageCount)
{
offset = page * pageSize - 2;
var entity = new ProductExt();
entity.Id = IdWorkerUtils.Instance.NextId();
entity.Name = Constant.PREV_PAGER;
entity.Pager = (page - 1);
dataSource.Insert(offset, entity);
offset++;
entity = new ProductExt();
entity.Id = IdWorkerUtils.Instance.NextId();
entity.Name = Constant.NEXT_PAGER;
entity.Pager = (page + 1);
dataSource.Insert(offset, entity);
}
else
{
var entity = new ProductExt();
entity.Id = IdWorkerUtils.Instance.NextId();
entity.Name = Constant.PREV_PAGER;
entity.Pager = (page - 1);
dataSource.Add(entity);
}
}
}
logger.Info("商品控件插入分页控件,耗时<{0}>", sw.ElapsedMilliseconds);
return dataSource;
}
}
}