Dans mon fichier App.xaml
, j'ai le code suivant pour autoriser les en-têtes de colonnes "à deux étages" dans DataGrid
s.WPF - DataGrid - Logique de redimensionnement automatique des colonnes
XAML:
<adv:ColumnHeaderFontSizeToMaxHeightConverter x:Key="columnHeaderFontSizeToMaxHeightConverter" />
<DataTemplate x:Key="WrappingDataGridColumnHeaderTemplate" DataType="{x:Type sys:String}">
<TextBlock TextWrapping="WrapWithOverflow"
Text="{Binding}"
ToolTip="{Binding}"
MaxHeight="{Binding Path=FontSize, Mode=OneWay,
RelativeSource={RelativeSource Self},
Converter={StaticResource columnHeaderFontSizeToMaxHeightConverter} }" />
</DataTemplate>
Converter:
internal class ColumnHeaderFontSizeToMaxHeightConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter,
CultureInfo culture)
{
Debug.Assert(value.GetType() == typeof(double));
// We want to have up to 2 lines of text here plus a little bit of space for margins, etc
// WPF will automatically use the smallest height required
return (double)value * 2.9;
}
public object ConvertBack(object value, Type targetType, object parameter,
CultureInfo culture)
{
Debug.Assert(false);
throw new NotImplementedException();
}
}
Cependant, le redimensionnement automatique des colonnes que la classe DataGrid
fournit en double-cliquant sur les séparateurs de colonnes ne prend pas en compte le fait que les en-têtes peuvent devenez encore plus petit avec l'emballage de mots.
Par exemple, supposons que vous avez une colonne avec une longue-tête et courtes valeurs comme ceci:
| Long Header |
-------------------
| A |
| B |
| C |
Un double-clic sur le séparateur se traduira par ceci:
| Long Header |
---------------
| A |
| B |
| C |
Mais ce qui serait encore mieux est si elle se traduirait par ceci:
| Long |
| Header |
----------
| A |
| B |
| C |
Ma question est la suivante:
Existe-t-il un moyen de fournir un "indice" au redimensionnement automatique pour lui faire savoir qu'il peut aller encore plus petit? Ou devrais-je complètement réimplémenter la logique de redimensionnement automatique sur double clic?
EDIT: Avec l'aide de Malaek, j'ai mis à jour mon code comme suit, mais un problème persiste. Il ne joue pas bien avec mon MaxHeight et 3 mots ou plus. Le premier double clic a une partie cachée de l'en-tête, mais il réapparaît au second double clic même si la colonne ne change pas de largeur. Je posterai le code que j'ai utilisé sous peu. Code
<DataGrid.Resources>
...
<Style TargetType="{x:Type DataGridColumnHeader}"
BasedOn="{StaticResource {x:Type DataGridColumnHeader}}">
<Setter Property="ContentTemplate" Value="{StaticResource WrappingDataGridColumnHeaderTemplate}" />
<EventSetter Event="SizeChanged" Handler="DataGridColumnHeader_SizeChanged"/>
<EventSetter Event="Loaded" Handler="DataGridColumnHeader_Loaded" />
</Style>
...
</DataGrid.Resources>
DataGrid derrière::
DataGrid XAML
private void RightThumb_PreviewMouseDoubleClick(object sender, MouseButtonEventArgs e)
{
Thumb thumb = sender as Thumb;
DataGridColumnHeader dataGridColumnHeader = VisualTreeHelpers.GetVisualParent<DataGridColumnHeader>(thumb);
DataGridColumn column = dataGridColumnHeader.Column;
UpdateColumnForResize(column);
}
private void LeftThumb_PreviewMouseDoubleClick(object sender, MouseButtonEventArgs e)
{
Thumb thumb = sender as Thumb;
DataGridColumnHeader dataGridColumnHeader = VisualTreeHelpers.GetVisualParent<DataGridColumnHeader>(thumb);
DataGridColumn column = this.Columns.FirstOrDefault(
c => c.DisplayIndex == dataGridColumnHeader.Column.DisplayIndex - 1);
UpdateColumnForResize(column);
}
private void UpdateColumnForResize(DataGridColumn column)
{
if (column != null)
{
column.Width = column.Width.DisplayValue;
string header = (string)column.Header;
if (header.Contains("\r\n"))
return;
int middle = header.Length/2;
int closestToMiddle = -1;
for (int i = 0; i < header.Length; ++i)
{
if (header[i] == ' ')
{
if (closestToMiddle == -1)
closestToMiddle = i;
else if (Math.Abs(i - middle) < Math.Abs(closestToMiddle - middle))
closestToMiddle = i;
}
}
if (closestToMiddle != -1)
{
StringBuilder newHeader = new StringBuilder(header);
newHeader.Replace(" ", "\r\n", closestToMiddle, 1);
column.Header = newHeader.ToString();
}
}
}
private void DataGridColumnHeader_SizeChanged(object sender, SizeChangedEventArgs e)
{
DataGridColumnHeader columnHeader = sender as DataGridColumnHeader;
DataGridColumn column = columnHeader.Column;
if (column != null && column.Header.ToString().IndexOf("\r\n") >= 0)
{
column.Header = column.Header.ToString().Replace("\r\n", " ");
column.Width = column.Width.DisplayValue;
}
}
private void DataGridColumnHeader_Loaded(object sender, EventArgs e)
{
DataGridColumnHeader columnHeader = sender as DataGridColumnHeader;
Thumb thumb = columnHeader.Template.FindName("PART_RightHeaderGripper", columnHeader) as Thumb;
if (thumb != null)
thumb.PreviewMouseDoubleClick += RightThumb_PreviewMouseDoubleClick;
thumb = columnHeader.Template.FindName("PART_LeftHeaderGripper", columnHeader) as Thumb;
if (thumb != null)
thumb.PreviewMouseDoubleClick += LeftThumb_PreviewMouseDoubleClick;
}
EDIT2: Apparemment, le problème est un peu plus subtile. L'en-tête "Dernière mise à jour sur" le déclenche, mais "Dernière mise à jour par" ne le déclenche pas. Je suis toujours en train d'enquêter.
Je ne sais pas où vous avez trouvé la méthode VisualTreeHelpers.GetVisualParent() à partir, mais je suppose que c'est quelque chose comme celui qui est décrit ici? http://stackoverflow.com/questions/4059626/how-do-i-change-wpf-menus-icon-column-size/4063239#4063239 –
Ashley
@Ashley: Ah, désolé! J'ai oublié d'ajouter celui-là, venant tout droit –
Hrm, eh bien, il semble que de travailler seulement une partie du temps. Il semble que parfois, lorsque vous double-cliquez sur le «Thumb», il est en fait parfois le «pouce» gauche de la colonne sur le côté droit de la colonne que vous essayez de redimensionner. Il semble qu'il devrait y avoir un événement différent pour 'PART_LeftHeaderGripper' qui saisit la colonne à gauche, puis fait les espaces pour la conversion sur ce point. Je travaille sur un correctif maintenant. – Ashley