예제 #1
0
파일: TilePanel.cs 프로젝트: Daoting/dt
        /// <summary>
        /// 获取数据行的垂直位置
        /// </summary>
        /// <param name="p_index"></param>
        /// <returns></returns>
        internal override double GetRowVerPos(int p_index)
        {
            double height = 0;

            if (_owner.IsVir)
            {
                // 虚拟行,等高
                height = Math.Floor((double)p_index / _colCount) * _rowHeight;
                if (_owner.MapRows != null)
                {
                    // 等高有分组
                    int cnt = 0, iGrpRow = 0;
                    for (int i = 0; i < _owner.MapRows.Count; i++)
                    {
                        if (_owner.MapRows[i])
                        {
                            height += _owner.GroupRows[iGrpRow++].DesiredSize.Height;
                        }
                        else
                        {
                            cnt++;
                        }

                        if (cnt > p_index)
                        {
                            break;
                        }
                    }
                }
            }
            else
            {
                // 真实行
                if (_owner.MapRows == null)
                {
                    // 无分组
                    for (int i = 0; i < p_index; i++)
                    {
                        // 行末尾项
                        bool isRowLast = ((i + 1) % _colCount == 0);
                        if (isRowLast)
                        {
                            height += _rowHeight;
                        }
                    }
                }
                else
                {
                    // 有分组
                    int iDataRow = 0, iGrpRow = 0;
                    // 分组内的项目索引
                    int   indexInGroup = 0;
                    LvRow lastRow      = null;
                    for (int i = 0; i < _owner.MapRows.Count; i++)
                    {
                        if (_owner.MapRows[i])
                        {
                            if (lastRow != null)
                            {
                                // 上个分组最后未摆满一行
                                height += _rowHeight;
                                lastRow = null;
                            }
                            height += _owner.GroupRows[iGrpRow++].DesiredSize.Height;
                        }
                        else
                        {
                            bool isRowLast = ((indexInGroup + 1) % _colCount == 0);
                            if (isRowLast)
                            {
                                // 摆满一行
                                height += _rowHeight;
                                lastRow = null;
                            }
                            else
                            {
                                // 记录最后一项
                                lastRow = _dataRows[iDataRow];
                            }
                            iDataRow++;
                            indexInGroup++;
                        }

                        if (iDataRow >= p_index)
                        {
                            break;
                        }
                    }
                }
            }

            if (_groupHeader != null)
            {
                height -= _groupHeader.DesiredSize.Height;
            }
            return(Math.Max(height, 0));
        }
예제 #2
0
파일: TilePanel.cs 프로젝트: Daoting/dt
        protected override void ArrangeGroupRealRows(Size p_finalSize)
        {
            int      iGrpRow = 0, iDataRow = 0;
            double   totalHeight  = 0;
            GroupRow lastGroup    = null;
            bool     firstVisible = true;
            LvRow    lastRow      = null;
            // 分组内的项目索引
            int indexInGroup = 0;

            for (int i = 0; i < _owner.MapRows.Count; i++)
            {
                if (_owner.MapRows[i])
                {
                    // 布局分组
                    if (lastRow != null)
                    {
                        // 上个分组最后未摆满一行
                        totalHeight += _rowHeight;
                        lastRow      = null;
                    }
                    var gr = _owner.GroupRows[iGrpRow++];

                    // 若未进入可视区
                    if (firstVisible)
                    {
                        // top为行的上侧和滚动栏上侧的距离,bottom为行的下侧距离
                        double top    = totalHeight + _deltaY;
                        double bottom = top + gr.DesiredSize.Height;

                        // 可见区域:0 - _maxSize.Height
                        if ((top > 0 && top < _maxSize.Height) ||
                            (bottom > 0 && bottom < _maxSize.Height))
                        {
                            // 初次进入可见区,确定可见区顶端行所属分组
                            firstVisible = false;
                            lastGroup    = _owner.GroupRows[iGrpRow - 1];
                        }
                    }

                    gr.Arrange(new Rect(0, totalHeight, p_finalSize.Width, gr.DesiredSize.Height));
                    totalHeight += gr.DesiredSize.Height;
                    indexInGroup = 0;
                }
                else
                {
                    var row = _dataRows[iDataRow++];

                    // 若未进入可视区
                    if (firstVisible)
                    {
                        double top    = totalHeight + _deltaY;
                        double bottom = top + row.DesiredSize.Height;

                        // 可见区域:0 - _maxSize.Height
                        if ((top > 0 && top < _maxSize.Height) ||
                            (bottom > 0 && bottom < _maxSize.Height))
                        {
                            // 初次进入可见区,确定可见区顶端行所属分组
                            firstVisible = false;
                            lastGroup    = _owner.GroupRows[iGrpRow - 1];
                        }
                    }

                    bool isRowLast = ((indexInGroup + 1) % _colCount == 0);
                    row.Arrange(new Rect((indexInGroup % _colCount) * _itemWidth, totalHeight, isRowLast ? _itemWidth + 1 : _itemWidth, _rowHeight));

                    if (isRowLast)
                    {
                        // 摆满一行
                        totalHeight += _rowHeight;
                        lastRow      = null;
                    }
                    else
                    {
                        // 记录最后一项
                        lastRow = row;
                    }
                    indexInGroup++;
                }
            }

            // 分组导航头
            if (_groupHeader != null)
            {
                if (!_isScrolling &&
                    _deltaY < _groupHeader.DesiredSize.Height &&
                    lastGroup != null)
                {
                    // 离滚动栏顶部距离小于分组导航头高度时显示
                    // 分组导航头高度可能为0!
                    _groupHeader.SetCurrentGroup(lastGroup);
                    // -_deltaY确保始终在滚动栏顶部位置
                    _groupHeader.Arrange(new Rect(0, -_deltaY, p_finalSize.Width, _groupHeader.DesiredSize.Height));
                }
                else
                {
                    // 第一行在滚动栏下侧太远时不显示分组导航头
                    _groupHeader.Arrange(_rcEmpty);
                }
            }
        }
예제 #3
0
파일: TilePanel.cs 프로젝트: Daoting/dt
        protected override void ArrangeGroupVirRows(Size p_finalSize)
        {
            // 整个面板不在滚动栏可视区时,布局到空区域
            if (_deltaY >= _maxSize.Height ||       // 面板在滚动栏下方外部
                _deltaY <= -p_finalSize.Height)     // 面板在滚动栏上方外部
            {
                // 虚拟数据行
                foreach (var elem in _dataRows)
                {
                    elem.Arrange(_rcEmpty);
                }

                // 分组行
                foreach (var grp in _owner.GroupRows)
                {
                    grp.Arrange(_rcEmpty);
                }

                // 分组导航头
                _groupHeader?.Arrange(_rcEmpty);
                return;
            }


            int    iAllRow = 0, iGrpRow = 0, iDataRow = 0;
            double totalHeight = 0;
            // 分组内的项目索引
            int   indexInGroup = 0;
            LvRow lastRow      = null;

            //----------------------------------------------
            // 面板可见,在滚动栏下方,按顺序布局所有行
            //----------------------------------------------
            if (_deltaY >= 0 && _deltaY < _maxSize.Height)
            {
                // 分组导航头
                if (_groupHeader != null)
                {
                    if (!_isScrolling && _deltaY < _groupHeader.DesiredSize.Height)
                    {
                        // 离滚动栏顶部距离小于分组导航头高度时显示
                        // 分组导航头高度可能为0!
                        _groupHeader.SetCurrentGroup(_owner.GroupRows[0]);
                        // -_deltaY确保始终在滚动栏顶部位置
                        _groupHeader.Arrange(new Rect(0, -_deltaY, p_finalSize.Width, _groupHeader.DesiredSize.Height));
                    }
                    else
                    {
                        // 离滚动栏顶部太远时不显示分组导航头
                        _groupHeader.Arrange(_rcEmpty);
                    }
                }

                for (int i = 0; i < _owner.MapRows.Count; i++)
                {
                    if (_owner.MapRows[i])
                    {
                        // 布局分组行
                        if (lastRow != null)
                        {
                            // 上个分组最后未摆满一行
                            totalHeight += _rowHeight;
                            lastRow      = null;
                        }

                        var gr = _owner.GroupRows[iGrpRow];
                        gr.Arrange(new Rect(0, totalHeight, p_finalSize.Width, gr.DesiredSize.Height));
                        totalHeight += gr.DesiredSize.Height;
                        iGrpRow++;
                        indexInGroup = 0;
                    }
                    else
                    {
                        // 布局数据行
                        var row = _dataRows[iDataRow];
                        // 行末尾项宽度加1为隐藏右边框
                        bool isRowLast = ((indexInGroup + 1) % _colCount == 0);
                        row.Arrange(new Rect((indexInGroup % _colCount) * _itemWidth, totalHeight, isRowLast ? _itemWidth + 1 : _itemWidth, _rowHeight));
                        row.SetViewRow(_owner.Rows[i - iGrpRow], true);

                        if (isRowLast)
                        {
                            // 摆满一行
                            totalHeight += _rowHeight;
                            lastRow      = null;
                        }
                        else
                        {
                            // 记录最后一项
                            lastRow = row;
                        }

                        iDataRow++;
                        indexInGroup++;

                        // 虚拟行都已布局时退出
                        if (iDataRow >= _dataRows.Count)
                        {
                            break;
                        }
                    }

                    // 剩下行不可见,结束布局
                    if (_deltaY + totalHeight > _maxSize.Height)
                    {
                        break;
                    }
                }

                // 将剩余的虚拟行和分组行布局到空区域
                if (iDataRow < _dataRows.Count)
                {
                    for (int i = iDataRow; i < _dataRows.Count; i++)
                    {
                        _dataRows[i].Arrange(_rcEmpty);
                    }
                }
                if (iGrpRow < _owner.GroupRows.Count)
                {
                    for (int i = iGrpRow; i < _owner.GroupRows.Count; i++)
                    {
                        _owner.GroupRows[i].Arrange(_rcEmpty);
                    }
                }
                return;
            }

            //----------------------------------------------
            // _deltaY < 0 && _deltaY > -p_finalSize.Height
            // 面板顶部超出滚动栏 并且 没有整个面板都超出,此时_deltaY为负数
            //----------------------------------------------

            // 避免所有行完全超出滚动栏顶部的情况
            iAllRow = _owner.MapRows.Count;
            GroupRow lastGroup = null;

            // 布局顶部超出的分组、计算总高、数据行索引
            for (int i = 0; i < _owner.MapRows.Count; i++)
            {
                if (_owner.MapRows[i])
                {
                    // 分组行
                    // 布局上个分组
                    if (lastGroup != null)
                    {
                        lastGroup.Arrange(_rcEmpty);
                    }

                    lastGroup = _owner.GroupRows[iGrpRow];
                    double height = lastGroup.DesiredSize.Height;
                    if (totalHeight + height > -_deltaY)
                    {
                        // 进入可见区
                        iAllRow = i;
                        break;
                    }

                    iGrpRow++;
                    totalHeight += height;
                    indexInGroup = 0;
                }
                else
                {
                    // 数据行
                    if (indexInGroup % _colCount == 0)
                    {
                        // 换行
                        if (totalHeight + _rowHeight > -_deltaY)
                        {
                            // 进入可见区
                            iAllRow = i;
                            break;
                        }
                        totalHeight += _rowHeight;
                    }
                    iDataRow++;
                    indexInGroup++;
                }
            }
            // 可见数据行在所有虚拟行的索引
            iDataRow = iDataRow % _pageItemCount;

            // 分组导航头
            if (_groupHeader != null)
            {
                if (!_isScrolling && iAllRow < _owner.MapRows.Count)
                {
                    _groupHeader.SetCurrentGroup(lastGroup);
                    // -_deltaY确保始终在滚动栏顶部位置
                    _groupHeader.Arrange(new Rect(0, -_deltaY, p_finalSize.Width, _groupHeader.DesiredSize.Height));
                }
                else
                {
                    // 所有数据行都在滚动栏上侧
                    _groupHeader.Arrange(_rcEmpty);
                }
            }

            // 布局可视行
            int iStart = iDataRow;

            for (int i = iAllRow; i < _owner.MapRows.Count; i++)
            {
                if (_owner.MapRows[i])
                {
                    // 布局分组
                    if (lastRow != null)
                    {
                        // 上个分组最后未摆满一行
                        totalHeight += _rowHeight;
                        lastRow      = null;
                    }

                    var gr = _owner.GroupRows[iGrpRow];
                    gr.Arrange(new Rect(0, totalHeight, p_finalSize.Width, gr.DesiredSize.Height));
                    totalHeight += gr.DesiredSize.Height;
                    iGrpRow++;
                    indexInGroup = 0;
                }
                else
                {
                    var row = _dataRows[iDataRow];
                    // 行末尾项宽度加1为隐藏右边框
                    bool isRowLast = ((indexInGroup + 1) % _colCount == 0);
                    row.Arrange(new Rect((indexInGroup % _colCount) * _itemWidth, totalHeight, isRowLast ? _itemWidth + 1 : _itemWidth, _rowHeight));
                    row.SetViewRow(_owner.Rows[i - iGrpRow], true);

                    if (isRowLast)
                    {
                        // 摆满一行
                        totalHeight += _rowHeight;
                        lastRow      = null;
                    }
                    else
                    {
                        // 记录最后一项
                        lastRow = row;
                    }

                    iDataRow++;
                    indexInGroup++;
                    if (iDataRow >= _dataRows.Count)
                    {
                        iDataRow = 0;
                    }
                    if (iDataRow == iStart)
                    {
                        break;
                    }
                }

                // 剩下行不可见,结束布局
                if (_deltaY + totalHeight > _maxSize.Height)
                {
                    break;
                }
            }

            // 无法确定剩余的虚拟行,上次布局在不可见区域不需再布局!

            // 将剩余分组布局到空区域
            if (iGrpRow < _owner.GroupRows.Count)
            {
                for (int i = iGrpRow; i < _owner.GroupRows.Count; i++)
                {
                    _owner.GroupRows[i].Arrange(_rcEmpty);
                }
            }
        }