This example illustrates how to show a chart control with many points. The built-in Charts module draws all points on the same screen at once, and this can affect readability. To improve usability, you can implement real-time zooming and scrolling, for example, the dxChart
widget from the DevExtreme library. This example shows how to use this widget in an XAF application.
Implementation Details
The approach used in this example is based on the technique of displaying a custom data bound control. The example demonstrates how to use this technique with client-side components that do not have server-side implementation.
- Register client libraries. For details, refer to the corresponding section of the How to use DevExtreme Widgets in an XAF application Knowledge Base article.
- Create the content. In the YourSolutionName.Web project, create a custom ASP.NET user control (*.ascx) and add ASPxPanel to it that acts as the container for DevExtreme widgets. It is convenient to keep client-side scripts in a separate file. Add a JavaScript file and declare the
createWidgets
function in it. Implement this function using the approach described in the following topic: Zooming and Panning.
Using the client-side Init event of the ASPxPanel component, call theJavaScriptwindow.DxSample = window.DxSample || {}; window.DxSample.OrdersChart = { createWidgets: function (panel) { var $mainElement = $(panel.GetMainElement()); $mainElement.dxChart({..}); } };
createWidgets
function and pass the first event argument as this function parameter. - Register your JavaScript files. In code behind for your user control (e.g., YourSolutionName.Web/YourUserControlName.ascx.xx file), handle the UserControl.Load event and call the WebWindow.RegisterClientScriptInclude method to include your JavaScript file into the web page.
- Load data and pass it to the client side. To supply data for client-side widgets, use the approach described in the following article: Passing Values Between Client and Server Sides. For this purpose, implement the IComplexControl interface in your UserControl class. Within the IComplexControl.Setup method, load data from the database, convert it to an array of plain objects, and add it to the JSProperties dictionary.
- Add your user control to the Application Model using the approach demonstrated in the following article: How to: Show a Custom Data-Bound Control in an XAF View (ASP.NET Web Forms).
Files to Review
Documentation
- How to use DevExtreme Widgets in an XAF application
- Passing Values Between Client and Server Sides
- How to: Show a Custom Data-Bound Control in an XAF View (ASP.NET Web Forms)
Example Code
Code<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="OrdersChart.ascx.cs" Inherits="WebChart.Web.OrdersChart" %>
<%@ Register Assembly="DevExpress.Web.v23.1, Version=23.1.6.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a"
Namespace="DevExpress.Web" TagPrefix="dx" %>
<dx:ASPxPanel ID="ASPxPanel1" runat="server">
<ClientSideEvents Init="function(s, e) {
DxSample.OrdersChart.createWidgets(s);
}" />
<PanelCollection>
<dx:PanelContent runat="server">
<div class="dxsample-orderschart-chart"></div>
<div class="dxsample-orderschart-range"></div>
</dx:PanelContent>
</PanelCollection>
</dx:ASPxPanel>
C#using System;
using System.Linq;
using System.Web.UI;
using DevExpress.ExpressApp;
using DevExpress.ExpressApp.Editors;
using DevExpress.ExpressApp.Web;
using DxSample.Module.BusinessObjects;
namespace WebChart.Web {
public partial class OrdersChart : UserControl, IComplexControl {
protected void Page_Load(object sender, EventArgs e) {
string url = this.ResolveClientUrl("~/Scripts/Controls/orders-chart.js");
WebWindow.CurrentRequestWindow.RegisterClientScriptInclude("orders-chart", url);
}
private object GetChartData(IObjectSpace objectSpace) {
string[] countriesToDisplay = new string[] { "Germany", "Mexico", "UK" };
return objectSpace.GetObjectsQuery<Order>()
.Where(o => countriesToDisplay.Contains(o.Customer.Country))
.ToArray()
.GroupBy(o => new
{
date = new DateTime(o.OrderDate.Year, o.OrderDate.Month, 1),
country = o.Customer.Country
})
.Select(og => new
{
arg = og.Key.date,
val = og.Sum(o => o.UnitPrice),
series = og.Key.country
})
.ToArray();
}
#region IComplexControl Members
void IComplexControl.Refresh() {
}
void IComplexControl.Setup(IObjectSpace objectSpace, XafApplication application) {
this.ASPxPanel1.JSProperties.Add("cpChartData", this.GetChartData(objectSpace));
}
#endregion
}
}
JavaScript"use strict";
(function () {
window.DxSample = window.DxSample || {};
window.DxSample.OrdersChart = {
createWidgets: function(panel) {
var $mainElement = $(panel.GetMainElement());
var $chart = $mainElement.children('.dxsample-orderschart-chart');
var $range = $mainElement.children('.dxsample-orderschart-range');
$chart.dxChart({
dataSource: {
store: {
type: 'array',
data: panel.cpChartData
}
},
commonSeriesSettings: {
type: 'line'
},
seriesTemplate: { nameField: 'series' }
});
$range.dxRangeSelector({
size: { height: 120 },
margin: { left: 10 },
scale: { minorTickCount: 1 },
dataSource: {
store: {
type: 'array',
data: panel.cpChartData
}
},
chart: {
seriesTemplate: { nameField: 'series' }
},
behavior: { callSelectedRangeChanged: 'onMoving' },
onSelectedRangeChanged: function (e) {
var chart = $chart.dxChart('instance');
chart.zoomArgument(e.startValue, e.endValue);
}
});
}
};
})();