private void Hover(Point location)
        {
            SEListViewHitInfo hitInfo = _layoutManager.HitTest(location);

            if (hitInfo.ItemHit)
            {
                HoveredItem = Items[hitInfo.ItemIndex];
            }
            else
            {
                HoveredItem = null;
            }
        }
        protected override void OnMouseDoubleClick(MouseEventArgs e)
        {
            if (ItemDoubleClick != null)
            {
                SEListViewHitInfo hitInfo = _layoutManager.HitTest(e.Location);
                if (hitInfo.ItemHit)
                {
                    SEListViewItem item = Items[hitInfo.ItemIndex];
                    OnItemDoubleClick(item);
                }
            }

            base.OnMouseDoubleClick(e);
        }
        public void MouseDown(MouseEventArgs e)
        {
            /*
             * 如果按下的是鼠标右键
             * 如果按在已选定的项上,只切换焦点,不改变选择
             * 如果按在未选定项上,则切换为点的项为选中项
             * 不考虑键盘按键
             */

            _mouseItemsAreaOffset = _itemsAreaOffset;

            List <SEListViewItem> oldSelectedItems = _imageListView.GetSelectedItems();

            SEListViewHitInfo hitInfo = HitTest(e.Location);

            if (hitInfo.ItemHit)
            {
                SEListViewItem        item               = _imageListView.Items[hitInfo.ItemIndex];
                List <SEListViewItem> allItems           = _imageListView.Items.ToList();
                SEListViewItem        currentFocusedItem = _imageListView.FocusedItem;

                if (_imageListView.LeftButton)
                {
                    #region 如果不允许多选
                    if (_imageListView.AllowMultiSelection == false)
                    {
                        //如果点击的项就是当前选择的项
                        if (oldSelectedItems.Count > 0 && oldSelectedItems.Contains(item))
                        {
                            //判断Control键是否按下,如果按下了Control键,取消当前项的选择状态
                            if (_imageListView.ControlKey)
                            {
                                item.Selected = false;
                            }
                        }
                        else
                        {
                            //如果点击的项不是当前选择的项
                            //清除原选定项的选定状态
                            _imageListView.ClearSelect();
                            //设置新项为选定项
                            item.Selected = true;
                        }
                    }
                    #endregion
                    #region 如果允许多选
                    //在同时按下 Control 和 Shift 的情况下,优先考虑 Shift
                    else
                    {
                        #region 如果按下 Shift
                        //判断是否按下了 Shift ,如果按下 Shift,不考虑 Control 的状态
                        //也不用考虑是否点击的项是否是现有选定项之一
                        if (_imageListView.ShiftKey)
                        {
                            //如果当前存在具有输入焦点的项
                            if (currentFocusedItem != null && currentFocusedItem != item)
                            {
                                //连续选中从当前具有焦点的项至点击的项之间的所有项
                                //并将不在此范围内的项取消选中状态
                                int startIndex = Math.Min(currentFocusedItem.Index, hitInfo.ItemIndex);
                                int endIndex   = Math.Max(currentFocusedItem.Index, hitInfo.ItemIndex);
                                foreach (var i in from c in oldSelectedItems where c.Index <startIndex || c.Index> endIndex select c)
                                {
                                    i.Selected = false;
                                }
                                for (int i = startIndex; i <= endIndex; i++)
                                {
                                    SEListViewItem eachItem = allItems[i];
                                    if (eachItem.Selected == false)
                                    {
                                        eachItem.Selected = true;
                                    }
                                }
                            }
                            //如果当前不存在具有输入焦点的项
                            else
                            {
                                //清除原选定项的选定状态
                                _imageListView.ClearSelect();
                                item.Selected = true;
                            }
                        }
                        #endregion
                        #region 如果 Shift键没有处于按下状态
                        else
                        {
                            #region 如果点击的项 是 当前选择的项之一
                            if (oldSelectedItems.Count > 0 && oldSelectedItems.Contains(item))
                            {
                                //判断是否按下了 Control,且没有按下 Shift
                                if (_imageListView.ControlKey && _imageListView.ShiftKey == false)
                                {
                                    item.Selected = false;
                                }

                                //判断是否什么键都没有按下
                                if (_imageListView.ControlKey == false && _imageListView.ShiftKey == false)
                                {
                                    //清除原选定项的选定状态
                                    _imageListView.ClearSelect();
                                    item.Selected = true;
                                }
                            }
                            #endregion
                            #region 如果点击的项 不是 当前选择的项之一
                            else
                            {
                                //判断Control键是否按下,如果按下了Control键,则保持原有选择的情况把新项也设置为选中
                                //否则清除当前选择
                                if (_imageListView.ControlKey == false)
                                {
                                    //清除原选定项的选定状态
                                    _imageListView.ClearSelect();
                                }
                                item.Selected = true;
                            }
                            #endregion
                        }
                        #endregion
                    }
                    #endregion
                }
                else
                {
                    //如果点在未选中的项上
                    if (oldSelectedItems.Contains(item) == false)
                    {
                        _imageListView.ClearSelect();
                        //设置新项为选定项
                        item.Selected = true;
                    }
                }

                #region 为项设置输入焦点

                //设置新的输入焦点要放在后面处理,因为在使用Shift连续选择时,需要用到原具有焦点的项
                if (currentFocusedItem == null || (currentFocusedItem != null && currentFocusedItem != item))
                {
                    if (currentFocusedItem != null)
                    {
                        currentFocusedItem.Focused = false;
                    }
                    item.Focused = true;
                }
                #endregion
            }
            else
            {
                _imageListView.ClearSelect();
            }

            List <SEListViewItem> newSelectedItems = _imageListView.GetSelectedItems();
            if (oldSelectedItems.SequenceEqual(newSelectedItems) == false)
            {
                _imageListView.NeedPaint();
                _imageListView.OnSelectedItemChanged();
            }
        }
        public SEListViewHitInfo HitTest(Point point)
        {
            int itemIndex = -1;

            //这里对X,Y坐标的减,实现目的是平移坐标
            //传进来的是相对控件左上角的坐标,应平移为Padding后的内框左上角相对坐标
            //但是要考虑滚动时,上面的Padding也允许显示项
            //X坐标直接向右平移即可
            //Y坐标在没有滚动时,直接向下平移,如果存在滚动,当滚动值小于顶部Padding时
            //将Y坐标平移至项的最层端Y坐标上,即:Padding-滚动值

            //相对于Padding后的内框坐标系的坐标
            Point relativePoint = point;

            // Normalize to item area coordinates
            relativePoint.X -= ItemsBounds.Left;

            //y即平移量
            //此处y坐标需要在绘制项的区域(Padding后的区域)的基础上,考虑滚动条的offset
            int y = ItemsArea.Top - _itemsAreaOffset;

            if (y < 0)
            {
                y = 0;
            }
            relativePoint.Y -= y;

            if (relativePoint.X > 0 && relativePoint.Y > 0)
            {
                //当前点击的行和列的索引,从0开始
                //int col = relativePoint.X / _itemSizeWithMargin.Width;
                int row = (relativePoint.Y + _itemsBoundsOffset) / _itemSizeWithMargin;

                ////判断点的是不是右边的空白,可能右边会有比较大的空白,又没大到够完整的显示一列图像
                //bool isNotHitRightEmptyArea = col <= _columnCount - 1;
                //if (isNotHitRightEmptyArea)
                //{
                //    int index = row * _columnCount + col;

                //    //判断是不是点在图像区域内,还是图像边上,四周的Margin上
                //    Rectangle bounds = GetItemBounds(index);
                //    //判断点的坐标是不是在项的显示区域(Bounds)内,要用相对整个控件的原始坐标
                //    //因为项的bounds是相对整个控件的
                //    bool isHitInItem = bounds.Contains(point.X, point.Y);

                //    if (isHitInItem)
                //    {
                //        itemIndex = index;
                //    }
                //}

                int       index       = row;
                Rectangle bounds      = GetItemBounds(index);
                bool      isHitInItem = bounds.Contains(point.X, point.Y);

                if (isHitInItem)
                {
                    itemIndex = index;
                }
            }

            //是否点击在了有效项上
            bool itemHit = itemIndex >= 0 && itemIndex < _imageListView.Items.Count;

            SEListViewHitInfo hitInfo = new SEListViewHitInfo(itemIndex, itemHit);

            return(hitInfo);
        }