web-dev-qa-db-fra.com

Quelle est la meilleure approche pour imprimer / créer des rapports à partir de WPF?

J'ai un projet à venir qui devra pouvoir imprimer des rapports simples à partir de ses données. Ce sera basé sur WPF, et je me demande dans quelle direction aller.

Je sais que WPF présente sa propre technologie d'impression (basée sur XPS) qui semble assez facile à utiliser. Cependant, une partie de moi se demande s'il serait simplement plus facile d'utiliser le contrôle ReportViewer et de l'intégrer dans un contrôle hôte Windows Forms, car cela donnera aux utilisateurs la possibilité d'exporter vers une variété de formats ainsi que d'imprimer.

Quelqu'un a-t-il une expérience de l'impression/des rapports à partir de WPF? Quelle direction recommanderiez-vous?

70
Matt Hamilton

Nous avons eu ce même problème et nous avons fini par utiliser RDLC/ReportViewer pour l'instant. Il n'y a pas d'outil de rapport WPF natif (à ma connaissance) et RDLC est assez simple à utiliser et gratuit. La surcharge d'exécution pour celui-ci est petite (environ 2 Mo) mais vous devez vous rappeler de la distribuer car elle ne fait pas partie du .NET Framework.

25
Bob King

Limitations de RDL

À l'origine, je suis allé avec RDLC/ReportViewer pour imprimer avec WPF mais je l'ai trouvé très limitant. Certaines des limitations que j'ai trouvées étaient:

  • RDL ne pouvait que créer le plus ennuyeux des rapports
  • La création d'un rapport à l'aide de RDL nécessitait beaucoup plus de travail que dans WPF simple: les outils de conception sont très primitifs par rapport aux accords Expression Blend et RDL uniquement dans les tableaux
  • Je n'avais pas la possibilité d'utiliser des modèles de contrôle, des modèles de données, des styles, etc.
  • Mes champs et colonnes de rapport n'ont pas pu être redimensionnés et réorganisés efficacement en fonction de la taille des données
  • Les graphiques devaient être importés sous forme d'images - ils ne pouvaient pas être dessinés ou modifiés en tant que vecteurs
  • Positionnement des éléments requis code-behind plutôt que liaison de données
  • Manque de transformations
  • Liaison de données très primitive

L'impression directement à partir de WPF est très facile

En raison de ces limitations, j'ai cherché à créer des rapports à l'aide de WPF pur et j'ai découvert que c'était vraiment assez trivial. WPF vous permet d'implémenter votre propre sous-classe DocumentPaginator qui peut générer des pages.

J'ai développé une sous-classe DocumentPaginator simple qui prend n'importe quel visuel, analyse l'arborescence visuelle et masque les éléments sélectionnés pour créer chaque page.

Détails DocumentPaginator

Voici ce que fait ma sous-classe DocumentPaginator lors de l'initialisation (appelée lorsque le premier PageCount est récupéré, ou lors du premier appel GetPage ()):

  1. Analyse l'arborescence visuelle et crée une carte de tous les panneaux déroulants dans ItemsControls
  2. En commençant par le plus externe, rend les éléments dans les ItemsControls invisibles du premier au premier jusqu'à ce que le visuel tienne sur une seule page sans avoir à faire défiler. Si l'extérieur ne peut pas être suffisamment réduit, réduit les panneaux intérieurs jusqu'à ce qu'il réussisse ou qu'il n'y ait qu'un seul élément à chaque niveau. Enregistrez l'ensemble des éléments visibles comme première page.
  3. Masquez les éléments de niveau inférieur qui ont déjà été affichés sur la première page, puis rendez les éléments suivants visibles jusqu'à ce qu'ils ne tiennent plus sur la page. Enregistrez tout sauf le dernier élément ajouté comme deuxième page.
  4. Répétez le processus pour toutes les pages, en stockant les résultats dans une structure de données.

La méthode GetPage de mon DocumentPaginator est la suivante:

  1. Rechercher le numéro de page donné dans la structure de données générée lors de l'initialisation
  2. Masquer et afficher les éléments dans l'arborescence visuelle comme indiqué dans la structure de données
  3. Définir les propriétés jointes PageNumber et NumberOfPages pour que le rapport puisse afficher la numérotation des pages
  4. Videz le répartiteur (Dispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, new Action(() => {} ));) pour terminer les tâches de rendu en arrière-plan
  5. Créer un rectangle de la taille de la page dont VisualBrush est le visuel en cours d'impression
  6. Mesurer, organiser et mettre à jour Disposition du rectangle, puis retournez-le

Cela s'est avéré être un code assez simple et m'a permis de transformer pratiquement tout ce que je pouvais créer avec WPF en pages et de l'imprimer.

Prise en charge supplémentaire des rapports

Maintenant que mon paginateur fonctionne, je n'ai plus à me soucier de savoir si je crée mon contenu WPF pour écran ou papier. En fait, souvent l'interface utilisateur que je crée pour la saisie et l'édition de données fonctionne également très bien pour l'impression.

À partir de là, j'ai ajouté une barre d'outils simple et du code derrière, ce qui a donné lieu à un système de rapports complet construit autour de WPF qui était beaucoup plus capable que RDL. Mon code de rapport peut exporter vers des fichiers, imprimer sur l'imprimante, couper/coller des images de page et couper/coller des données pour Excel. Je peux également basculer n'importe laquelle de mes interfaces utilisateur en "vue d'impression" en cliquant sur une case à cocher pour voir à quoi elle ressemblera si elle est imprimée. Tout cela en quelques centaines de lignes de C # et XAML!

À ce stade, je pense que la seule fonctionnalité de RDL que mon code de rapport ne possède pas est la possibilité de générer une feuille de calcul Excel formatée. Je peux voir comment cela pourrait être fait, mais jusqu'à présent, cela n'a pas été nécessaire - couper et coller les données à elles seules a suffi.

D'après mon expérience, ma recommandation serait d'écrire un paginateur, puis de commencer à utiliser WPF lui-même pour créer vos rapports.

42
Ray Burns
8
Lukas Cenovsky

Et Scryber? Il permet PDF modèles de rapport à définir en utilisant xml et liés aux données dans votre application au moment de l'exécution. http://scryber.codeplex.com/

3
LiamV

Jetez un oeil à PdfReports . Il s'agit d'un premier moteur de génération de rapports de code, qui s'appuie sur les bibliothèques iTextSharp et EPPlus. Il est compatible avec les applications Web et Windows .NET 3.5+.

3
VahidN

Pour développer la réponse de Ray Burns, si vous recherchez un exemple d'implémentation, voir: Paginateur de document de grille de données personnalisé

Ce qui est un excellent point de départ.

2
Alex Hope O'Connor

J'ai récemment accompli la tâche de développer son propre système de rapport, qui consiste essentiellement en un environnement de conception et un gestionnaire de source de données. La première tâche a été de développer un environnement de conception de type WYSWIG. J'ai fait cela en utilisant GDI +, sans même se soucier de l'impression, car il est apparu que l'impression/la génération de l'aperçu avant impression était plus facile que ce à quoi je m'attendais.En général, il suffit de dessiner toutes les choses à l'écran sur l'objet graphique de l'événement d'impression.

Je pense que dans le cas de WPF, ce serait similaire, donc tout ce dont vous devez vous soucier est d'afficher votre rapport à l'écran et l'impression ne serait que de quelques lignes de code.

1
MoreThanChaos

Sans entrer dans une discussion politique entière sur l'avenir de WPF, la meilleure option que nous avons trouvée était d'envelopper ReportViewer dans un contrôle hôte Windows Forms.

http://blog.pineywoodstech.com/index.php/2012/01/using-Microsoft-reportviewer-with-wpf/

0
Doug