简体   繁体   中英

Position values are not match with actual values

Microsoft Chart Control generates a different visual then the set property. Property based it always shows correct value but if you open the generated chart with graphic software like Photoshop it shows pixels are not matching with the set property.

I found this bug while trying to retrieve all InnerPlot Positions into a HiddenField. Based on this bug right now, there is no way to get correct absolute position of ChartAreas or InnerPlots. Please let me know if you believe there is a workaround about it...

Thank you for your time and attention...


STEPS TO REPRODUCE

Test.aspx

<%@ Page Language="VB" AutoEventWireup="false" CodeFile="Test.aspx.vb" Inherits="Test" %>
<%@ Register Assembly="System.Web.DataVisualization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
    Namespace="System.Web.UI.DataVisualization.Charting" TagPrefix="asp" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Test</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
     <asp:Chart ID="Chart1" runat="server"></asp:Chart>
    </div>
    </form>
</body>
</html>

Test.aspx.vb

Imports System.Web.UI.DataVisualization.Charting

Partial Class Test
    Inherits System.Web.UI.Page

    Private Sub DataHelper()
        Dim Historical() As String = _
    { _
    "Date,Open,High,Low,Close,Volume", _
    "2009-03-05,1.75,2.00,1.73,1.81,47339300", _
    "2009-03-04,1.90,1.90,1.83,1.87,22306600", _
    "2009-03-03,1.91,1.91,1.80,1.81,15412400", _
    "2009-03-02,1.91,1.94,1.83,1.88,19585500", _
    "2009-02-27,1.93,2.00,1.80,2.00,31469500", _
    "2009-02-26,2.08,2.09,1.81,1.98,32307100", _
    "2009-02-25,2.10,2.16,2.00,2.01,54325200", _
    "2009-02-24,1.80,2.00,1.80,2.00,33935300", _
    "2009-02-23,1.65,1.91,1.61,1.73,44444100", _
    "2009-02-20,1.60,1.61,1.50,1.58,37889100" _
    }
        Dim Query As IEnumerable = From HistoricalLine In Historical Skip 1 _
                                   Where Not String.IsNullOrEmpty(HistoricalLine) _
                                   Let HistoricalFields = HistoricalLine.Split(",") _
                                   Let HistoricalDate = CDate(HistoricalFields(0)) _
                                   Order By HistoricalDate Ascending _
                                   Select New With { _
                                    .Date = HistoricalDate, _
                                    .Open = CDbl(HistoricalFields(1)), _
                                    .High = CDbl(HistoricalFields(2)), _
                                    .Low = CDbl(HistoricalFields(3)), _
                                    .Close = CDbl(HistoricalFields(4)), _
                                    .Volume = CDbl(HistoricalFields(5)) _
                                   }

        Chart1.DataSource = Query
    End Sub

    Private Sub CreateChartArea(ByVal areaname As String)
        Chart1.ChartAreas.Add(New ChartArea)
        With Chart1.ChartAreas.Last
            .Name = areaname
            .AxisY2.Enabled = AxisEnabled.False
            .AxisX2.Enabled = AxisEnabled.False
            With .AxisX
                .MajorTickMark.Enabled = False
                .MinorTickMark.Enabled = False
                .MinorGrid.Enabled = False
                .MajorGrid.LineColor = Drawing.Color.Yellow
            End With
            With .AxisY
                .MajorTickMark.Enabled = False
                .MinorTickMark.Enabled = False
                .MinorGrid.Enabled = False
                .MajorGrid.LineColor = Drawing.Color.Red
                .IsStartedFromZero = False
            End With
            .BackColor = Drawing.Color.SkyBlue
            .BorderDashStyle = ChartDashStyle.Solid
            .BorderColor = Drawing.Color.Brown
            .BorderWidth = 0
            .ShadowOffset = 0
        End With
    End Sub

    Private Sub CreateSeries(ByVal seriename As String, ByVal areaname As String)
        Chart1.Series.Add(New Series)
        With Chart1.Series.Last
            .Name = seriename
            .ChartArea = areaname
            .YValuesPerPoint = 4
            .ChartType = SeriesChartType.Candlestick
            .XValueType = ChartValueType.DateTime
            .IsXValueIndexed = True
            .XValueMember = "Date"
            .YValueMembers = "High,Low,Open,Close"
            .BorderColor = Drawing.Color.Green
            .IsValueShownAsLabel = True
        End With
    End Sub

    Private Sub ChartHelper()
        Chart1.ImageStorageMode = ImageStorageMode.UseImageLocation
        Chart1.ImageLocation = "~/_temp/HG_#SEQ(300,60)"   '<= make sure you have "_temp" directory
        Chart1.ImageType = ChartImageType.Png
        Chart1.RenderType = RenderType.ImageTag

        Chart1.Titles.Add(New Title())
        Chart1.Legends.Add(New Legend())
        Chart1.Legends.Last.Enabled = False

        Chart1.Palette = ChartColorPalette.BrightPastel
        Chart1.BackColor = Drawing.Color.Pink

        CreateChartArea("A1")
        CreateSeries("S1", "A1")

        CreateChartArea("A2")
        CreateSeries("S2", "A2")

        CreateChartArea("A3")
        CreateSeries("S3", "A3")

        CreateChartArea("A4")
        CreateSeries("S4", "A4")

        Chart1.DataBind()
        Chart1.SaveXml(Server.MapPath("~/_temp/MyChart.xml"))
    End Sub

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        If Not Page.IsPostBack Then
            DataHelper()
            ChartHelper()
            TestPart()
        End If
    End Sub

    Private Sub TestPart()
        Dim SpaceBetweenChartAreas As Single = 1 '<= %1 of Chart's Height

        Chart1.Height = 500
        Chart1.Width = 1000

        Dim locator As Integer = 0
        For Each chartareaItem In Chart1.ChartAreas
            With chartareaItem
                .Position.Auto = False
                .Position.Height = 20 '500px/100*20 = 100px
                .Position.Width = 80 '1000px/100*80 = 800px
                .Position.X = 0
                .Position.Y = locator
                .InnerPlotPosition.Auto = False
                .InnerPlotPosition.Height = 100 '%100 of ChartArea Position's Height
                .InnerPlotPosition.Width = 100 ' %100 of ChartArea Position's Width
                .InnerPlotPosition.X = 0
                .InnerPlotPosition.Y = 0
                locator += SpaceBetweenChartAreas + .Position.Height
            End With
        Next
    End Sub

End Class

Please don't forget to create a directory "_temp"

Also you can see the actual result at http://ilerler.com/-bug4ms/Test.png
在此处输入图片说明

RESULTS

1st ChartArea Height
ACTUAL 101px | EXPECTED 100px

space
ACTUAL 4px | EXPECTED 5px

2nd ChartArea Height
ACTUAL 101px | EXPECTED 100px

space
ACTUAL 4px | EXPECTED 5px

3rd ChartArea Height
ACTUAL 100px | EXPECTED 100px

space
ACTUAL 4px | EXPECTED 5px

4th ChartArea Height
ACTUAL 101px | EXPECTED 100px

space
ACTUAL 85px | EXPECTED 85px

You have the following line:

Dim SpaceBetweenChartAreas As Single = 1 '<= %1 of Chart's Height

That means that your calculations are being performed with single precision float point values - which are highly susceptible to rounding errors.

At the very least you should use Double values.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM