首页 > 解决方案 > 如何在 DevExpress BootstrapChart 的不同窗格中分隔线系列组?

问题描述

现在,我正在使用DevExpress BootstrapChart (v17.2.13.0)开发 Web 应用程序,并且已将控件与对象数据源绑定。以下是用于在图表中显示的示例数据:

在此处输入图像描述

这是我的目标:

所以图表应该是这样的:

在此处输入图像描述

但是,此时只能实现的是,线系列要么显示在两个窗格中但未分组,要么在图表中不显示任何内容。

这是我的代码:

<dx:BootstrapChart ID="chart" ClientInstanceName="chart" runat="server" 
    DataSourceID="ods_ChartData" Height="640px" TitleText="Chart Data" CrosshairEnabled="true" Panes="A,B">
    <ClientSideEvents Init="OnChartInit" />
    <SettingsToolTip Shared="true" Enabled="true" OnClientCustomizeTooltip="ChartToolTip" />
    <ArgumentAxis ArgumentType="System.DateTime" GridVisible="True" MinorGridVisible="True" 
        TickVisible="True" MinorTickVisible="True" TickInterval="1" MinorTickCount="3" TitleText="Date">
        <Label DisplayMode="Rotate" RotationAngle="-0" Format-Formatter="FormatDate" />
    </ArgumentAxis>
    <ValueAxisCollection>
        <dx:BootstrapChartValueAxis Pane="A" TitleText="ademand_im" />
        <dx:BootstrapChartValueAxis Pane="B" TitleText="rdemand_im" />
    </ValueAxisCollection>
    <SettingsCommonSeries Type="Line" ArgumentField="data_time" Point-Size="0" />
    <SettingsSeriesTemplate NameField="hardware_id" />
    <SeriesCollection>
        <dx:BootstrapChartLineSeries Pane="A" ValueField="ademand_im" />
        <dx:BootstrapChartLineSeries Pane="B" ValueField="rdemand_im" />
    </SeriesCollection>
</dx:BootstrapChart>

在此代码中,如果我删除“SettingsSeriesTemplate”行,数据将显示在两个窗格中,但在每个窗格中仅显示为单行。但是,如果我保留这条线,图表将不会显示任何内容。

标签: asp.netchartsdevexpressseriespane

解决方案


在我尝试了解此控件的工作原理后,我发现的唯一解决方案是我必须将“hardware_id”列转换为“ademand_im”和“rdemand_im”值,这可能不是理想的值。

因此,应该将表转换为具有“ademand_im_83245551”、“ademand_im_88310991”、“rdemand_im_83245551”和“rdemand_im_88310991”列,而不是“hardware_id”、“ademand_im”和“rdemand_im”列。

这是转换后的表格的样子:

在此处输入图像描述

这是我用来转换表格的函数代码(VB.NET):

<Extension()>
Public Function PivotDataTableColumnGroup(srcData As DataTable, rowGroupField As String, pivotColumnField As String, valueGroupFields As IEnumerable(Of String),
                                            Optional ValueGroupColumnName As Func(Of String, String, String) = Nothing,
                                            Optional otherFields As IEnumerable(Of String) = Nothing,
                                            Optional GetOtherFieldValue As Func(Of DataTable, String, Object, Object) = Nothing
                                            ) As DataTable
    Dim groupValueList As List(Of Object) = srcData.GetDistinctValuesByColumnName(rowGroupField)
    Dim pivotValueList As List(Of Object) = srcData.GetDistinctValuesByColumnName(pivotColumnField)
    Dim hasOtherFieldColumn As Boolean = Not (otherFields Is Nothing Or GetOtherFieldValue Is Nothing)

    Dim dt As New DataTable
    With dt
        .Columns.Add(rowGroupField, srcData.Columns(rowGroupField).DataType)
        For i As Integer = 0 To valueGroupFields.Count - 1
            For j As Integer = 0 To pivotValueList.Count - 1
                Dim columnName As String = GetColumnNameFromGroupFieldAndPivotValues(valueGroupFields(i), pivotValueList(j), ValueGroupColumnName)
                dt.Columns.Add(columnName, srcData.Columns(valueGroupFields(i)).DataType)
            Next
        Next
        If hasOtherFieldColumn Then
            For i As Integer = 0 To otherFields.Count - 1
                .Columns.Add(otherFields(i), srcData.Columns(otherFields(i)).DataType)
            Next
        End If

        For i As Integer = 0 To groupValueList.Count - 1
            Dim currentGroupValue As Object = groupValueList(i)
            Dim dr As DataRow = dt.NewRow()
            dr(rowGroupField) = currentGroupValue
            If hasOtherFieldColumn Then
                For j As Integer = 0 To otherFields.Count - 1
                    dr(otherFields(j)) = DBNullIfNothing(GetOtherFieldValue(srcData, otherFields(j), currentGroupValue))
                Next
            End If
            For j As Integer = 0 To valueGroupFields.Count - 1
                Dim currentField As String = valueGroupFields(j)
                For k As Integer = 0 To pivotValueList.Count - 1
                    Dim currentPivotValue As Object = pivotValueList(k)
                    Dim columnName As String = GetColumnNameFromGroupFieldAndPivotValues(valueGroupFields(j), pivotValueList(k), ValueGroupColumnName)
                    Dim value As Object = (From row In srcData.AsEnumerable
                                            Where row(rowGroupField) = currentGroupValue _
                                                    AndAlso row(pivotColumnField) = currentPivotValue
                                            Select row(currentField)
                                            ).FirstOrDefault
                    dr(columnName) = DBNullIfNothing(value)
                Next
            Next
            dt.Rows.Add(dr)
        Next
    End With
    Return dt
End Function

<Extension()>
Public Function GetDistinctValuesByColumnName(dt As DataTable, columnName As String) As List(Of Object)
    Dim valueList As List(Of Object) = (From row As DataRow In dt.AsEnumerable
                                        Where Not IsDBNull(row(columnName))
                                        Order By row(columnName)
                                        Select row(columnName) Distinct
                                        ).ToList
    Return valueList
End Function

Private Function GetColumnNameFromGroupFieldAndPivotValues(groupField As String, pivotValue As Object, Optional ValueGroupColumnName As Func(Of String, String, String) = Nothing) As String
    Dim columnName As String = groupField & "_" & pivotValue.ToString()
    If ValueGroupColumnName IsNot Nothing Then
        columnName = ValueGroupColumnName(groupField, pivotValue)
    End If
    Return columnName
End Function

Public Function DBNullIfNothing(o As Object) As Object
    If o Is Nothing Then Return DBNull.Value
    Return o
End Function

这就是我使用该函数转换表格的方式:

Dim chartData As DataTable = result.PivotDataTableColumnGroup("data_time", "hardware_id", {"ademand_im", "rdemand_im"}, Nothing, Nothing, Nothing)
ResultChartData = chartData     'Stored in ASPxHiddenField in JSON form

之后,我必须在后面的代码中手动添加图表系列,而不是在 aspx 文件中设置图表系列属性:

Private Sub chart_LoadProfile_DataBound(sender As Object, e As EventArgs) Handles chart_LoadProfile.DataBound
    Using ResultChartData
        Dim seriesList As List(Of String) = (From col As DataColumn In ResultChartData.Columns
                                                Where col.ColumnName <> "data_time"
                                                Order By col.ColumnName
                                                Select col.ColumnName
                                        ).ToList
        Dim hardWardCount As Integer = (From s In seriesList Where s.Contains("ademand_im_")).Count
        Dim showInLegend As Boolean = hardWardCount > 1
        With chart_LoadProfile.SeriesCollection
            .Clear()
            For i As Integer = 0 To seriesList.Count - 1
                Dim fieldName As String = seriesList(i)
                Dim hardwareId As String = seriesList(i).Split("_")(2)
                Dim series As New BootstrapChartLineSeries
                With series
                    .ArgumentField = "data_time"
                    .ValueField = fieldName
                    .Point.Size = 0
                    .ShowInLegend = showInLegend
                    If fieldName.Contains("ademand_im_") Then
                        .Pane = "A"
                        .Name = "kW - " & hardwareId
                    Else
                        .Pane = "B"
                        .Name = "kVar - " & hardwareId
                    End If
                End With
                .Add(series)
            Next
        End With
    End Using
End Sub

推荐阅读