我試圖在DataGrid中爲動畫列添加動畫。這也很完美。但是,我總是需要希望有一列的最大寬度,以便從中計算與DataGrid寬度的比率。始終獲得dataGrid所需的最大列寬度/空間
這適用於第一次通話。但只要列一旦動畫,「DesiredValue」總是等於該列的值。
((DataGridTemplateColumn)column).Width.DesiredValue
有沒有人有解決方案或方法總是有一個或所有列的最大所需寬度?
謝謝
問候 多米尼克
我試圖在DataGrid中爲動畫列添加動畫。這也很完美。但是,我總是需要希望有一列的最大寬度,以便從中計算與DataGrid寬度的比率。始終獲得dataGrid所需的最大列寬度/空間
這適用於第一次通話。但只要列一旦動畫,「DesiredValue」總是等於該列的值。
((DataGridTemplateColumn)column).Width.DesiredValue
有沒有人有解決方案或方法總是有一個或所有列的最大所需寬度?
謝謝
問候 多米尼克
關鍵是要設置列到汽車的寬度,以獲得所需的空間(設置爲自動後,不要忘記更新您的佈局!)。我發現在.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 <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
}
}
這裏是我的解決方案的嘗試。這裏的問題是,如果該列不在視圖中,「單元變量」將始終爲空。
現在我將爲我的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);
}
這不是測試,但我認爲應該做你想要什麼?
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
也許這有助於一點點...
感謝您的回答。這已經使我朝着正確的方向發展。準備就緒後,我會立即發佈我的解決方案。 –