我试图在DataGrid中为列添加动画效果。这也很完美。但是,我总是需要一个想要有一个列的最大宽度,以便从中计算出与DataGrid宽度的比率。
这适用于第一次通话。但是一旦这些专栏被动画化,就会出现#34; DesiredValue"始终等于列的值。
((DataGridTemplateColumn)column).Width.DesiredValue
是否有人有解决方案或方法始终拥有一列或所有列的最大所需宽度?
谢谢
问候 星
答案 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 <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
}
}
<强> 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);
}
这是我的解决方案的尝试。这里的问题是,如果列不在视图中,那么&#34;单元格变量&#34;将永远为空。
现在,我将为DataGridColumns创建一个行为,以便在Text更改时通知父DataGrid其大小。希望这能完成这项工作。
{{1}}