始终获取dataGrid

时间:2016-07-07 09:45:03

标签: c# .net wpf datagrid wpfdatagrid

我试图在DataGrid中为列添加动画效果。这也很完美。但是,我总是需要一个想要有一个列的最大宽度,以便从中计算出与DataGrid宽度的比率。

这适用于第一次通话。但是一旦这些专栏被动画化,就会出现#34; DesiredValue"始终等于列的值。

((DataGridTemplateColumn)column).Width.DesiredValue

是否有人有解决方案或方法始终拥有一列或所有列的最大所需宽度?

谢谢

问候 星

2 个答案:

答案 0 :(得分:2)

它没有经过测试,但我认为应该做你想做的事情?

int GetMaximumColumnWidth(DataGrid Grid, int ColumnIndex)
{
    int maximum = 0;
    foreach(DataRow row in Grid.Rows)
    {
        string text = row.ItemArray[ColumnIndex];
        Size textSize = TextRenderer.MeasureText(text, Grid.Font);

        if(textSize.Width > maximum)
        {
             maximum = textSize.Width;
        }
    }

    return maximum;
} 

这只是迭代列的所有值,测量文本并返回最大宽度。

编辑:

抱歉,我发现您正在寻找wpf的解决方案。 TextRenderer是WinForms。但是也有一些方法来测量wpf中的文本,如下所述: WPF equivalent to TextRenderer

也许它有点帮助...

答案 1 :(得分:0)

解决方案:

诀窍是将列的宽度设置为auto,以获得所需的空间(设置为auto后,不要忘记更新布局!)。我在.NetFramework的Framework.dll中找到了提示(在DataGridColumnHeader.cs中找到)。如果双击"夹子",该列将获得所需的宽度。

    public void AdjustColumns()
    {
        double availableSpace = this.ActualWidth;
        double starSpace = 0.0;
        double starFactor = 0.0;

        Dictionary<HTDataGridTemplateColumn, DataGridLengthAnimation> columnAnimations = new Dictionary<HTDataGridTemplateColumn, DataGridLengthAnimation>();

        Storyboard storyboard = new Storyboard();

        foreach (DataGridColumn column in this.Columns.AsParallel())
        {
            if (column.Visibility == Visibility.Visible && column.GetType() == typeof(HTDataGridTemplateColumn) && ((HTDataGridTemplateColumn)column).ResizeMode != HTDataGridTemplateColumn.ResizeModeOptions.None)
            {
                DataGridLengthAnimation animation = new DataGridLengthAnimation
                {
                    From = column.ActualWidth,
                    DataGridLengthUnitType = DataGridLengthUnitType.Pixel,
                    Duration = new Duration(TimeSpan.FromMilliseconds(250)),
                    FillBehavior = FillBehavior.Stop
                };

                column.Width = DataGridLength.Auto;

                columnAnimations.Add((HTDataGridTemplateColumn)column, animation);

                Storyboard.SetTarget(animation, column);
                Storyboard.SetTargetProperty(animation, new PropertyPath(DataGridColumn.WidthProperty));

                storyboard.Children.Add(animation);
            }
        }

        this.UpdateLayout();

        foreach (KeyValuePair<HTDataGridTemplateColumn, DataGridLengthAnimation> columnAnimation in columnAnimations)
        {
            if (columnAnimation.Key.ResizeMode == HTDataGridTemplateColumn.ResizeModeOptions.Fit)
            {
                availableSpace -= columnAnimation.Key.Width.DesiredValue;

                columnAnimation.Value.To = columnAnimation.Key.Width.DesiredValue;
                columnAnimation.Value.Completed += (sender, args) =>
                {
                    columnAnimation.Key.Width = new DataGridLength(columnAnimation.Key.Width.DesiredValue, DataGridLengthUnitType.Pixel);
                };
            }
            else
                starSpace += columnAnimation.Key.Width.DesiredValue;
        }

        if (starSpace > 0.0)
            starFactor = availableSpace/starSpace;

        foreach (KeyValuePair<HTDataGridTemplateColumn, DataGridLengthAnimation> columnAnimation in columnAnimations.Where(a => a.Key.ResizeMode == HTDataGridTemplateColumn.ResizeModeOptions.Stretch))
        {
            columnAnimation.Value.To = columnAnimation.Key.Width.DesiredValue * starFactor;
            columnAnimation.Value.Completed += (sender, args) =>
            {
                columnAnimation.Key.Width = new DataGridLength(columnAnimation.Key.Width.DesiredValue * starFactor, DataGridLengthUnitType.Pixel);
            };
        }

        storyboard.Begin();
    }
}

以下是调整列宽的方法(获取自定义DataGrid控件):

神奇的方法:

public class HTDataGridTemplateColumn : DataGridTemplateColumn
{
    /// <summary>
    /// Declare how the &lt;see cref="DataGridColumn"/&gt; should be resized. 
    /// </summary>
    public ResizeModeOptions ResizeMode
    {
        get { return (ResizeModeOptions)GetValue(ResizeModeProperty); }
        set { SetValue(ResizeModeProperty, value); }
    }

    public static readonly DependencyProperty ResizeModeProperty = DependencyProperty.Register("ResizeMode", typeof(ResizeModeOptions), typeof(HTDataGridTemplateColumn), new PropertyMetadata(ResizeModeOptions.None));

    /// <summary>
    /// Declare how the <see cref="DataGridColumn"/> should be resized.
    /// </summary>
    public enum ResizeModeOptions
    {
        /// <summary>
        /// No resize animation/action will be done.
        /// </summary>
        None,
        /// <summary>
        /// The width is adjusted.
        /// </summary>
        Fit,
        /// <summary>
        /// The width is streched.
        /// </summary>
        Stretch
    }
}

<强> HTDataGridTemplateColumn:

    private double[,] _CellSizeArray;
    private double[] _ColumnSize;

    //Only call once!
    private void CalculateCellSizeArray()
    {
        try
        {
            _CellSizeArray = new double[this.Columns.Count, this.Items.Count];

            foreach (object item in this.Items)
            {
                DataGridRow row = this.ItemContainerGenerator.ContainerFromItem(item) as DataGridRow;
                DataGridCellsPresenter presenter = Helper.VisualTree.GetVisualChild<DataGridCellsPresenter>(row);

                for (int i = 0; i < this.Columns.Count; i++)
                {
                    DataGridCell cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(i);

                    if (cell == null)
                    {
                        this.UpdateLayout();
                        this.ScrollIntoView(this.Columns[i]);
                        cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(i);
                    }

                    TextBlock textBlock = Helper.VisualTree.GetVisualChild<TextBlock>(cell);

                    DependencyPropertyDescriptor dp = DependencyPropertyDescriptor.FromProperty(TextBlock.TextProperty, typeof(TextBlock));

                    dp.AddValueChanged(textBlock, (object a, EventArgs b) =>
                    {
                        Size s = MeasureTextSize(textBlock.Text, textBlock.FontFamily, textBlock.FontStyle, textBlock.FontWeight, textBlock.FontStretch, textBlock.FontSize);
                        _CellSizeArray[i, row.GetIndex()] = s.Width;
                    });

                    Size size = MeasureTextSize(textBlock.Text, textBlock.FontFamily, textBlock.FontStyle, textBlock.FontWeight, textBlock.FontStretch, textBlock.FontSize);

                    _CellSizeArray[i, row.GetIndex()] = size.Width;
                }
            }
            CalculateColumnSize();
        }
        catch (Exception exception)
        {

        }

    }

    private void CalculateColumnSize()
    {
        _ColumnSize = new double[this.Columns.Count];

        for (int column = 0; column < _CellSizeArray.GetLength(0); column++)
        {
            for (int row = 0; row < _CellSizeArray.GetLength(1); row++)
            {
                if (_CellSizeArray[column, row] > _ColumnSize[column])
                    _ColumnSize[column] = _CellSizeArray[column, row];
            }
        }
    }

    /// <summary>
    /// Get the required height and width of the specified text. Uses FortammedText
    /// </summary>
    public static Size MeasureTextSize(string text, FontFamily fontFamily, FontStyle fontStyle, FontWeight fontWeight, FontStretch fontStretch, double fontSize)
    {
        FormattedText ft = new FormattedText(text, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface(fontFamily, fontStyle, fontWeight, fontStretch), fontSize, Brushes.Black);
        return new Size(ft.Width, ft.Height);
    }

    /// <summary>
    /// Get the required height and width of the specified text. Uses Glyph's
    /// </summary>
    public static Size MeasureText(string text, FontFamily fontFamily, FontStyle fontStyle, FontWeight fontWeight, FontStretch fontStretch, double fontSize)
    {
        Typeface typeface = new Typeface(fontFamily, fontStyle, fontWeight, fontStretch);
        GlyphTypeface glyphTypeface;

        if (!typeface.TryGetGlyphTypeface(out glyphTypeface))
        {
            return MeasureTextSize(text, fontFamily, fontStyle, fontWeight, fontStretch, fontSize);
        }

        double totalWidth = 0;
        double height = 0;

        for (int n = 0; n < text.Length; n++)
        {
            ushort glyphIndex = glyphTypeface.CharacterToGlyphMap[text[n]];

            double width = glyphTypeface.AdvanceWidths[glyphIndex] * fontSize;

            double glyphHeight = glyphTypeface.AdvanceHeights[glyphIndex] * fontSize;

            if (glyphHeight > height)
            {
                height = glyphHeight;
            }

            totalWidth += width;
        }

        return new Size(totalWidth, height);
    } 

预览

small

big

OLD尝试:

这是我的解决方案的尝试。这里的问题是,如果列不在视图中,那么&#34;单元格变量&#34;将永远为空。

现在,我将为DataGridColumns创建一个行为,以便在Text更改时通知父DataGrid其大小。希望这能完成这项工作。

{{1}}