Bonjour,
j'aimerais, qu'importe l'interaction effectuée par l'utilisateur, pourvoir copier un DataGrid vers le presse papier, pour ensuite le réinjecter dans des rapports Word rapidement.
Cordialement, Orwel
Bonjour,
j'aimerais, qu'importe l'interaction effectuée par l'utilisateur, pourvoir copier un DataGrid vers le presse papier, pour ensuite le réinjecter dans des rapports Word rapidement.
Cordialement, Orwel
Bonjour,
Qu'est-ce que tu n'arrives pas à faire ?
Il faut procéder de la manière suivante :
- Soit utiliser le DataGrid existant soit créer un contrôle qui aura l'aspect de l'image que tu souhaites copier.
- À partir de cet UIElement, générer une image à l'aide de la méthode Render de la classe RenderTargetBitmap (cf msdn)
- Enfin, il faut copier le flux (Stream) de l'image obtenu dans le presse papier à l'aide des méthodes de la classe statique Clipboard
NeoKript
Merci beaucoup, ta réponse m'a permit d'avancer.
Mais j'ai encore un problème; lorsque le DataGrid a beacuoup d'élément, une Scroll Bar apparaît et seulement la partie visible du DataGrid est convertie en image, avec la Scroll Bar.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 public static void PushInClipboard(DataGrid dataGrid) { var img = new RenderTargetBitmap((int)dataGrid.RenderSize.Width, (int)dataGrid.RenderSize.Height, 96, 96, PixelFormats.Pbgra32); img.Render(dataGrid); Clipboard.SetImage(img); }
J'ai donc désactivée la Scroll Bar du DataGrid et demandais la réactualisation du DataGrid. La Scroll Bar n'apparaît plus sur l'image, mais le DataGrid apparaît toujours incomplet. Il est comme il apparaît à l'écran.
Je pense que je dois utiliser les méthodes DataGrid.MEasure et DataGrid.Arrange, mais je ne sais pas quelles paramètres y passer, cardataGrid.Width et dataGrid.Heigth = NAN.
Mon code actuelle non fonctionnel :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10 public static void PushInClipboard(DataGrid dataGrid) { dataGrid.HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled; dataGrid.UpdateLayout(); dataGrid.Measure(new Size(dataGrid.Width, dataGrid.Height)); dataGrid.Arrange(new Rect(new Size(dataGrid.Width, dataGrid.Height))); var img = new RenderTargetBitmap((int)dataGrid.RenderSize.Width, (int)dataGrid.RenderSize.Height, 96, 96, PixelFormats.Pbgra32); img.Render(dataGrid); Clipboard.SetImage(img); }
Pour la taille du contrôle, essayes d'utiliser les propriétés DesiredHeight et DesiredWidth, ça devrait fonctionner.
Effectivement, il s'agit de l'attribut qui connait la taille du DataGrid. Mais celui-ci est limité par la taille du composant parent.
Donc il faudrait le sortir du composant parent, le copier, et le remettre.
Ou effectuer une copie.
Voici un code de test
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12 <Window x:Class="PushDataGridInClipboard.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525"> <Grid> <DataGrid Name="DataGrid" AutoGenerateColumns="False" MouseDoubleClick="DataGrid_MouseDoubleClick"> <DataGrid.Columns> <DataGridTextColumn Binding="{Binding Value}"/> </DataGrid.Columns> </DataGrid> </Grid> </Window>Edit :: DesiredSize n'est pas la taille total du composant.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace PushDataGridInClipboard { /// <summary> /// Logique d'interaction pour MainWindow.xaml /// </summary> public partial class MainWindow : Window { class MyDouble { public double Value { get; set; } public MyDouble(double value) { Value = value; } } public MainWindow() { InitializeComponent(); var list = new List<MyDouble>(); for (int i = 0; i < 200; i++) list.Add(new MyDouble(i)); DataGrid.ItemsSource = list; } private void DataGrid_MouseDoubleClick(object sender, MouseButtonEventArgs e) { PushInClipboard((DataGrid)sender); } /// <summary> /// Copie le DataGrid en tant qu'image dans le presse papier. /// </summary> public static void PushInClipboard(DataGrid dataGrid) { dataGrid.VerticalScrollBarVisibility = ScrollBarVisibility.Disabled; dataGrid.UpdateLayout(); dataGrid.Measure(new Size(dataGrid.DesiredSize.Width, dataGrid.DesiredSize.Height)); dataGrid.Arrange(new Rect(new Size(dataGrid.DesiredSize.Width, dataGrid.DesiredSize.Height))); var img = new RenderTargetBitmap((int)dataGrid.DesiredSize.Width, (int)dataGrid.DesiredSize.Height, 96, 96, PixelFormats.Pbgra32); img.Render(dataGrid); Clipboard.SetImage(img); } } }
Instancies un nouveau DataGrid (par code) en ajoutant les mêmes propriétés ItemsSource, Columns ... Comme ça le contrôle ne sera pas lié à ton UI et tu pourras lui donner la taille qu'il désire...
Voici le code de la copie :
Plusieurs problèmes avec ta solution :var grid = new DataGrid();
var column = new DataGridTextColumn();
column.Binding = new Binding("Value");
grid.Columns.Add(column);
grid.ItemsSource = dataGrid.ItemsSource;
1) Je connais pas la taille qu'il désire. Si il n'est pas attaché à l'UI, alors tout les paramètre de taille sont à 0, or ni Heigth et Width qui sont encore un NAN.
J'ai essayé de forcer la taille du DataGrid en modifiant Heigth et Width, j’obtiens une image noir.
2)La copie me semble limité et difficile, car alors il faudrait une méthode de copie vers le presse papier par DataGrid.
Sauf si il existe une méthode pour copier certaine propriété du DataGrid.
En essayant :
J'ai la fameuse erreur qu'une colonne ne peut appartenir qu'a un unique DataGrid.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 var grid = new DataGrid(); foreach (var column in dataGrid.Columns) grid.Columns.Add(column); grid.ItemsSource = dataGrid.ItemsSource;
---------
Je pense qu'il serait préférable de sortir le DataGrid et l'ajouter à une fenêtre de taille infinie. Mais je ne sais pas comment faire pour récupérer le conteneur du DataGrid pour le retirer et donner une taille infinie à une fenêtre.
Sinon, je pense qu'il est illogique de chercher à faire des images aussi grande. Je vais voir si je peux modifier le besoin.
Merci beaucoup pour ton aide.
Voici une solution. Elle améliore légèrement l'affichage en modifiant certain attribut du DataGrid et les restaure à l'origine à la fin de son exécution. Seul la partie visible du DataGrid ira dans le presse papier.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 /// <summary> /// Copie le DataGrid en tant qu'image dans le presse papier. /// </summary> public static void PushInClipboard(DataGrid dataGrid) { //Savegarde les attributs modifiées du DataGrid var tmpRenderSize = dataGrid.RenderSize; var tmpHorizontal = dataGrid.HorizontalScrollBarVisibility; var tmpVertical = dataGrid.VerticalScrollBarVisibility; //Modifie les attributs pour un meilleur affichage dataGrid.HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled; dataGrid.VerticalScrollBarVisibility = ScrollBarVisibility.Disabled; dataGrid.Measure(new Size(dataGrid.DesiredSize.Width, dataGrid.DesiredSize.Height)); dataGrid.Arrange(new Rect(dataGrid.DesiredSize)); dataGrid.UpdateLayout(); //Sauvegarde l'affichage dans le presse papir var img = new RenderTargetBitmap((int)dataGrid.RenderSize.Width, (int)dataGrid.RenderSize.Height, 96, 96, PixelFormats.Pbgra32); img.Render(dataGrid); Clipboard.SetImage(img); //Restore les attributs d'origine dataGrid.HorizontalScrollBarVisibility = tmpHorizontal; dataGrid.VerticalScrollBarVisibility = tmpVertical; dataGrid.Measure(new Size(tmpRenderSize.Width, tmpRenderSize.Height)); dataGrid.Arrange(new Rect(tmpRenderSize)); dataGrid.UpdateLayout(); }
Ça doit être jouable de faire ça, avec la DesiredSize de l'ItemPresenter contenu dans le ScrollViewer du DataGrid.
Sinon une méthode plus simple (mais moins propre) consiste à récupérer la propriété RowHeight du DataGrid multipliée par le nombre d'item de l'ItemsSource + la taille du Header... Et de définir cette valeur en tant qu'hauteur souhaitée lors du rendu (dans un DataGrid copié).
Merci bien, mais je vais arrêter ici sur ce problème. D'autres priorités
Je ne sais pas si je devrais mettre résolue, car la question n'est pas entièrement résolue. Mais en redéfinissant les besoins des utilisateurs, soit copié le DataGrid vers un document Word au final. Si le DataGrid est trop grand, il ne logera pas dans le document. C'est donc l'utilisateur qui redimensionne le DataGrid pour obtenir l'affichage qu'il désire (les DataGris on la possibilité de masquer les colonnes et sont dans des zones dimensionnables
Point intéressant, plutôt que perdre du temps à réaliser une chose complexe, chercher à redéfinir le cahier de spec. vers une fonctionnalité moins complexe, mais qui reste ce que l’utilisateur attend
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager