How to make a report viewer on Avalonia and FastReport Open Source. Part 2


How to make a report viewer on Avalonia and FastReport Open Source. Part 2
In the first part of the article, we began developing a report viewer. We created a toolbar and implemented the report loading and display.
To be displayed, the report must be in fpx format. Then, we export it to png format and display it in an Image object. Forms in Avalonia are encoded using XAML. It would be logical to display the report in the same format, but FastReport Open Source does not support export to XAML. Therefore, we will use the available export in image format.

So, we have already implemented the main function of the application - the display of the selected report. But often a report consists of many pages, so the next function that we need to implement is navigation through report pages. That is, you need to implement controls that allow us to move between the pages of the report. To do this, we already have 4 buttons and a text field in the toolbar:
  • Button: go to the first page;
  • Button: go back to the page;
  • Button: go to the next page;
  • Button: go to the last page;
  • Text field: page number.

It remains to implement handlers for them. But at first we create one property:
  private int currentPage = 0;
 public int CurrentPage
        {
            get { return currentPage; }
            set
            {
                if (value >= 0 && value < pages.Count)
                    currentPage = value;
            }
        }
The CurrentPage property contains the current page number. The initial value is 0, that is, the first page. In the Set method, we check that the value is in the range between 0 and the number of elements in the page list. As you remember, in the XAML code of the page the tag for the button has a Click event:
<Button Name="First" Click="First_Click" Margin="5" Background="Transparent">
Now we will write the handlers for these events, they are extremely simple:
private void First_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
        {
            CurrentPage = 0;
            SetImage();
        }
Here we set the current page - the first page and load the image corresponding to this page.
        private void Prev_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
        {
            CurrentPage--;
            SetImage();
        }
Here the current page is reduced by one. That is, each time you press the Prev button, one value will be taken from the current page number. So, we’ll go back to the initial page until the CurrentPage value reaches 0.
        private void Next_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
        {
            CurrentPage++;
            SetImage();
        }
For the Next button, everything is the same, but exactly the opposite. Here we increase the page number by 1.
        private void Last_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
        {
            CurrentPage = pages.Count - 1;
            SetImage();
        }
The Last button simply sets the maximum page number equal to the number of pages in the page list.
Let's add a couple of lines of code to the SetContent method:
        private void SetContent(Report report)
        {           
DeleteTempFiles();
            ex.ImageFormat = ImageExportFormat.Png;
            ex.Resolution = 96;
            Random rnd = new Random();
            ex.Export(report, Directory.GetCurrentDirectory() + "/test." + rnd.Next(100) + ".png");
            foreach (string file in ex.GeneratedFiles)
            {
                pages.Add(new Avalonia.Media.Imaging.Bitmap(file));
            }
            CurrentPage = 0;
        }
In the beginning, we've added a call to the function remove unnecessary export files left over from previous times.
And in the last line, we set the value of CurrentPage to 0. This is necessary in case you, for example, are viewing report page number 3 and want to load another report. The SetContent method will load the report and set the first page.
Do you remember how the image installation method looked like? Here it is:
public void SetImage()
        {
            img.Source = pages[0];
        }
In this form, it displays only the first page. But now at our disposal property CurrentPage. Let's refine the method so that it sets the current page:
        public void SetImage()
        {
            img.Source = pages[CurrentPage];
            img.Height = imHeight;
            img.Width = imWidth;
            PageNumber.Text = (CurrentPage + 1).ToString();
        }
In addition to loading the current image, we set the height and width of the image. The height and width values are equal to the initial height and width of the image, which we will save, for example, in the window constructor:
        private double imHeight;
        private double imWidth;
      
 public MainWindow()
        {
            InitializeComponent();
            imHeight = img.Height;
            imWidth = img.Width;
        }
This is necessary for returning to the initial settings of the image when moving to another page of the report in case of scaling has been applied, which we will soon implement too.
But let’s back to SetImage method. In the last line we set the current number in the text field. Thus, we will always know which report page is currently displayed.
Since we started working with PageNumber, let's implement the KeyDown event handler:        private void PageNumber_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                if (int.Parse(PageNumber.Text) > 0)
                {
                    CurrentPage = int.Parse(PageNumber.Text) - 1;
                    SetImage();
                }
            }
        }
If the Enter button is pressed, the report page with the number entered in the PageNumber text box will be loaded.
We have only two non-working buttons: zoom in and out. Implement the Click event for the Zoom_in button:
private void Zoom_in_Click(object sender, RoutedEventArgs e)
        {
                if (ex != null)
                {
                    ex.ImageFormat = ImageExportFormat.Png;
                    ex.Resolution += 25;
                    ex.PageNumbers = (CurrentPage + 1).ToString();
                     ex.Export(Report, Directory.GetCurrentDirectory() + "/testZoom.png");
                    if (CurrentPage >= 0 && CurrentPage < pages.Count)
                        img.Source = LoadImage(Directory.GetCurrentDirectory() + "/testZoom.png");
                    PageNumber.Text = (CurrentPage + 1).ToString();
                }
            img.Width += 50;
            img.Height += 50;
        }
In order to make the image appear sharp when zoomed, it is necessary to increase its resolution. And for this you need to do a new export. But if there are many pages in the report, exporting the entire report again will not be the best solution. It is much faster to export the current page. Therefore, in this method, we export the current page with an increased resolution and save it to a temporary file testZoom.png. Then we load this image into the Image object. We do the zooming by increasing the height and width of the image.
We create a similar handler for the Zoom_out button:
  private void Zoom_out_Click(object sender, RoutedEventArgs e)
        {
                if (ex != null)
                {
                    ex.ImageFormat = ImageExportFormat.Png;
                    ex.Resolution -= 25;
                    ex.PageNumbers = (CurrentPage + 1).ToString();
                    ex.Export(Report, Directory.GetCurrentDirectory() + "/testZoom.png");
                    if (CurrentPage >= 0 && CurrentPage < pages.Count)
                        img.Source = LoadImage(Directory.GetCurrentDirectory() + "/testZoom.png");
                    PageNumber.Text = (CurrentPage + 1).ToString();
                }

            img.Width -= 50;
            img.Height -= 50;
        }
It's all the same as in the previous method, only we do not increase the resolution, but decrease it. Also reduce the height and width of the image object.
Now let's test our application. Run it.
Using the "Open" button with an open folder icon, we select the report file in the dialog box. Press the button to go to the last page of the report:
Now let's try the zoom function. Press several times on the enlargment button:
And now reduce the size of the image:
We also check the function of switching to the desired report page by entering the number in the text field:
That's all. I hope this simple application will help you to use FastReport.OpenSource in your Avalonia applications.

Comments

Popular posts

How to use FastReport Open Source in ASP.NET Core Web API application

FastReport Open Source - what is it and how to use it

FastReport Designer Community Edition