/// <summary> /// 处理行单击。 /// </summary> /// <param name="info"></param> private void ProcessItemClick(TreeListHitTestInfo info) { var item = (TreeListItem)((VirtualTreeListItem)info.Element).Item; //按着ctrol切换选中状态 if (_controlPressed) { SelectItem(item, !item.Selected, false); } else if (_shiftPressed && _lastRowIndex != -1) { if (_lastRowIndex > _virMgr.Items.Count - 1) { return; } for (var i = SelectedItems.Count - 1; i >= 0; i--) { SelectedItems[i].SetSelected(false); } SelectedItems.InternalClear(); Invalidate(_bound.ItemBound); var start = _lastRowIndex; var end = item.Index; if (start > end) { start = end; end = _lastRowIndex; } for (var i = start; i <= end; i++) { if (!(_virMgr.Items[i].Item is TreeListItem t)) { continue; } t.SetSelected(true); SelectedItems.InternalAdd(t); } Invalidate(); RaiseItemSelectionChangedEvent(); } //选中且不是多选时,只触发单击事件 else if (item.Selected && SelectedItems.Count == 1) { RaiseItemClickEvent(item); return; } //选中当前行 else { SelectItem(item, true); HideEditor(); _lastRowIndex = item.Index; } RaiseItemClickEvent(item); }
/// <summary> /// 处理鼠标单击时 <see cref="TreeListHitTestInfo"/> 的处理。 /// </summary> /// <param name="info"></param> /// <param name="eventType"></param> private void ProcessHitTestInfoClick(TreeListHitTestInfo info, TreeListHitTestEventType eventType) { if (info.Bounds.IsEmpty) { return; } if (eventType == TreeListHitTestEventType.MouseUp && info.HitTestType == TreeListHitTestType.Column) { ProcessColumnClick(info); } else if (eventType == TreeListHitTestEventType.MouseDown) { switch (info.HitTestType) { case TreeListHitTestType.Cell: ProcessCellClick(info); break; case TreeListHitTestType.Item: ProcessItemClick(info); break; case TreeListHitTestType.PlusMinus: ProcessPlusMinusClick(info); break; case TreeListHitTestType.Checkbox: ProcessItemCheckedChange(info); break; } } }
/// <summary> /// 处理单元格单击。 /// </summary> /// <param name="info"></param> private void ProcessCellClick(TreeListHitTestInfo info) { AdjustItemPosistion(info); if (info.Owner != null) { ProcessItemClick(info.Owner); } var cell = (TreeListCell)info.Element; RaiseCellClickEvent(cell); switch (cell.BoxType) { case BoxType.CheckBox: if (!RaiseBeforeCellCheckChangeEvent(cell)) { cell.Checked = !cell.Checked; RaiseAfterCellCheckChangeEvent(cell); } break; case BoxType.RadioButton: var items = cell.Item.Parent == null ? cell.Item.TreeList.Items : cell.Item.Parent.Items; foreach (var item in items) { if (item == cell.Item) { continue; } var c1 = item.Cells[cell.Column]; if (!RaiseBeforeCellCheckChangeEvent(c1)) { c1.Checked = false; RaiseAfterCellCheckChangeEvent(c1); } } if (!RaiseBeforeCellCheckChangeEvent(cell)) { cell.Checked = true; RaiseAfterCellCheckChangeEvent(cell); } break; } cell.Item.InvalidateItem(); if (cell.Item.Enabled && !RaiseBeforeCellEditingEvent(cell)) { var rect = GetCellTextRectangle(cell, info.Bounds); _editor.BeginEdit(cell, rect); } }
/// <summary> /// 处理 +/- 符号单击。 /// </summary> /// <param name="info"></param> private void ProcessPlusMinusClick(TreeListHitTestInfo info) { var item = (TreeListItem)((VirtualTreeListItem)info.Element).Item; var expended = item.Expended; var cancel = expended ? RaiseBeforeItemCollapseEvent(item) : RaiseBeforeItemExpandEvent(item); if (cancel) { return; } HideEditor(); item.Expended = !item.Expended; }
/// <summary> /// 处理列头单击。 /// </summary> /// <param name="info"></param> private void ProcessColumnClick(TreeListHitTestInfo info) { if (_lastHoverHitInfo != null && _lastHoverHitInfo.HitTestType == TreeListHitTestType.Column && _lastHoverHitInfo.Element != null) { var column = (TreeListColumn)info.Element; HideEditor(); if (Sortable) { if (_sortedColumn != column) { _sortedOrder = SortOrder.Ascending; } else { if (_sortedOrder == SortOrder.Ascending) { _sortedOrder = SortOrder.Descending; } else { _sortedOrder = SortOrder.Ascending; } } _sortedColumn = column; if (RaiseColumnClickEvent(column, _sortedOrder)) { if (Groups.Count == 0) { Items.Sort(++_sortVersion, column, _sortedOrder); } else { Groups.Sort(++_sortVersion, column, _sortedOrder); } UpdateItems(); } } } }
/// <summary> /// 调整数据行的座标。当选中的行显示在顶处或底处,但是只显示一部份时,调整座标以显示整行的内容。 /// </summary> /// <param name="info"></param> private void AdjustItemPosistion(TreeListHitTestInfo info) { var y = info.Bounds.Y - _bound.ItemBound.Y; if (y < 0 || (y = info.Bounds.Bottom - _bound.ItemBound.Bottom) > 0) { _vbar.Value += y; var r = info.Bounds; r.Offset(0, -y); info.Bounds = r; if (info.Owner != null) { r = info.Owner.Bounds; r.Offset(0, -y); info.Owner.Bounds = r; } } }
private void ProcessItemCheckedChange(TreeListHitTestInfo info) { var vitem = (VirtualTreeListItem)info.Element; var item = (TreeListItem)vitem.Item; if (RaiseBeforeItemCheckChangeEvent(item)) { return; } item.Checked = !item.Checked; if (item.Mixed) { item.Mixed = false; } RaiseAfterItemCheckChangeEvent(item); InvalidateItem(vitem); }
private TreeListHitTestInfo HitTestCell(VirtualTreeListItem vitem, Rectangle rect, int x, int y) { var workRect = _bound.ItemBound; var x1 = workRect.X - GetOffsetLeft(); var item = (TreeListItem)vitem.Item; foreach (var column in Columns) { if (column.Index > item.Cells.Count) { return(null); } if (column.Hidden) { continue; } var rect1 = new Rectangle(x1, rect.Y, column.Width, ItemHeight); if (rect1.Contains(x, y)) { var owner = new TreeListHitTestInfo(TreeListHitTestType.Item, vitem, rect); if (column.Index <= item.Cells.Count - 1) { return(new TreeListHitTestInfo(TreeListHitTestType.Cell, item.Cells[column.Index], rect1) { Owner = owner }); } else { return(owner); } } x1 += column.Width; } return(null); }
/// <summary> /// 处理鼠标双击时 <see cref="TreeListHitTestInfo"/> 的处理。 /// </summary> /// <param name="info"></param> private void ProcessHitTestInfoDbClick(TreeListHitTestInfo info) { HideEditor(); switch (info.HitTestType) { case TreeListHitTestType.Cell: if (info.Owner != null) { ProcessHitTestInfoDbClick(info.Owner); } break; case TreeListHitTestType.Item: if (info.Element != null) { var item = (TreeListItem)((VirtualTreeListItem)info.Element).Item; RaiseItemDoubleClickEvent(item); } break; } }
/// <summary> /// 处理当前鼠标经过的对象。 /// </summary> /// <param name="info"></param> /// <param name="drawState"></param> private void ProcessHitTestInfo(TreeListHitTestInfo info, DrawState drawState) { if (info.Bounds.IsEmpty) { return; } switch (info.HitTestType) { case TreeListHitTestType.Column: var column = (TreeListColumn)info.Element; using (var graphics = CreateGraphics()) { var drawArgs = new TreeListColumnRenderEventArgs(column, graphics, info.Bounds) { DrawState = drawState }; graphics.KeepClip(_bound.ColumnBound, () => Renderer.DrawColumnHeader(drawArgs)); } break; case TreeListHitTestType.ColumnSize: Cursor = Cursors.VSplit; break; case TreeListHitTestType.Cell: if (info.Owner != null) { ProcessHitTestInfo(info.Owner, drawState); } var cell = (TreeListCell)info.Element; var rect = GetCellTextRectangle(cell, info.Bounds); ShowToolTip(cell, rect); break; case TreeListHitTestType.Item: if (HandCursor) { Cursor = Cursors.Hand; } if (drawState == DrawState.Pressed || !HotTracking) { return; } var vitem = (VirtualTreeListItem)info.Element; var item = (TreeListItem)vitem.Item; if (item.Selected) { return; } using (var graphics = CreateGraphics()) { var drawArgs = new TreeListItemRenderEventArgs(item, graphics, info.Bounds) { DrawState = drawState, Alternate = vitem.Index % 2 != 0 }; DrawItem(drawArgs); } break; } }