using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows.Forms; using System.Windows.Forms.VisualStyles; using System.Drawing; using System.Diagnostics; using System.Reflection; using Sheng.Winform.Controls.Kernal; using System.Collections; namespace Sheng.Winform.Controls { /// /// /// public class ShengListView : Control { #region 常量 /// /// Creates a control with a border. /// private const int WS_BORDER = 0x00800000; /// /// Specifies that the control has a border with a sunken edge. /// private const int WS_EX_CLIENTEDGE = 0x00000200; #endregion #region 私有成员 private bool _suspendLayout = false; /// /// /// public bool Suspend { get { return _suspendLayout; } } /// /// 是否需要在调用 ResumeLayout 时重绘 /// private bool _needPaint = false; private ShengListViewLayoutManager _layoutManager; /// /// 为项扩展的用于呈现的属性 /// private readonly Dictionary _extendMember = new Dictionary(); //ToolTip _toolTip = new ToolTip(); //private System.Timers.Timer lazyRefreshTimer; #endregion #region 公开属性 /// /// Gets whether the shift key is down. /// internal bool ShiftKey { get; private set; } /// /// Gets whether the control key is down. /// internal bool ControlKey { get; private set; } /// /// 鼠标左键是否处于按下状态 /// internal bool LeftButton { get; private set; } /// /// 鼠标右键是否处于按下状态 /// internal bool RightButton { get; private set; } internal bool AnyMouseButton { get { return LeftButton || RightButton; } } //debug public /// /// 鼠标最后点击的位置 /// internal Point LastMouseDownLocation { get; private set; } private ShengListViewItem _hoveredItem; /// /// 当前鼠标经过的项 /// internal ShengListViewItem HoveredItem { get { return _hoveredItem; } private set { ShengListViewItem oldHoveredItem = _hoveredItem; ShengListViewItem newHoveredItem = value; _hoveredItem = value; if (oldHoveredItem != null && oldHoveredItem != newHoveredItem) { oldHoveredItem.Hovered = false; } if (newHoveredItem != null) newHoveredItem.Hovered = true; if (oldHoveredItem != newHoveredItem) { NeedPaint(); } } } private ShengListViewLayoutMode _layoutMode; /// /// /// public ShengListViewLayoutMode LayoutMode { get { return _layoutMode; } set { _layoutMode = value; ShengListViewLayoutManager layoutManager; switch (_layoutMode) { case ShengListViewLayoutMode.Standard: layoutManager = new ShengListViewStandardLayoutManager(this); break; case ShengListViewLayoutMode.Descriptive: layoutManager = new ShengListViewDescriptiveLayoutManager(this); break; default: layoutManager = new ShengListViewLayoutManager(this); Debug.Assert(false, "没这ListViewRenderer"); break; } SetLayoutManager(layoutManager); } } private BorderStyle _borderStyle = BorderStyle.Fixed3D; /// /// /// public BorderStyle BorderStyle { get { return _borderStyle; } set { _borderStyle = value; } } private ShengListViewTheme _theme = new ShengListViewTheme(); /// /// 配色方案 /// public ShengListViewTheme Theme { get { return _theme; } set { _theme = value; Refresh(); } } /// /// 当前布局中项的高度 /// public int ItemHeight { get { return _layoutManager.ItemHeightWithMargin; } } private bool _allowMultiSelection = false; /// /// /// public bool AllowMultiSelection { get { return _allowMultiSelection; } set { _allowMultiSelection = value; } } /// /// 是否没有任何项 /// public bool IsEmpty { get { return Items.Count == 0; } } private ShengListViewItemCollection _items = new ShengListViewItemCollection(); /// /// /// public ShengListViewItemCollection Items { get { return _items; } set { _items = value; } } /// /// 获取当前具有输入焦点的项 /// public ShengListViewItem FocusedItem { get { foreach (var item in _items) { if (item.Focused) return item; } return null; } } /// /// 默认的用于呈现为项中文本的Property /// public string DisplayMember { get; set; } #endregion #region 构造 /// /// /// public ShengListView() { SetStyle(ControlStyles.ResizeRedraw, true); SetStyle(ControlStyles.OptimizedDoubleBuffer, true); SetStyle(ControlStyles.Selectable, true); this.Padding = new System.Windows.Forms.Padding(10); _items.Owner = this; //设置一个默认布局 this.LayoutMode = ShengListViewLayoutMode.Standard; //_layoutManager = new ListViewLayoutManager(this); //lazyRefreshTimer = new System.Timers.Timer(); //lazyRefreshTimer.Interval = 10; //lazyRefreshTimer.Enabled = false; //lazyRefreshTimer.Elapsed += lazyRefreshTimer_Tick; //lazyRefreshCallback = new RefreshDelegateInternal(Refresh); } //delegate void RefreshDelegateInternal(); //private RefreshDelegateInternal lazyRefreshCallback; //void lazyRefreshTimer_Tick(object sender, EventArgs e) //{ // if (IsHandleCreated && IsDisposed == false) // BeginInvoke(lazyRefreshCallback); // lazyRefreshTimer.Stop(); //} #endregion #region 方法 #region internal /// /// 更改了选择的项 /// internal void OnSelectedItemChanged() { SelectedItemChanaged?.Invoke(this, new EventArgs()); } /// /// 双击项 /// /// internal void OnItemDoubleClick(ShengListViewItem item) { ItemDoubleClick?.Invoke(this, new ShengListViewItemDoubleClickEventArgs(item)); } internal void OnItemsRemoved(List items) { _layoutManager.OnItemsRemoved(items); ItemsRemoved?.Invoke(this, new ShengListViewItemsRemovedEventArgs(items)); } /// /// 请求在下次调用 ResumeLayout 时重绘 /// internal void NeedPaint() { _needPaint = true; } internal void RenderItem(ShengListViewItem item) { if (Suspend == false) { _layoutManager.RenderItem(this.CreateGraphics(), item); } } internal object GetItemPropertyValue(object itemValue, string propertyName) { if (itemValue == null || String.IsNullOrEmpty(propertyName)) { Debug.Assert(false, "itemValue 或 propertyName 为空"); throw new ArgumentNullException(); } return ReflectionPool.GetPropertyValue(itemValue, propertyName); } internal string GetItemText(object itemValue) { Debug.Assert(itemValue != null, "itemValue 为 null"); if (itemValue == null) return String.Empty; if (ItemTextGetting != null) { ShengListViewGetItemTextEventArgs args = new ShengListViewGetItemTextEventArgs(itemValue); ItemTextGetting(this, args); if (String.IsNullOrEmpty(args.Text) == false) return args.Text; } if (String.IsNullOrEmpty(DisplayMember)) { return itemValue.ToString(); } else { return GetItemText(itemValue, DisplayMember); } } internal string GetItemText(object itemValue, string propertyName) { Debug.Assert(itemValue != null && String.IsNullOrEmpty(propertyName) == false, "itemValue 为 null"); object text = GetItemPropertyValue(itemValue, propertyName); if (text == null) return String.Empty; else return text.ToString(); } /// /// 获取当前选中的所有项 /// /// internal List GetSelectedItems() { List items = new List(); foreach (var item in _items) { if (item.Selected) items.Add(item); } return items; } #endregion #region public /// /// /// /// public void AddExtendMember(IShengListViewExtendMember member) { Dictionary extendMembers = member.GetExtendMembers(); foreach (var item in extendMembers) { SetExtendMember(item.Key, item.Value); } } /// /// 设置扩展属性供特定LayoutEngine使用 /// 如果指定的 ExtendMember 已存在,覆盖之 /// 用String.Empty 或 null 做为 propertyName传入,表示删除指定的 member /// /// /// public void SetExtendMember(string member, string propertyName) { if (String.IsNullOrEmpty(member)) { Debug.Assert(false, "member 为空"); throw new ArgumentNullException(); } if (String.IsNullOrEmpty(propertyName)) { _extendMember.Remove(member); } else { if (_extendMember.Keys.Contains(member)) { _extendMember[member] = propertyName; } else { _extendMember.Add(member, propertyName); } } } /// /// /// /// /// public bool ContainerExtendMember(string member) { if (String.IsNullOrEmpty(member) ) { Debug.Assert(false, "member 为空"); throw new ArgumentNullException(); } return _extendMember.Keys.Contains(member); } /// /// /// /// /// public string GetExtendMember(string member) { if (ContainerExtendMember(member) == false) { Debug.Assert(false, "指定的 member 不存在" + member); throw new ArgumentOutOfRangeException(); } return _extendMember[member]; } /// /// 恢复正常的布局逻辑。 /// public new void ResumeLayout() { _suspendLayout = false; if (_needPaint) { this.Refresh(); _needPaint = false; } base.ResumeLayout(); } /// /// /// /// public new void ResumeLayout(bool refreshNow) { _suspendLayout = false; if (refreshNow) { this.Refresh(); _needPaint = false; } else { ResumeLayout(); } base.ResumeLayout(refreshNow); } /// /// 临时挂起控件的布局逻辑。 /// public new void SuspendLayout() { _suspendLayout = true; base.SuspendLayout(); } /// /// /// public override void Refresh() { if (_suspendLayout) return; base.Refresh(); } /// /// 获取当前选中项所绑定的对象 /// 如果没有选中项,返回null,如果选中多项,返回选中项集合中的第一个 /// /// public object GetSelectedValue() { List selectedItems = GetSelectedItems(); if (selectedItems.Count == 0) return null; return selectedItems[0].Value; } /// /// 根据指定的绑定项对象 /// 设置当前列表中选定的项 /// /// public void SetSelectedValue(object obj) { if (obj == null) { ClearSelect(); return; } var items = (from item in _items where item.Value == obj select item).ToList(); if (items.Count == 0) { Debug.Assert(false, "没有指定的项"); return; } var oldSelectedItems = GetSelectedItems(); //这里为什么用foreach //考虑到多个项绑定到同一个对象的情况,不过理论上讲不应该出现这种情况 SuspendLayout(); ClearSelect(); foreach (var item in items) { item.Selected = true; } ResumeLayout(); if (items.SequenceEqual(oldSelectedItems) == false) OnSelectedItemChanged(); } /// /// 获取当前选中的所有项的绑定对象集合 /// 如果当前没有选中任何项,返回空集合 /// /// public List GetSelectedValues() { List selectedValues = new List(); List selectedItems = GetSelectedItems(); foreach (var item in selectedItems) { selectedValues.Add(item.Value); } return selectedValues; } /// /// 取消所有项的选择 /// public void ClearSelect() { bool suspend = false; if (this.Suspend == false) { this.SuspendLayout(); suspend = true; } foreach (var selectedItem in GetSelectedItems()) { selectedItem.Selected = false; } if (suspend) this.ResumeLayout(); } /// /// /// /// public void DataBind(IList list) { if (list == null) { Debug.Assert(false, "list 为 null"); throw new ArgumentNullException(); } SuspendLayout(); Items.Clear(); foreach (var item in list) { this.Items.Add(new ShengListViewItem(item)); } ResumeLayout(); } /// /// /// public void Clear() { SuspendLayout(); Items.Clear(); ResumeLayout(); } #endregion #region private private void Hover(Point location) { ShengListViewHitInfo hitInfo = _layoutManager.HitTest(location); if (hitInfo.ItemHit) { HoveredItem = Items[hitInfo.ItemIndex]; } else { HoveredItem = null; } } private void SetLayoutManager(ShengListViewLayoutManager layoutManager) { if (_layoutManager == layoutManager) return; if (_layoutManager != null) _layoutManager.Dispose(); _layoutManager = layoutManager; Refresh(); } #endregion #region protected /// /// 获取创建控件句柄时所需要的创建参数 /// protected override CreateParams CreateParams { get { //设置控件的边框样式 CreateParams p = base.CreateParams; p.Style &= ~WS_BORDER; p.ExStyle &= ~WS_EX_CLIENTEDGE; if (_borderStyle == BorderStyle.Fixed3D) p.ExStyle |= WS_EX_CLIENTEDGE; else if (_borderStyle == BorderStyle.FixedSingle) p.Style |= WS_BORDER; return p; } } /// /// /// /// protected override void OnResize(EventArgs e) { base.OnResize(e); //_layoutManager.Update(); } #region Mouse /// /// /// /// protected override void OnMouseDown(MouseEventArgs e) { SuspendLayout(); if (Focused == false) Focus(); LeftButton = (e.Button & MouseButtons.Left) == MouseButtons.Left; RightButton = (e.Button & MouseButtons.Right) == MouseButtons.Right; LastMouseDownLocation = e.Location; _layoutManager.MouseDown(e); ResumeLayout(); base.OnMouseDown(e); } /// /// /// /// protected override void OnMouseUp(MouseEventArgs e) { if ((e.Button & MouseButtons.Left) == MouseButtons.Left) LeftButton = false; if ((e.Button & MouseButtons.Right) == MouseButtons.Right) RightButton = false; SuspendLayout(); _layoutManager.MouseUp(e); ResumeLayout(); //显示上下文菜单 bool rightButton = (e.Button & MouseButtons.Right) == MouseButtons.Right; if (rightButton && this.ContextMenuStrip != null) { this.ContextMenuStrip.Show(this.PointToScreen(e.Location)); } base.OnMouseUp(e); } /// /// /// /// protected override void OnMouseMove(MouseEventArgs e) { // if (_toolTip.Active) // _toolTip.Hide(this); SuspendLayout(); //如果处于框选状态,不处理Hover if (_layoutManager.MouseSelecting == false) { Hover(e.Location); } _layoutManager.MouseMove(e); ResumeLayout(); base.OnMouseMove(e); } /// /// /// /// protected override void OnMouseWheel(MouseEventArgs e) { SuspendLayout(); _layoutManager.OnMouseWheel(e); Hover(e.Location); NeedPaint(); ResumeLayout(); base.OnMouseWheel(e); } /// /// /// /// protected override void OnMouseDoubleClick(MouseEventArgs e) { if (ItemDoubleClick != null) { ShengListViewHitInfo hitInfo = _layoutManager.HitTest(e.Location); if (hitInfo.ItemHit) { ShengListViewItem item = Items[hitInfo.ItemIndex]; OnItemDoubleClick(item); } } base.OnMouseDoubleClick(e); } /// /// /// /// protected override void OnMouseHover(EventArgs e) { //Point toolTipPoint = this.PointToClient(Cursor.Position); //_toolTip.Show("ff", this, toolTipPoint); base.OnMouseHover(e); } #endregion #region Key /// /// /// /// /// protected override bool IsInputKey(Keys keyData) { if ((keyData & Keys.Left) == Keys.Left || (keyData & Keys.Right) == Keys.Right || (keyData & Keys.Up) == Keys.Up || (keyData & Keys.Down) == Keys.Down) return true; else return base.IsInputKey(keyData); } /// /// /// /// protected override void OnKeyDown(KeyEventArgs e) { ShiftKey = (e.Modifiers & Keys.Shift) == Keys.Shift; ControlKey = (e.Modifiers & Keys.Control) == Keys.Control; _layoutManager.OnKeyDown(e); base.OnKeyDown(e); } /// /// /// /// protected override void OnKeyUp(KeyEventArgs e) { ShiftKey = (e.Modifiers & Keys.Shift) == Keys.Shift; ControlKey = (e.Modifiers & Keys.Control) == Keys.Control; _layoutManager.OnKeyUp(e); base.OnKeyUp(e); } #endregion #region Focus /// /// /// /// protected override void OnGotFocus(EventArgs e) { base.OnGotFocus(e); Refresh(); } /// /// /// /// protected override void OnLostFocus(EventArgs e) { base.OnLostFocus(e); Refresh(); } #endregion #region Paint /// /// /// /// protected override void OnPaint(PaintEventArgs e) { if (_layoutManager != null) { _layoutManager.Render(e.Graphics); } //Size size1 = new Size(100, 100); //Size size2 = new Size(50, 50); //e.Graphics.DrawRectangle(Pens.Black, new Rectangle(new Point(10, 10), size1)); //size1 = Size.Add(size1, size2); //e.Graphics.DrawRectangle(Pens.Red, new Rectangle(new Point(10, 10), size1)); } #endregion /// /// /// /// protected override void Dispose(bool disposing) { base.Dispose(disposing); } #endregion #endregion #region 事件 /// /// 更改了选择的项 /// public event EventHandler SelectedItemChanaged; /// /// 双击项 /// public event EventHandler ItemDoubleClick; /// /// 项被删除 /// public event EventHandler ItemsRemoved; /// /// 通过外能事件获取用于绘制项的文本 /// public event EventHandler ItemTextGetting; #endregion } }