2016-07-07 57 views
1

我试图在DataGrid中为动画列添加动画。这也很完美。但是,我总是需要希望有一列的最大宽度,以便从中计算与DataGrid宽度的比率。始终获得dataGrid所需的最大列宽度/空间

这适用于第一次通话。但只要列一旦动画,“DesiredValue”总是等于该列的值。

((DataGridTemplateColumn)column).Width.DesiredValue 

有没有人有解决方案或方法总是有一个或所有列的最大所需宽度?

谢谢

问候 多米尼克

回答

0

解决方法:

关键是要设置列到汽车的宽度,以获得所需的空间(设置为自动后,不要忘记更新您的布局!)。我发现在.NetFramework的Framework.dll中提示(在DataGridColumnHeader.cs中找到)。如果您双击“抓手”,该列将获得所需的宽度。

private void OnGripperDoubleClicked(object sender, MouseButtonEventArgs e) 
    { 
     DataGridColumnHeader header = this.HeaderToResize(sender); 
     if ((header != null) && (header.Column != null)) 
     { 
      header.Column.Width = DataGridLength.Auto; 
      e.Handled = true; 
     } 
    } 

这是我的方法来调整式柱宽度(得自定义数据网格控制):

神奇方法:

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(); 
    } 
} 

HTDataGridTemplateColumn:

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 
    } 
} 

预览

small

big

OLD尝试:

这里是我的解决方案的尝试。这里的问题是,如果该列不在视图中,“单元变量”将始终为空。

现在我将为我的DataGridColumns做出行为,以便在文本更改时通知父DataGrid的大小。希望这能够完成这项工作。

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); 
    } 
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

也许这有助于一点点...

+0

感谢您的回答。这已经使我朝着正确的方向发展。准备就绪后,我会立即发布我的解决方案。 –

相关问题