I'm trying to export my chart in my clipboard as PNG file.

I want to export my Chart to PNG or JPEG or any image file in the clipboard, so i can copy it to another place with CTRL+V. Here is the code that get the image in base64. Commented code can be ignored but it represent the conversion from base64 to System.Drawing.Image . "ExportChart()" is triggered when a button "Save to clipboard" is clicked and "GetUrl()" is triggered "OnExportComplete".

    public async Task ExportChart(Microsoft.AspNetCore.Components.Web.MouseEventArgs args)
    {
        ExportType ExportFileType = ExportType.PNG;
        await Chart.ExportAsync(ExportFileType, FileName, null, false);
    }

    public void GetUrl(ExportEventArgs Args)
    {
        string dataURL = Args.DataUrl;
        //byte[] bytes = Convert.FromBase64String(dataURL);  

        //System.Drawing.Image image;
        //using (MemoryStream ms = new MemoryStream(bytes))
        //{
        //    image = System.Drawing.Image.FromStream(ms);
        //}
        Clipboard.SetTextAsync(dataURL);
    }

Notice that the Clipboard method is not the Windows.Forms class but the Maui.ApplicationModel class. This means that the method "SetImage()" doesn't exist in this context.


Thank you !


4 Replies

RS Ruba Shanmugam Syncfusion Team April 27, 2022 12:48 PM UTC

Hi Miquel,


Thank you for contacting Syncfusion support.


Currently, in the Syncfusion MAUI chart, we don't have export support. Still, we need some more information about your exact requirement. Can you please clarify the following, so that we can able to proceed further?


  1. What kind of chart you are using in the MAUI.
  2. Are you using any Syncfusion product in MAUI?
  3. Please share the issue replication sample with a video to reproduce our side


Regards,

Ruba Shanmugam



MM MIQUEL Maxime April 27, 2022 01:01 PM UTC

Hello,


Im using Syncfusion Blazor Charts in MAUI Blazor, and also Inputs and ColorPicker.

Here's the code of my page: 


@page "/display"
@using Newtonsoft.Json.Linq
@using System.Drawing


<div class="container">
    <div class="chart">
        <div class="boutons">
            <SfButton @onclick="AddChartSeries">sin(x)</SfButton>
            <SfButton @onclick="AddChartSeriesDeux">2sin(x)</SfButton>
            <SfButton @onclick="AddChartSeriesTrois">1/2*sin(2x)</SfButton>
            <SfButton @onclick="RemoveChartSeries">Remove Chart Series</SfButton>


            @*Si aucune courbe est selectionnée ou que plus d'une est selectionnée : On désactive le color picker*@
            @if(selection==null || selection.Count()==0 || selection.Count()>1){
                <SfColorPicker Disabled="true" Mode="ColorPickerMode.Palette" ModeSwitcher="false" ShowButtons="false" ValueChange="OnChange"></SfColorPicker>
            }
            //Sinon on affiche un color picker avec la valeur de la courbe selectionnée.
            else
            {
                foreach(int i in selection)
                {


                    <SfColorPicker Value="@SeriesCollection[i].color" Mode="ColorPickerMode.Palette" ModeSwitcher="false" ShowButtons="false" ValueChange="OnChange"></SfColorPicker>
                }
            }


        </div>
        <SfChart @ref="@Chart" SelectionMode="SelectionMode.Series">
            <ChartEvents OnPointClick="@PointClickHandler" OnExportComplete="@GetUrl"></ChartEvents>
            <ChartPrimaryXAxis Maximum="@max" Minimum="@min" Interval="5" CrossesAt="0"></ChartPrimaryXAxis>
            <ChartPrimaryYAxis Maximum="3" Minimum="-3" CrossesAt="0"></ChartPrimaryYAxis>
            <ChartTooltipSettings Enable=@active Shared=true Header="" EnableMarker=false Format="${series.name} <br> X : ${point.x} <br> Y : ${point.y}" Fill="white">
                <ChartTooltipBorder Color="rgb(247, 206, 105)" Width="2"></ChartTooltipBorder>
                <ChartTooltipTextStyle Color="black"></ChartTooltipTextStyle>
            </ChartTooltipSettings>
            <ChartSeriesCollection>
                @foreach (SeriesData series in SeriesCollection)
                {
                    <ChartSeries [email protected] [email protected] [email protected] Name="@series.name" Width="@series.width" Fill="@series.color" >
                            <ChartSeriesAnimation Enable="false"></ChartSeriesAnimation>
                    </ChartSeries>
                }
            </ChartSeriesCollection>
            <ChartAnnotations>
                @foreach(LineChartData p in annotations)
                {
                    <ChartAnnotation CoordinateUnits="Units.Point" [email protected] [email protected]()>
                        <ContentTemplate>
                            <div>je suis un point</div>
                        </ContentTemplate>
                    </ChartAnnotation>
                }
            </ChartAnnotations>
            <ChartLegendSettings Visible="true" ToggleVisibility="true"></ChartLegendSettings>
        </SfChart>
    </div>
    <div id="modif">
        <p>Min</p>
        <SfNumericTextBox TValue="double" Value="@min" Max="-1" Min="-200">
            <NumericTextBoxEvents TValue="double" ValueChange="OnChangeMin"></NumericTextBoxEvents>
        </SfNumericTextBox>
        <p>Pas</p>
        <SfNumericTextBox TValue="double" Value="@pas" Min="0.01" Max="10">
            <NumericTextBoxEvents TValue="double" ValueChange="OnChangePas"></NumericTextBoxEvents>
        </SfNumericTextBox>
        <p>Max</p>
        <SfNumericTextBox TValue="double" Value="@max" Max="200" Min="-1">
            <NumericTextBoxEvents TValue="double" ValueChange="OnChangeMax"></NumericTextBoxEvents>
        </SfNumericTextBox>
        <SfButton OnClick="ExportChart" IsToggle="true" IsPrimary="true">
            Export


        </SfButton>
        <SfButton OnClick="activate" IsPrimary="true" IsToggle="true">
            Enable trackball


        </SfButton>


    </div>
</div>


@code{
    public List<LineChartData> annotations = new List<LineChartData>();


    public bool active = false;
    public Dictionary<string,bool> palettes= new Dictionary<string,bool>();
    private double pas { get; set; }
    private double min { get; set; }
    private double max { get; set; }
    List<SeriesData> SeriesCollection;
    private List<int> selection = new List<int>();
    SfChart Chart;
    public string FileName { get; set; } = "Graph";






    //Change la velur booleene de active quand on active ou desactive la trackball
    public void activate(MouseEventArgs args)
    {
        this.active = !this.active;
    }


    //Permet d'exporter le Graphique au format png
    public async Task ExportChart(Microsoft.AspNetCore.Components.Web.MouseEventArgs args)
    {
        ExportType ExportFileType = ExportType.PNG;
        await Chart.ExportAsync(ExportFileType, FileName,null,false);
    }


    //Permet de recupèrer la base64 du graphique (png)
    public void GetUrl(ExportEventArgs Args)
    {
        string dataURL = Args.DataUrl;
        //byte[] bytes = Convert.FromBase64String(dataURL);


        //System.Drawing.Image image;
        //using (MemoryStream ms = new MemoryStream(bytes))
        //{
        // image = System.Drawing.Image.FromStream(ms);
        //}
        Clipboard.SetTextAsync(dataURL);
    }


    //Permet le changement de couleur en fonction de la couleur selectionnée
    public void OnChange(ColorPickerEventArgs args)
    {
        if(selection.Count()==1){
            foreach(int i in selection)
            {
                SeriesCollection[i].color = args.CurrentValue.Hex;
            }
            StateHasChanged();
            Chart.RefreshAsync();
        }
    }


    //Méthode appelé quand une courbe et cliquée
    public void PointClickHandler(PointEventArgs args)
    {


        //Si le trackball n'est pas afficher :
        if (!active)
        {
            //On récupère son index dans "SeriesCollection"
            int i = (int)args.SeriesIndex;


            if (selection.Contains(i))
            {
                SeriesCollection[i].width = 1;
                selection.Remove(i);
            }
            else
            {
                selection.Add(i);
                SeriesCollection[i].width = 2;
            }
            StateHasChanged();
            Chart.RefreshAsync();
        }
        //Si le trackball est afficher : On ajoute une nouvelle annotation
        else
        {
            double X = (double)args.X;
            double Y = (double)args.Y;
            annotations.Add(new LineChartData { XValue = X, YValue = Y });
            StateHasChanged();
            Chart.RefreshAsync();
        }
    }




    //On ajoute la première courbe et on définit sa couleur
    public void AddChartSeries()
    {
        string couleurDispo = "";
        foreach(string key in palettes.Keys)
        {
            if (!palettes[key])
            {
                couleurDispo = key;
                palettes[key] = true;
                break;
            }
        }
        SeriesCollection.Add(new SeriesData
        {
            name="sin(x)",
            XName = nameof(LineChartData.XValue),
            YName = nameof(LineChartData.YValue),
            Data = GetChartData(1),
            color=couleurDispo,
            width=1
        });
    }


    //On ajoute la deuxième courbe et on définit sa couleur
    public void AddChartSeriesDeux()
    {
        string couleurDispo = "";
        foreach(string key in palettes.Keys)
        {
            if (!palettes[key])
            {
                couleurDispo = key;
                palettes[key] = true;
                break;
            }
        }
        SeriesCollection.Add(new SeriesData
        {
            name="2sin(x)",
            XName = nameof(LineChartData.XValue),
            YName = nameof(LineChartData.YValue),
            Data = GetChartData(2),
            color=couleurDispo,
            width=1
        });
    }


    //On ajoute la troisième courbe et on définit sa couleur
    public void AddChartSeriesTrois()
    {
        string couleurDispo = "";
        foreach(string key in palettes.Keys)
        {
            if (!palettes[key])
            {
                couleurDispo = key;
                palettes[key] = true;
                break;
            }
        }
        SeriesCollection.Add(new SeriesData
        {
            name = "1/2*sin(x)",
            XName = nameof(LineChartData.XValue),
            YName = nameof(LineChartData.YValue),
            Data = GetChartData(3),
            color=couleurDispo,
            width=1
        });
    }


    //Au changement du pas
    public void OnChangePas(Syncfusion.Blazor.Inputs.ChangeEventArgs<double> args)
    {
        this.pas = args.Value;
        StateHasChanged();
    }
    //Au changement du min
    public void OnChangeMin(Syncfusion.Blazor.Inputs.ChangeEventArgs<double> args)
    {
        this.min = args.Value;
        StateHasChanged();
    }
    //Au changement du max
    public void OnChangeMax(Syncfusion.Blazor.Inputs.ChangeEventArgs<double> args)
    {
        this.max = args.Value;
        StateHasChanged();
    }




    //Classe permettant de supprimer une series
    public void RemoveChartSeries()
    {
        //Si aucune courbe n'est selectionée, on les supprimes toutes et on dit que sa couleur n'est plus utilisée
        if (selection.Count() == 0)
        {
            foreach(KeyValuePair<string,bool> kvp in palettes)
            {
                palettes[kvp.Key] = false;
            }


            SeriesCollection = new List<SeriesData>();
            selection = new List<int>();
        }
        //Sinon on supprrime les courbes sélectionées et on rend leur couleur de nouveau disponibles
        else
        {
            List<SeriesData> Asupprimer = new List<SeriesData>();
            foreach(int i in selection)
            {
                palettes[SeriesCollection[i].color] = false;
            }
            foreach(int i in selection)
            {
                Asupprimer.Add(SeriesCollection[i]);
            }
            foreach(SeriesData s in Asupprimer)
            {
                SeriesCollection.Remove(s);
            }
            selection = new List<int>();
        }
    }


    //A l'initialisation de la page
    protected override void OnInitialized()
    {
        base.OnInitialized();


        //On ajoute les couleurs par défaut des courbes
        palettes.Add("#0000FF", false);
        palettes.Add("#FF0000", false);
        palettes.Add("#00FF00", false);




        //On définit le pas, min et max par défaut de notre graphique
        this.pas = 0.1;
        this.min = -20;
        this.max = 20;


        //On instancie la liste des series
        SeriesCollection = new List<SeriesData>();
    }


    //En fonction de la valeur donnée, cette méthode remplis et renvoie une série de donnée correspondante
    private List<LineChartData> GetChartData(int courbe)
    {


        List<LineChartData> data = new List<LineChartData>();


        //Si correpond à la courbe 1
        if (courbe == 1)
        {
            for (double i = 0; i <= max; i+=pas)
            {
                data.Add(new LineChartData()
                {
                    XValue = i,
                    YValue = Math.Sin(i)
                });
            }
            for (double i = -pas; i >= min; i -= pas)
            {
                data.Add(new LineChartData()
                {
                    XValue = i,
                    YValue = Math.Sin(i)
                });
            }
        }//Si la courbe correspond à la 2
        else if (courbe == 2)
        {


            for (double i = 0; i <= max; i+=pas)
            {
                data.Add(new LineChartData()
                {
                    XValue = i,
                    YValue = 2*(Math.Sin(i))
                });
            }
            for (double i = -pas; i >= min; i -= pas)
            {
                data.Add(new LineChartData()
                {
                    XValue = i,
                    YValue = 2*(Math.Sin(i))
                });
            }
        }//Et enfin si la courbe est la 3ème
        else if (courbe == 3)
        {
            for (double i = 0; i <= max; i+=pas)
            {
                data.Add(new LineChartData()
                {
                    XValue = i,
                    YValue = 0.5*(Math.Sin(2*i))
                });
            }
            for (double i = -pas; i >= min; i -= pas)
            {
                data.Add(new LineChartData()
                {
                    XValue = i,
                    YValue = 0.5*(Math.Sin(2*i))
                });
            }
        }




        List<LineChartData> SortedList = data.OrderBy(o => o.XValue).ToList();
        return SortedList;
    }




    //Classe contenannt les informations relatives à une serie
    public class SeriesData
    {
        public string name
        {
            get;
            set;
        }


        public string XName
        {
            get;
            set;
        }
        public string YName
        {
            get;
            set;
        }
        public List<LineChartData> Data
        {
            get;
            set;
        }


        public string color
        {
            get;
            set;
        }


        public int width
        {
            get;
            set;
        }


    }


    //Classe représentant les points du graphique
    public class LineChartData
    {
        public double XValue
        {
            get;
            set;
        }
        public double YValue
        {
            get;
            set;
        }
    }


}


DG Durga Gopalakrishnan Syncfusion Team May 2, 2022 12:33 PM UTC

Hi Miquel,


We are analyzing your reported scenario. We will update the status within two business days(5th April 2022). We appreciate your patience until then.


Regards,

Durga Gopalakrishnan.



DG Durga Gopalakrishnan Syncfusion Team May 5, 2022 11:48 AM UTC

Hi Miquel,


Thanks for being patience.


We have prepared sample to export Syncfusion chart as PNG in .NET MAUI Blazor Application. Chart is exported fine as per behavior. Please check with the below sample and documentation link.



Sample : https://www.syncfusion.com/downloads/support/directtrac/general/ze/MauiApp2090708551.zip


UG : https://blazor.syncfusion.com/documentation/getting-started/maui-blazor-app


Kindly revert us if you have any concerns.


Regards,

Durga Gopalakrishnan.


Loader.
Up arrow icon