Example: Even-odd layout

Sometimes you will need a layout that is showing data differently depending on the page being a left or right page in a report E.g, a simple report like this where first page is showing controls to the left on the page and 2nd page is showing data to the right of the page.

image-20240429-132005.png

However, this is not supported default in DevExpress but can relatively easily be implemented using simple scripting as shown below.

 

The basic principle is to make controls for both even and odd layout - then use the scripts below to turn off controls if its either left or right hand side page. Note that left/right depends on which page you start on so you might have to adjust which script to call

A report design for the above example is shown below - note that is shows controls for both left and right page at the same time. Its easiest to make one side first and then copy and paste the control and arrange them as needed.

image-20240429-132131.png

The trick is to render both controls and then turn one of the side’s controls off. This can be done by setting the e.Cancel property to true - this way the control instance will be removed from the report.

However, paging is only known after every control has been laid out and page size has been taken into account (and grouping rules where data should be shown), so you will need to use the PrintOnPage event as controls wont know which page index its on until after PrintOnPage is done. The event will include the pageindex in the PrintOnPageEvent sent to the script method. Default the PageIndex is 0 based so first page is pageindex = 0 unless overridden.

Script to handle even-odd layout - this can be used “as-is” in many reports.

private void turnOffIfEvenPage (object sender, DevExpress.XtraReports.UI.PrintOnPageEventArgs e) { // Images needs to be handled specially - otherwise they will reset to last image used. if (""+sender.GetType() == "Pims.Api.Reporting.PerfionImage" ) ((Pims.Api.Reporting.PerfionImage)sender).ImageID = null; if( e.PageIndex %2 == 0){ e.Cancel =true; } } private void turnOffIfOddPage (object sender, DevExpress.XtraReports.UI.PrintOnPageEventArgs e) { // Images needs to be handled specially - otherwise they will reset to last image used. if (""+sender.GetType() == "Pims.Api.Reporting.PerfionImage" ) ((Pims.Api.Reporting.PerfionImage)sender).ImageID = null; if( e.PageIndex %2 == 1){ e.Cancel =true; } }


OBS: PerfionImage control has a quirk where it will repeat the last value it used , so the script will set it to null so then PrintOnPage event handler will not reset the image binding - and then setting e.Cancel = true if the control calling the script needs to be turned off.

When the script is copied to scripting you will need to Expand “Scripts” and assign the right method in PrintOnPage - below example uses turnOffIfOddPage to turn off control for the first (0 index) base.

 


A couple of notes on (advanced) scripting.

  • Scripting is something that requires a developer and if overdone it will be quickly become hard to maintain - and it can't be supported by Perfion as it by definition is a custom code implementation.

    • This means that even simple scripted reports most likely will not be maintainable by end users.

  • Scripted reports should be considered sourcecode - thus its a good idea to have it in sourcecontrol systems like e.,g GIT. Can argue this would be a good practice for normal reports also.

  • It can be “debugged” in 2 ways - neither is supported by Perfion but can be useful.

    • SIMPLE
      Using simple output to System.Windows.Forms.MessageBox.Show - note that you will often end up showing a MessageBox for every time a control is rendered which can be a LOT of times for a report

    • ADVANCED (developer only and requires something like Visual studio)
      Script is runtime compiled C# - this means you can compile script code as a library and upload it to reports.

      Here you can supply the path to the compiled DLL.

      You will still need to have the method in the report for designer to be able to pick it up but instead of using script code you can just call your method in the DLL.
      so the script method

      private void turnOffIfEvenPage (object sender, DevExpress.XtraReports.UI.PrintOnPageEventArgs e) { // Images needs to be handled specially - otherwise they will reset to last image used. if (""+sender.GetType() == "Pims.Api.Reporting.PerfionImage" ) ((Pims.Api.Reporting.PerfionImage)sender).ImageID = null; if( e.PageIndex %2 == 0){ e.Cancel =true; } }

      becomes something like this

      private void turnOffIfEvenPage (object sender, DevExpress.XtraReports.UI.PrintOnPageEventArgs e) { if (MyNameSpace.ShouldITurnOffEvenPage(sender, e) ) [ e.Cancel = true; } }

      The very cool thing here is that you attach a debugger to Perfion.exe and use breakpoints in your DLL project and you can inspect data structures (e.g., to see page index) . Note that any change to the code in a library / DLL project will require the report to be reloaded as it will only load the DLL on startup and then breakpoints will note fire as its not the same code..