WPF FlowDocument Table - AutoFit option?

前端 未结 4 1820
臣服心动
臣服心动 2021-01-13 11:23

I want a table to logically size the columns according to the contents. Is this possible in WPF?

alt text http://img43.imageshack.us/img43/2640/flowdocument.jpg

4条回答
  •  醉话见心
    2021-01-13 11:58

    You can write a simplified "AutoFit" function like below, that roughly compacts the width of columns within a given extent.

    If you use Double, not Integer, and try to precisely calculate them, it may take much longer to converge wastefully.

    using System;
    using System.Windows;
    using System.Windows.Input;
    using System.Windows.Documents;
    using System.Windows.Controls;
    using System.Text.RegularExpressions;
    using System.Linq;
    using System.Collections.Generic;
    
    
    
    namespace Example {
    
        //----------------------------------------------------------------------------------------------------
        public class MyTable : Table {
    
            ...
    
            //------------------------------------------------------------------------------------------------
            public MyTable() {
    
                ...
    
                AutoFit();
    
                ...
    
            }
            //------------------------------------------------------------------------------------------------
    
            ...
    
            //------------------------------------------------------------------------------------------------
            private void AutoFit() {
    
                int extent = 10;
                int[] lengths = new int[this.Columns.Count];
    
                // collect content lengths of each column of the first 5 rows
                foreach(TableRow row in this.RowGroups[0].Rows.Take(5)) {
                    for(int i = 0; i < row.Cells.Count; i++) {
                        TableCell cell = row.Cells[i];
                        TextRange t = new TextRange(cell.ContentStart, cell.ContentEnd);
                        int length = new List(Regex.Split(t.Text, @"\r\n|[\r\n]")).Select(s => s.Length).Max();
                        lengths[i] = Math.Max(lengths[i], length);
                    }
                }
    
                // keep content lengths with column index before sort
                List contentSizes = lengths.Select((length, index) => {
                    return new ColumnSize() {Index = index, Size = length};
                }).OrderBy(e => e.Size).ToList();
    
                // assign compacted ratio to columns by recursion
                int[] compactedSizes = Compact(new int[contentSizes.Count], contentSizes, extent);
    
                // set width to columns
                for(int i = 0; i < compactedSizes.Length; i++) {
                    this.Columns[i].Width = new GridLength(compactedSizes[i], GridUnitType.Star);
                }
    
            }
            //------------------------------------------------------------------------------------------------
            private int[] Compact(int[] sizes, List contentSizes, int extent) {
    
                int min = contentSizes.Min(e => e.Size);
                int max = extent - contentSizes.Count + 1;
    
                contentSizes = contentSizes.Select(e => {
                    int size = (int)Math.Floor((double)e.Size / (double)min);
                    e.Size = size > max ? max : size;
                    return e;
                }).OrderBy(e => e.Size).ToList();
    
                if(contentSizes.Sum(e => e.Size) > extent) {
                    if(sizes.All(v => v == 0)) {
                        sizes = sizes.Select(v => 1).ToArray();
                    } else {
                        contentSizes.TakeWhile(e => e.Size == 1).ToList().ForEach(e => sizes[e.Index] += 1);
                    }
                    sizes = Compact(sizes, contentSizes.SkipWhile(e => e.Size <= 1).ToList(), extent);
                } else {
                    contentSizes.ForEach(e => sizes[e.Index] = e.Size);
                }
    
                return sizes;
    
            }
            //------------------------------------------------------------------------------------------------
            private class ColumnSize {
    
                public int Index { get; set; }
                public int Size { get; set; }
    
            }
            //------------------------------------------------------------------------------------------------
    
            ...
    
        }
        //----------------------------------------------------------------------------------------------------
    
    }
    

提交回复
热议问题