Setting a dynamic size for an Asp:Chart control

11,887

You can use CSS styles to make sure that the chart fills the panel. The chart element, which is an image in the HTML output, will be stretched or compressed when the browser window is resized.

<style>
    html, body, form
    {
        height: 100%;
    }

    .chart
    {
        width: 100% !important;
        height: 100% !important;
    }
</style>

As for setting the Width and Height of the chart, there is a catch: the actual size of the panel is not available until the page has been loaded in the browser. After that, you can get the size with Javascript code and store the values in hidden fields, which are then available in code behind.

You could trigger a postback the first time the page has loaded, to adjust the chart to the size of the panel. To make the adjustment dynamic, other postbacks could be triggered every time the window size changes by a certain amount. With the help of an UpdatePanel, the visual impact of the postbacks can be reduced.

<asp:ScriptManager ID="scriptManager1" runat="server" />
<asp:HiddenField ID="panelWidth" runat="server" Value="" />
<asp:HiddenField ID="panelHeight" runat="server" Value="" />
<asp:UpdatePanel ID="UpdatePanel1" runat="server" style="width: 90%; height: 40%">
    <ContentTemplate>
        <asp:Chart ID="Chart1" runat="server" CssClass="chart" Visible="false">
            <Series>
                <asp:Series Name="Series1"></asp:Series>
            </Series>
            <ChartAreas>
                 <asp:ChartArea Name="ChartArea1"></asp:ChartArea>
            </ChartAreas>
        </asp:Chart>
        <asp:Button ID="btnPostBack" runat="server" Style="display: none" />
    </ContentTemplate>
</asp:UpdatePanel>
<script type="text/javascript">
    (function () {
        var panel = document.getElementById('<%= UpdatePanel1.ClientID %>');
        var panelWidth = document.getElementById('<%= panelWidth.ClientID %>');
        var panelHeight = document.getElementById('<%= panelHeight.ClientID %>');
        var initialWidth = panel.offsetWidth;
        var initialHeight = panel.offsetHeight;

        function getChangeRatio(val1, val2) {
            return Math.abs(val2 - val1) / val1;
        };

        function redrawChart() {
            setTimeout(function () {
                initialWidth = panel.offsetWidth;
                initialHeight = panel.offsetHeight;
                document.getElementById('<%= btnPostBack.ClientID %>').click();
            }, 0);
        };

        function savePanelSize() {
            var isFirstDisplay = panelWidth.value == '';
            panelWidth.value = panel.offsetWidth;
            panelHeight.value = panel.offsetHeight;
            var widthChange = getChangeRatio(initialWidth, panel.offsetWidth);
            var heightChange = getChangeRatio(initialHeight, panel.offsetHeight);
            if (isFirstDisplay || widthChange > 0.2 || heightChange > 0.2) {
                redrawChart();
            }
        };

        savePanelSize();
        window.addEventListener('resize', savePanelSize, false);
    })();
</script>

The Javascript function savePanelSize is called after loading and after resizing the window. Empty values in the hidden fields indicate that the chart is displayed for the first time and that its size must be set in code behind. A redraw is also needed when the window size changes by more than 20%. The hidden button btnPostBack is used to trigger postbacks programmatically.

In code behind, the width and height of the chart are set to the size of the panel:

protected void Page_Load(object sender, EventArgs e)
{
    if (panelWidth.Value != "" && panelHeight.Value != "")
    {
        Chart1.Visible = true;
        Chart1.Width = int.Parse(panelWidth.Value);
        Chart1.Height = int.Parse(panelHeight.Value);
    }
}
Share:
11,887
Innat3
Author by

Innat3

Still under development...

Updated on June 06, 2022

Comments

  • Innat3
    Innat3 almost 2 years

    I am trying to make my chart width and height dynamic but I can't get it to work. So far what I've tried:

    I've set the Chart inside an Asp:Panel and given the panel the desired percentual values.

        <asp:Panel ID="Panel1" runat="server" Width="90%" Height="40%">
            <asp:Chart ID="Chart1" runat="server" CssClass="chart">
                <Series>
                    <asp:Series Name="Series1"></asp:Series>
                </Series>
                <ChartAreas>
                     <asp:ChartArea Name="ChartArea1"></asp:ChartArea>
                </ChartAreas>
            </asp:Chart>
        </asp:Panel>
    

    Then I try to assign those values to the chart in my C# code

        Chart1.Width = Panel1.Width;
        Chart1.Height = Panel1.Height;
    

    This however generates an exception, as the chart is receiving the percentual value instead of the amount of pixels. I also tried (int)Panel.Width.Value to no avail.

    I tried doing it with CSS as well, fiddling around with position:absolute and other attributes, but again, I can get it to work for a panel but not for a chart.

    Could anyone enlighten me with a simple solution which won't require getting into JQuery and such?

    EDIT:

    The variable value of Panel1.Width will output 90% while Panel1.Width.Value will for some reason output 90 (40% and 40 for Panel1.Height).

    Chart1.Width.Value will have a default value of 300px assigned by Visual Studio, therefore:

    Chart1.Width = new Unit(Chart1.Width.Value * Panel1.Width.Value / 100, UnitType.Pixel);
    

    will output the same as if I were to do:

    Chart1.Width = new Unit(300 * 90 / 100, UnitType.Pixel);
    

    OUTPUT: a static value of 270px

    I NEED to get the pixel value retrieved by the Panel1.Width percentage, but I can't figure out a way of doing that

    EDIT 2:

    The chart stretching bit with css works correctly but the output is a bit underwhelming, so I am trying to to make the javascript example work but I am having no success... I added a button to force a postback and in the page_load event I inserted:

    protected void Page_Load(object sender, EventArgs e)
    {
        if (IsPostBack)
        {
            if (panelWidth.Value != "" && panelHeight.Value != "")
            {
                Chart1.Visible = true;
                Chart1.Width = int.Parse(panelWidth.Value);
                Chart1.Height = int.Parse(panelHeight.Value);
            }
        }
        else //Initialize the chart with some sample points
        {
            Chart1.Series[0].Points.AddXY(1, 1);
            Chart1.Series[0].Points.AddXY(1, 2);
            Chart1.Series[0].Points.AddXY(2, 1);
            Chart1.Series[0].Points.AddXY(2, 2);
            Chart1.Series[0].Points.AddXY(3, 1);
            Chart1.Series[0].Points.AddXY(3, 2);
        }
    }
    

    If I start the page the chart is obviously not visible, so I also added a button

    <asp:Button ID="Button1" runat="server" Text="Button" />
    

    to the form to trigger a postback, which does reload the page but the panelWidth.Value and panelHeight.Value are still empty. Am I missing something? Seems like I can't trigger the javascript code :/

  • Innat3
    Innat3 over 7 years
    I am having trouble making the javascript code work, could you help me? I added the details on my question's 2nd edit
  • ConnorsFan
    ConnorsFan over 7 years
    Make sure that the markup and the Javascript code is copy/pasted in your ASPX file exactly as currently shown in my answer, without any change. The Javascript code block should be at the end of the form. If necessary, you can put the markup and code in an empty project to test it. You can also add calls like alert('I am here);` in the Javascript code to check if it is executed. The chart should be displayed and sized correctly without having to click anything.
  • Innat3
    Innat3 over 7 years
    Ahh problem was the js code placement, I had it right after the <title> thanks!