示例#1
0
        public static void ArrangeColumns(SpreadsheetView spreadsheet)
        {
            if (spreadsheet == null)
                return;

            var columns = new List<IColumn>();

            Action<SpreadsheetColumnCollection, List<IColumn>> addColumns = null;
            addColumns = (collection, list) =>
            {
                if (collection == null)
                    return;

                foreach (var column in collection)
                {
                    var stackColumn = column as IStackColumn;
                    if (stackColumn != null)
                    //if (column.IsParent)
                        //if (stackColumn is IDetailColumn && stackColumn.SubColumns.Count == 0)
                        //    list.Add(stackColumn);
                        //else
                        {
                            var columnPresenter = column.ColumnPresenter as StackColumnHeader;
                            if (columnPresenter != null)
                            {
                                if (!columnPresenter.ShowSubColumns)
                                    list.Add(column);
                                else
                                    addColumns(stackColumn.SubColumns, list);
                            }
                            else
                                addColumns(stackColumn.SubColumns, list);
                        }
                    else
                        list.Add(column);
                }
            };

            addColumns(spreadsheet.Columns, columns);
            if (columns.Count == 0)
                return;

            foreach (IColumn column in columns)
            {
                if (column.ColumnPresenter != null)
                {
                    if (!column.WidthBeforeArrangement.HasValue)
                        column.WidthBeforeArrangement = column.ColumnPresenter.DesiredSize.Width;
                    else if (!double.IsNaN(column.Width))
                        column.WidthBeforeArrangement = ((column.WidthBeforeArrangement + column.Width) / 2);
                }
            }

            var columnPresenterList = columns.Where(x => x.ColumnPresenter != null).Select(x => x.ColumnPresenter).ToList();

            var spreadSheetWidth = spreadsheet.CalculateSpreadsheetWidth();

            var totalDesiredWidth = columnPresenterList.Sum(x =>
                                    {
                                        var sourceColumn = x.DataContext as IColumn;
                                        return sourceColumn != null && sourceColumn.WidthBeforeArrangement.HasValue
                                            ? Math.Min(sourceColumn.WidthBeforeArrangement.Value, x.DesiredSize.Width)
                                            : x.DesiredSize.Width;
                                    });
            var totalAvailableWidth = spreadSheetWidth;

            if (spreadsheet.ParentSpreadsheet == null)
            {
                var rowIndicatorColumns = columns.Where(x => x.IsRowIndicator);
                if (rowIndicatorColumns.Any())
                {
                    columnPresenterList.RemoveAll(x => ((IColumn)x.DataContext).IsRowIndicator);
                    var rowIndicatorColumnsWidth = rowIndicatorColumns.Sum(x => x.Width);
                    totalDesiredWidth = totalDesiredWidth - rowIndicatorColumnsWidth;
                    totalAvailableWidth = spreadSheetWidth - rowIndicatorColumnsWidth;
                }
            }

            if (totalDesiredWidth > totalAvailableWidth)
            {
                var midWidth = totalAvailableWidth / columnPresenterList.Count;

                var columnDict = new Dictionary<IColumn, WidthRestrictions>();
                foreach (var child in columnPresenterList)
                {
                    if (child.DataContext is IColumn)
                    {
                        var column = child.DataContext as IColumn;

                        var defaultRange = new WidthRestrictions(column.MinWidth, column.MaxWidth);
                        defaultRange.UpdateValue(column.WidthBeforeArrangement.HasValue 
                                                    ? Math.Min(column.WidthBeforeArrangement.Value, child.DesiredSize.Width) 
                                                    : child.DesiredSize.Width);

                        columnDict.Add(column, defaultRange);
                    }
                }

                var regularColumns = columnDict.Where(x => x.Value.DesiredWidth <= midWidth).ToList();
                var wideColumns = columnDict.Where(x => x.Value.DesiredWidth > midWidth).ToList();
                var totalMinWidth = columnDict.Select(x => x.Value.DesiredWidth > midWidth ? midWidth : x.Value.DesiredWidth).Sum();
                var availableWidthLeft = totalAvailableWidth - totalMinWidth;
                var wideColumnsTotalWidth = wideColumns.Sum(x => x.Value.DesiredWidth);

                if (availableWidthLeft < wideColumnsTotalWidth)
                {
                    var availableWidth80 = Math.Ceiling(availableWidthLeft * 0.8);
                    var availableWidth20 = Math.Ceiling(availableWidthLeft * 0.2);

                    foreach (var col in wideColumns.ToList())
                    {
                        var currentValue = columnDict[col.Key].DesiredWidth;   
                        var newPossibleValue = Math.Ceiling(midWidth + ((col.Value.DesiredWidth / wideColumnsTotalWidth) * availableWidth80));

                        if ((newPossibleValue < 150) && (currentValue > newPossibleValue * 2))
                            columnDict[col.Key].UpdateValue(newPossibleValue * 2);
                        else
                            columnDict[col.Key].UpdateValue(newPossibleValue);
                    }

                    var extraWidth = availableWidth20 / regularColumns.Count;
                    foreach (var col in regularColumns.ToList())
                    {
                        columnDict[col.Key].UpdateValue(columnDict[col.Key].DesiredWidth + extraWidth);
                    }
                }
                else if (availableWidthLeft > wideColumnsTotalWidth)
                {
                    var extraWidth = (availableWidthLeft - wideColumnsTotalWidth) / columnDict.Count;

                    foreach (var col in regularColumns.ToList())
                    {
                        columnDict[col.Key].UpdateValue(columnDict[col.Key].DesiredWidth + extraWidth);
                    }

                    foreach (var col in wideColumns.ToList())
                    {
                        columnDict[col.Key].UpdateValue(midWidth + ((col.Value.DesiredWidth / wideColumnsTotalWidth) * availableWidthLeft) + extraWidth);
                    }
                }

                foreach (var item in columnDict)
                {
                    if (item.Key.ColumnPanelLoaded)
                        item.Key.Width = Math.Ceiling(item.Value.DesiredWidth);//Math.Round(item.Value.DesiredWidth, 0);
                }

                foreach (var col in spreadsheet.Columns.Where(x => x.IsParent))
                {
                    col.UpdateAutoSize();
                }

                var roundingInaccuracy = spreadSheetWidth - columns.Sum(x => x.Width);
                if (wideColumns.Any() && roundingInaccuracy > 0)
                {
                    columnDict.FirstOrDefault(x => x.Key == wideColumns.First().Key).Key.Width += roundingInaccuracy;
                }
            }
            else
            {
                var extraSpace = (totalAvailableWidth - totalDesiredWidth) / columns.Count(x => !x.IsRowIndicator);
                foreach (var column in columns.Where(x => !x.IsRowIndicator))
                {
                    if (column.ColumnPanelLoaded && (double.IsNaN(column.Width) || column.WidthBeforeArrangement.HasValue))
                        column.Width = Math.Ceiling((column.WidthBeforeArrangement.HasValue
                                                        ? Math.Min(column.WidthBeforeArrangement.Value, column.ColumnPresenter.DesiredSize.Width)
                                                        : column.ColumnPresenter.DesiredSize.Width) + extraSpace);
                    else
                        column.Width += extraSpace;
                }
            }
        }