DevExpress Report
Apparence
Liens utiles
- How to: Customize Dock Panels of the End-User Designer
- How to: Create a Table Report
- Calculated Fields
- Providing Data to Reports
- How to: Customize Dock Panels of the End-User Designer
- Sum
Généré un PDF depuis un template (*.repx)
XtraReport reportDevExpress = XtraReport.FromFile(@"C:\Template.repx", true);
// it has to be an ArrayList, otherwise the report is not well filled
reportDevExpress.DataSource = new ArrayList(MyDataList);
reportDevExpress.ExportToPdf(@"C:\File.pdf");
|
![]() |
XtraReport Class
|
PDF/A
// PDF/A-2b
PdfExportOptions options = new PdfExportOptions()
{
PdfACompatible = true
};
reportDevExpress.ExportToPdf(@"C:\File.pdf", options);
// PDF/A-3b
string additionalMetadata =
File.ReadAllText("DocumentInfo.txt") +
File.ReadAllText("PdfASchema.txt");
PdfExportOptions options = new PdfExportOptions()
{
PdfACompatible = true,
AdditionalMetadata = additionalMetadata,
};
reportDevExpress.ExportToPdf(@"C:\File.pdf", options);
|
PDF/A-3b | v 14.2.6 |
PDF/A-2b | v 14.1.3 |
![]() |
PdfExportOptions Class
|
Designer WinForm dans une fenêtre WPF
<Window xmlns:userDesigner="clr-namespace:DevExpress.XtraReports.UserDesigner;assembly=DevExpress.XtraReports.v13.2.Extensions"
xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms">
<Grid>
<WindowsFormsHost>
<WindowsFormsHost.Child>
<wf:UserControl x:Name="ucDockingWindows">
<wf:UserControl.Controls>
<userDesigner:XRDesignPanel x:Name="panel" Dock="Fill" />
</wf:UserControl.Controls>
</wf:UserControl>
</WindowsFormsHost.Child>
</WindowsFormsHost>
</Grid>
</Window>
|
public MainWindow()
{
InitializeComponent();
var dockManager = new XRDesignDockManager();
dockManager.Form = ucDockingWindows;
dockManager.Initialize(panel, DesignDockPanelType.All);
var barManager = new XRDesignBarManager();
barManager.Form = ucDockingWindows;
barManager.Initialize(panel);
barManager.DockManager = dockManager;
// Remove tool bar stuff
panel.SetCommandVisibility(ReportCommand.AddNewDataSource, CommandVisibility.None);
// Close GroupAndSort DesignDockPanel
var designDockPanel = (GroupAndSortDockPanel)dockManager[DesignDockPanelType.GroupAndSort];
designDockPanel.Close();
// get a specific DesignDockPanel from its name
var designDockPanel = dockManager.Panels.OfType<TypedDesignDockPanel>().FirstOrDefault(p => p.GetType().Name.StartsWith(DesignDockPanelType.GroupAndSort.ToString()));
// set report datasource
report.DataSource = dataSource;
|
Afficher une preview
var report = XtraReport.FromFile(@"Chemin\vers\le\fichier.repx", true);
using (ReportPrintTool printTool = new ReportPrintTool(report))
{
printTool.ShowPreviewDialog();
}
|
Éditer avec le designer classique
var report = XtraReport.FromFile(@"Chemin\vers\le\fichier.repx", true);
using (ReportPrintTool printTool = new ReportPrintTool(report))
{
printTool.ShowDesignerDialog();
}
|
Masquer des boutons dans le ruban
reportDesigner1.SetCommandVisibility(ReportCommand.SaveAll, CommandVisibility.None); |
Rafraichir le nom du rapport dans un onglet
XRDesignMdiController _controller;
var host = (IDesignerHost)_controller.ActiveDesignPanel.GetService(typeof(IDesignerHost));
var changeSrv = (IComponentChangeService)host.GetService(typeof(IComponentChangeService));
changeSrv.OnComponentChanging(_controller.ActiveDesignPanel.Report, null);
_controller.ActiveDesignPanel.Report.DisplayName = "Nouveau nom de rapport";
changeSrv.OnComponentChanged(_controller.ActiveDesignPanel.Report, null, null, null);
|
- BarButtonItem.ActAsDropDown Property
- BarButtonItem.DropDownControl Property
- DevExpress.XtraReports.UserDesigner Namespace
Override Commands in the End-User Designer (Custom Saving)
New
public ReportsDesigner()
{
reportDesigner1.AddCommandHandler(new MainCommandHandler(reportDesigner1);
/* ** */
public class MainCommandHandler : ICommandHandler
{
private XRDesignMdiController _controller;
public bool CanHandleCommand(ReportCommand command, ref bool useNextHandler)
{
useNextHandler = command != ReportCommand.NewReport;
return !useNextHandler;
}
public void HandleCommand(ReportCommand command, object[] args)
{
_controller.CreateNewReport();
_controller.ActiveDesignPanel.Report.DataSource = ...;
// Update the Field List
var host = (IDesignerHost)_controller.ActiveDesignPanel.GetService(typeof(IDesignerHost));
_fieldList.UpdateDataSource(host);
// Change the DisplayName
var changeSrv = (IComponentChangeService)host.GetService(typeof(IComponentChangeService));
changeSrv.OnComponentChanging(_controller.ActiveDesignPanel.Report, null);
_controller.ActiveDesignPanel.Report.DisplayName = ...;
changeSrv.OnComponentChanged(_controller.ActiveDesignPanel.Report, null, null, null);
// Change the FileName
_controller.ActiveDesignPanel.FileName = ...;
// display a star at the right of the name in the tab to inform that the file is not saved yet
_controller.ActiveDesignPanel.ReportState = ReportState.Changed;
|
Save
private void reportDesigner1_DesignPanelLoaded(object sender, DesignerLoadedEventArgs e)
{
XRDesignPanel panel = (XRDesignPanel)sender;
reportDesigner1.AddCommandHandler(new SaveCommandHandler(reportDesigner1, panel));
/* ** */
public class SaveCommandHandler : ICommandHandler
{
private XRDesignMdiController _controller;
private XRDesignPanel _panel;
public bool CanHandleCommand(ReportCommand command, ref bool useNextHandler)
{
// ici on choisit les commandes qui seront gérées
useNextHandler = command != ReportCommand.SaveFile &&
command != ReportCommand.SaveFileAs &&
command != ReportCommand.Closing;
return !useNextHandler;
}
public void HandleCommand(ReportCommand command, object[] args)
{
switch (command)
{
case ReportCommand.SaveFile:
HandleSave();
break;
case ReportCommand.SaveFileAs:
HandleSaveAs();
break;
case ReportCommand.Closing:
HandleClosing(args);
break;
default:
break;
}
}
private void HandleSave()
{
if (File.Exists(_panel.FileName))
{
// Save template
_panel.Report.SaveLayout(_panel.FileName, true);
// Prevent the "Report has been changed" dialog from being shown.
_panel.ReportState = ReportState.Saved;
}
else
{
HandleSaveAs();
}
}
private void HandleClosing(object[] args)
{
if (_panel.ReportState == ReportState.Changed)
{
if (args.Length == 2)
{
var panelForm = args[0] as XRDesignPanelForm;
var cancelEventArgs = args[1] as CancelEventArgs;
if (panelForm != null && cancelEventArgs != null)
{
// Select the report in the tabs
_panel.Select();
MessageBoxResult messageBoxResult = MessageBox.Show(
String.Format("The template '{0}' has changed. Do you want to save it?",
panelForm.ReportDisplayName),
"Template has changed",
MessageBoxButton.YesNoCancel);
if (messageBoxResult == MessageBoxResult.Cancel)
{
cancelEventArgs.Cancel = true;
}
}
}
}
}
}
|
Field List
Provide Custom Names for Data Items in the Field List
DataSource: Wrapper dynamique
Pour chaque élément de DataList, on créé un wrapper: pour chaque propriété marquée de l'attribut [Field("Nom affiché", "Groupe")]
- on créé un groupe s'il n'existe pas déjà
- où on y ajoute une propriété "Nom affiché"
- avec la valeur de la propriété.
XtraReport reportDevExpress = XtraReport.FromFile(templateFilePath, true);
reportDevExpress.DataSource = GetDataSource();
public object GetDataSource()
{
var wrapperArrayList = new DataWrapperArrayList("Nom de la Field List");
// wrap chaque élément de DataList
foreach (var wrapper in DataList.Select(r => DataWrapperForDesigner<FieldAttribute>.BuildDynamicWrapper(r, true)))
{
wrapperArrayList.Add(wrapper);
}
return wrapperArrayList;
}
// pour le Designer on n'a besoin juste d'un élément (data) et pas de la liste de tous les éléments (DataList)
// on a besoin de la structure de l'élément (liste des propriétés mais pas des valeurs)
public object GetDataSourceSkeleton()
{
var dynamicWrapper = DataWrapperForDesigner<FieldAttribute>.BuildDynamicWrapper(data, false);
var dynamicWrapperArrayList = new DataWrapperArrayList("Nom de la Field List") { dynamicWrapper };
dynamicWrapperArrayList.DisplayNames = DataWrapperForDesigner<FieldAttribute>.DisplayNames;
return dynamicWrapperArrayList;
}
|
public class DataWrapperArrayList : ArrayList, IDisplayNameProvider
{
private string _dataSourceDisplayName;
public DataWrapperArrayList(string dataSourceDisplayName)
{
_dataSourceDisplayName = dataSourceDisplayName;
}
public string GetDataSourceDisplayName()
{
return _dataSourceDisplayName;
}
public string GetFieldDisplayName(string[] fieldAccessors)
{
var fieldName = fieldAccessors[fieldAccessors.Length - 1];
if (DisplayNames != null && DisplayNames.ContainsKey(fieldName))
{
return DisplayNames[fieldName];
}
else
{
// Inserts spaces in the field names.
return SpaceFieldNames(fieldName);
}
}
private string SpaceFieldNames(string fieldName)
{
string result = string.Empty;
bool isPrevLow = false;
foreach (char symb in fieldName)
{
// Check if a character is of upper case.
// To avoid spaces inside abbreviations,
// check if the previous character is of upper case, too.
if (Char.IsUpper(symb) && isPrevLow)
{
result += " " + symb;
}
else
{
result += symb;
}
isPrevLow = Char.IsLower(symb);
}
return result;
}
public IDictionary<string, string> DisplayNames { get; set; }
}
|
public class DataWrapperForDesigner<A>
where A : Attribute, IFieldAttribute
{
/// <summary>
/// Store the dynamic wrapper type after it has been build the first time.
/// This to avoid creating a different type each type.
/// </summary>
private static IDictionary<Type, Type> _dynamicWrapperTypes;
/// <summary>
/// Builds the type of the dynamic wrapper or get the previously built type.
/// </summary>
/// <returns></returns>
private static Type BuildDynamicWrapperType(Type reportType)
{
// create once the dynamicWrapperType for a report type
if (!_dynamicWrapperTypes.ContainsKey(reportType))
{
ModuleBuilder moduleBuilder;
TypeBuilder typeBuilder = CreateTypeBuilder("DynamicWrapper", "DynamicWrapper.dll", "DynamicWrapper", out moduleBuilder);
var propertiesGroups = new Dictionary<string, List<PropertyInfo>>();
// for each properties with the attribute Field
foreach (var propertyInfo in reportType.GetProperties(BindingFlags.Instance | BindingFlags.Public).Where(p => Attribute.IsDefined(p, typeof(A))))
{
var fieldAttribute = (A)Attribute.GetCustomAttribute(propertyInfo, typeof(A), false);
if (!propertiesGroups.ContainsKey(fieldAttribute.Group))
{
propertiesGroups[fieldAttribute.Group] = new List<PropertyInfo>();
}
propertiesGroups[fieldAttribute.Group].Add(propertyInfo);
DisplayNames[propertyInfo.Name] = fieldAttribute.DisplayName;
}
// for each group create a dynamic class
foreach (var group in propertiesGroups.Keys)
{
TypeBuilder groupTypeBuilder = CreateTypeBuilder(group, moduleBuilder);
foreach (var propertyInfo in propertiesGroups[group])
{
AddProperty(groupTypeBuilder, propertyInfo.Name, propertyInfo.PropertyType);
}
Type groupType = groupTypeBuilder.CreateType();
// add the new type as property into the DynamicWrapper
AddProperty(typeBuilder, group, groupType);
}
_dynamicWrapperTypes[reportType] = typeBuilder.CreateType();
}
return _dynamicWrapperTypes[reportType];
}
/// <summary>
/// A dictionary which keys are property names and values names to display in the DevExpress designer.
/// </summary>
public static IDictionary<string, string> DisplayNames { get; private set; }
static DataWrapperForDesigner()
{
_dynamicWrapperTypes = new Dictionary<Type, Type>();
DisplayNames = new Dictionary<string, string>();
}
/// <summary>
/// Create the dynamic wrapper object and fill it if needed.
/// </summary>
public static object BuildDynamicWrapper(object data, bool fillTheWrapperWithData)
{
var dynamicWrapperType = BuildDynamicWrapperType(data.GetType());
var dynamicWrapper = Activator.CreateInstance(dynamicWrapperType);
if (fillTheWrapperWithTheReportData)
{
var propertiesGroups = new Dictionary<string, List<PropertyNameAndValue>>();
// for each properties of data with the attribute Field
foreach (var propertyInfo in report.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public).Where(p => Attribute.IsDefined(p, typeof(A))))
{
var fieldAttribute = (A)Attribute.GetCustomAttribute(propertyInfo, typeof(A), false);
if (!propertiesGroups.ContainsKey(fieldAttribute.Group))
{
propertiesGroups[fieldAttribute.Group] = new List<PropertyNameAndValue>();
}
propertiesGroups[fieldAttribute.Group].Add(new PropertyNameAndValue() { PropertyName = propertyInfo.Name, PropertyValue = propertyInfo.GetValue(report, null) });
}
foreach (var group in propertiesGroups.Keys)
{
var groupProperty = dynamicWrapperType.GetProperty(group);
var groupInstance = Activator.CreateInstance(groupProperty.PropertyType);
foreach (PropertyNameAndValue propertyNameAndValue in propertiesGroups[group])
{
if (propertyNameAndValue.PropertyValue != null)
{
var wrapperProperty = groupProperty.PropertyType.GetProperty(propertyNameAndValue.PropertyName);
if (wrapperProperty != null)
{
wrapperProperty.SetValue(groupInstance, propertyNameAndValue.PropertyValue, null);
}
else
{
log.ErrorFormat("Unable to retrieve the property {0} in the class {1}.", propertyNameAndValue.PropertyName, report.GetType().Name);
}
}
}
groupProperty.SetValue(dynamicWrapper, groupInstance, null);
}
}
return dynamicWrapper;
}
/// <summary>
/// Creates an assembly, a module and a type builder.
/// </summary>
/// <param name="assemblyName">Name of the assembly.</param>
/// <param name="moduleName">Name of the module.</param>
/// <param name="typeName">Name of the type.</param>
/// <param name="moduleBuilder">The module builder.</param>
/// <returns></returns>
private static TypeBuilder CreateTypeBuilder(string assemblyName, string moduleName, string typeName, out ModuleBuilder moduleBuilder)
{
var assemblyNameObject = new AssemblyName() { Name = assemblyName };
AssemblyBuilder assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(assemblyNameObject, AssemblyBuilderAccess.Run);
moduleBuilder = assemblyBuilder.DefineDynamicModule(moduleName);
return moduleBuilder.DefineType(typeName, TypeAttributes.Public | TypeAttributes.Class);
}
/// <summary>
/// Creates a type builder from a module.
/// </summary>
/// <param name="typeName">Name of the type.</param>
/// <param name="moduleBuilder">The module builder.</param>
/// <returns></returns>
private static TypeBuilder CreateTypeBuilder(string typeName, ModuleBuilder moduleBuilder)
{
return moduleBuilder.DefineType(typeName, TypeAttributes.Public | TypeAttributes.Class);
}
/// <summary>
/// Adds the property to the class.
/// </summary>
/// <param name="typeBuilder">The type builder.</param>
/// <param name="propertyName">Name of the property.</param>
/// <param name="propertyType">Type of the property.</param>
private static void AddProperty(TypeBuilder typeBuilder, string propertyName, Type propertyType)
{
FieldBuilder fieldBuilder = typeBuilder.DefineField("_" + propertyName, propertyType, FieldAttributes.Private);
PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(propertyName, PropertyAttributes.HasDefault, propertyType, null);
MethodBuilder getPropMthdBldr = typeBuilder.DefineMethod("get_" + propertyName, MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, propertyType, Type.EmptyTypes);
ILGenerator getIl = getPropMthdBldr.GetILGenerator();
getIl.Emit(OpCodes.Ldarg_0);
getIl.Emit(OpCodes.Ldfld, fieldBuilder);
getIl.Emit(OpCodes.Ret);
MethodBuilder setPropMthdBldr = typeBuilder.DefineMethod("set_" + propertyName, MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, null, new[] { propertyType });
ILGenerator setIl = setPropMthdBldr.GetILGenerator();
Label modifyProperty = setIl.DefineLabel();
Label exitSet = setIl.DefineLabel();
setIl.MarkLabel(modifyProperty);
setIl.Emit(OpCodes.Ldarg_0);
setIl.Emit(OpCodes.Ldarg_1);
setIl.Emit(OpCodes.Stfld, fieldBuilder);
setIl.Emit(OpCodes.Nop);
setIl.MarkLabel(exitSet);
setIl.Emit(OpCodes.Ret);
propertyBuilder.SetGetMethod(getPropMthdBldr);
propertyBuilder.SetSetMethod(setPropMthdBldr);
}
}
/// <summary>
/// A class used to store the property name with its value.
/// </summary>
class PropertyNameAndValue
{
public string PropertyName { get; set; }
public object PropertyValue { get; set; }
}
public interface IFieldAttribute
{
string DisplayName { get; }
string Group { get; }
}
|