2016-07-07 1 views
1

Я пытаюсь анимировать столбцы в DataGrid. Это также отлично работает. Тем не менее, мне всегда нужна максимальная ширина, которая хочет иметь столбец, чтобы вычислить оттуда отношение к ширине DataGrid.Всегда получать максимальную необходимую ширину столбца/пространство dataGrid

Это работает при первом звонке. Но как только столбцы когда-то были анимированы, «DesiredValue» всегда равно значению столбца.

((DataGridTemplateColumn)column).Width.DesiredValue 

Есть ли у кого-нибудь решение или способ всегда иметь максимальную требуемую ширину одного или всех столбцов?

спасибо

приветствие Доминика

ответ

0

Решение:

Хитрость заключается в том, чтобы установить ширину столбца авто , чтобы получить нужное пространство (после настройки на авто, не забудьте обновить макет!). Я нашел этот подсказку в файле Framework.dll .NetFramework (найденный в 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; 
     } 
    } 

Вот мой метод для регулировки ширины Колум (есть обычай DataGrid Control):

Волшебный метод:

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 Try:

Вот попытка моего решения. Проблема здесь в том, что если столбец не находится в представлении, «переменная ячейки» всегда будет равна нулю.

Теперь я сделаю поведение для своих 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; 
} 

Это просто итерация по всем значениям столбца, измерение текста и возврат максимальной ширины.

EDIT:

К сожалению, я вижу, что вы ищете решение в МОФ. TextRenderer - это WinForms. Но есть способы измерения текста в МОФ, как описано здесь: WPF equivalent to TextRenderer

Может быть, это немного помогает ...

+0

Спасибо за ваш ответ. Это уже привело меня в правильном направлении. Я отправлю свое решение, как только оно будет готово. –

Смежные вопросы