Je voudrais définir une telle taille pour le DataGrid (standard, de WPF) afin que toutes les cellules (texte) soient entièrement visibles. J'ai une fenêtre avec DockPanel, avec DataGrid dedans, donc quand je redimensionne la fenêtre, tous les widgets imbriqués (DockPanel et DataGrid) sont redimensionnés en conséquence.
Exemple (edit-1)
Disons que vous avez une fenêtre de 100 pixels de large et que vous avez DataGrid avec une colonne, dont la cellule est "le renard brun rapide ..." (400 pixels de large). Ainsi, le DataGrid devrait être redimensionné à 400 pixels (probablement plus, à cause du rembourrage) et la fenêtre devrait être redimensionnée à 400 pixels aussi (également plus, à cause du remplissage).
Je n'ai trouvé aucune méthode standard pour le faire (AFAIK WPF fournit un moyen de couper le contenu à la largeur souhaitée, mon problème est exactement opposé), donc je trouve une solution de contournement aussi moche, qui ne fonctionne pas trop bien.
J'ai fait plusieurs tests, et dans certains cas, la largeur calculée est trop grande (c'est un problème mineur), dans certains cas, elle est trop petite. Le problème commence à sa procédure de base - calcul de la largeur requise pour TextBox/TextBlock, la largeur calculée est toujours inférieure de 1 unité à ce qu'elle devrait être (si je règle la largeur sur un calculé, 1 pixel du texte est toujours coupé).
Alors quel facteur j'ignore ici? Ou peut-être mieux - existe-t-il déjà une méthode pour redimensionner DataGrid pour l'adapter à son contenu?
Largeur de calcul requise pour le texte (ici pour TextBlock):
public static double TextWidth(this TextBlock widget, string text)
{
var formattedText = new FormattedText(text, // can use arbitrary text
System.Globalization.CultureInfo.CurrentCulture,
widget.FlowDirection,
widget.FontFamily.GetTypefaces().FirstOrDefault(),
widget.FontSize,
widget.Foreground);
return formattedText.Width+widget.Padding.Left+widget.Padding.Right;
}
Ajuster la taille de la fenêtre pour qu'elle s'adapte au contenu de DataGrid (ugly_factor est une solution de contournement laide ;-) puisque je n'ai pas compris comment le réparer correctement, je la mets à 1,3 et de cette façon, ma fenêtre n'est "jamais" trop petite):
public static void AdjustWidthToDataGrid(this Window window, DataGrid dataGrid, double ugly_factor)
{
var max_widths = dataGrid.Columns.Select(it => window.TextWidth(it.Header as string)
* ugly_factor).ToArray();
foreach (var row in Enumerable.Range(0, dataGrid.Items.Count))
foreach (var col in Enumerable.Range(0, dataGrid.Columns.Count))
{
var cell = dataGrid.GetCell(row, col);
double width = 0;
if (cell.Content is TextBlock)
width = (cell.Content as TextBlock).TextWidth();
else if (cell.Content is TextBox)
width = (cell.Content as TextBox).TextWidth();
if (cell.Content is FrameworkElement)
{
var widget = cell.Content as FrameworkElement;
width = width + widget.Margin.Left + widget.Margin.Right;
}
max_widths[col] = Math.Max(max_widths[col],
width*ugly_factor+cell.Padding.Left+cell.Padding.Right);
}
double width_diff = 0;
foreach (var col in Enumerable.Range(0, dataGrid.Columns.Count))
width_diff += Math.Max(0,max_widths[col] - dataGrid.Columns[col].ActualWidth);
if (width_diff > 0)
window.Width = window.ActualWidth+ width_diff;
}
Commentaire de Marko est la réponse:
Je suis un peu perdu avec votre logique de redimensionnement. Tout d'abord, si vous définissez le
SizeToContent="WidthAndHeight"
De la fenêtre, la fenêtre est affichée à la taille complète de la grille de données. D'un autre côté, si vous affichez une fenêtre à une taille prédéfinie et que vous souhaitez redimensionner la fenêtre une fois la fenêtre affichée, le redimensionnement à la grille de données souhaitée avec est alors très contre-intuitif. Parce que le redimensionnement passera de disons 100px à 400px, mais que se passe-t-il si je veux redimensionner à seulement 250px ... (en supposant que vous redimensionnez en faisant glisser le coin de la fenêtre)
Je viens de sortir du même problème où je devais donner des options dans la colonne d'une grille de données pour adapter sa largeur selon le contenu de l'en-tête et de la cellule. J'ai utilisé le code suivant:
private void FitToContent()
{
// where dg is my data grid's name...
foreach (DataGridColumn column in dg.Columns)
{
//if you want to size ur column as per the cell content
column.Width = new DataGridLength(1.0, DataGridLengthUnitType.SizeToCells);
//if you want to size ur column as per the column header
column.Width = new DataGridLength(1.0, DataGridLengthUnitType.SizeToHeader);
//if you want to size ur column as per both header and cell content
column.Width = new DataGridLength(1.0, DataGridLengthUnitType.Auto);
}
}
J'ai également fourni une option sur les colonnes pour s'adapter à l'affichage (largeur de la grille de données). pour cela, j'ai utilisé le même code ci-dessus avec la modification mineure suivante:
column.Width = new DataGridLength(1.0, DataGridLengthUnitType.Star);
POUR TOUTES LES COLONNES .... :) Assurez-vous de conserver HorizontalScrollVisibility sur Auto.
Si j'ai bien compris votre question et que vous souhaitez:
Ceci peut être réalisé avec la liaison de données:
<DataGrid AutoGenerateColumns="False"
EnableRowVirtualization="True"
Height="111"
HorizontalAlignment="Left"
ItemsSource="{Binding}"
Margin="72,203,0,0"
Name="dataGrid"
RowDetailsVisibilityMode="VisibleWhenSelected"
VerticalAlignment="Top"
Width="{Binding Path=ActualWidth, ElementName=grid}">
<DataGrid.Columns>
<DataGridTextColumn x:Name="Column1"
Binding="{Binding Path=Something1}"
Header="Column1"
Width="Auto" />
<DataGridTextColumn x:Name="Column2"
Binding="{Binding Path=Something2}"
Header="Column2"
Width="*" />
</DataGrid.Columns>
</DataGrid>
Ici, la première colonne est aussi large que nécessaire et la seconde est un espace étalé qui reste. Cependant, la largeur du DataGrid est la même que la largeur de la grille qui l'entoure, donc le résultat souhaité est atteint.
SizeToCells est ce qui a fonctionné pour moi. J'aime ça parce que c'est en XAML et c'est concis.
<DataGridTextColumn x:Name="nameColumn" Binding="{Binding Name}" Header="Name" Width="SizeToCells"/>
Dans mon cas, j'ai trouvé DataGrid utiliser HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
par défaut, je l'ai donc réglé sur
<DataGrid ItemsSource="{Binding Source}" Width="Auto" Height="Auto"
HorizontalAlignment="Center" VerticalAlignment="Center"/>
Fonctionne ensuite.