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#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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;
}
}
}