Решение:
Хитрость заключается в том, чтобы установить ширину столбца авто , чтобы получить нужное пространство (после настройки на авто, не забудьте обновить макет!). Я нашел этот подсказку в файле 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 <see cref="DataGridColumn"/> 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
}
}
Просмотр
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);
}
Спасибо за ваш ответ. Это уже привело меня в правильном направлении. Я отправлю свое решение, как только оно будет готово. –