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 { /// /// 商品控件默认宽度 /// public const int PRODUCT_DEFAULT_WIDTH = 104; /// /// 商品控件默认高度 /// public const int PRODUCT_DEFAULT_HEIGHT = 76; /// /// 数据源 /// private List _dataSource = null; /// /// 显示价格类型 /// 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 dataSource, PriceTypeEnum priceType) { try { if (dataSource == null) { this._dataSource = new List(); } //加入分页,避免污染源数据,新建集合 List list = new List(); 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); } /// /// 分页List数据 /// /// /// public List ListPager(List data) { var result = new List(); 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; } } /// /// 每页数量 /// public int PageSize { get; private set; } /// /// 总页数 /// public int PageCount => this.PageSize <= 0 ? 0 : ((TotalCount + this.PageSize - 1) / this.PageSize); /// /// 当前页码 /// public int PageNumber { get; set; } /// /// 总数量 /// public int TotalCount { get; private set; } private int _columns = 1; /// /// 显示的列数 /// public int Columns { get { return _columns; } set { _columns = (value < 0 ? 1 : value); } } private int _rows = 1; /// /// 显示行数 /// 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; /// /// 控件间距 /// public int ItemSpace { get; set; } = 2; } /// /// 价格类型 /// 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 Merge(int rows, int cols, List 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; } } }