This example demonstrates how to save the custom data related to a dashboard to the dashboard XML definition and how to load this data later. In this example, the standard ‘Save’ menu item removed from the Web Dashboard menu. A new ‘Save As’ menu item allows end-users to add a custom comment appended to the dashboard XML definition. Moreover, the current dashboard state and modified date is added to the XML definition.
You can load dashboards containing custom data using the ‘Open’ menu item. A comment and modified date form the selected dashboard is displayed within the form at the top of the web page. The loaded dashboard state is applied to the dashboard using a client-side API.
function onBeforeRender(sender, e) {
// Gets an underlying part of the ASPxClientDashboard control and removes the 'Save' item from a standard menu.
var innerControl = sender.GetDashboardControl();
var toolbox = innerControl.findExtension("toolbox");
toolbox.removeMenuItem("save");
// Specifies which actions will be performed on clicking a custom menu item (which is added below using addMenuItem).
var clickAction = function () {
// Creates a popup that will display a text box allowing end-users to specify a comment to be appended to the dashboard XML file.
var popup = $("#popupContainer").dxPopup({
title: "Save As",
visible: true,
width: 600,
height: 200,
onShown: function () {
$("#textBoxContainer").dxTextBox({
placeholder: 'Enter any comment...',
showClearButton: true
});
},
toolbarItems: [{
toolbar: "bottom",
widget: "dxButton",
location: "after",
options: {
text: "Save",
onClick: saveButtonAction
}
}, {
toolbar: "bottom",
widget: "dxButton",
location: "after",
options: {
text: "Cancel",
onClick: cancelButtonAction
}
}]
});
popup.show();
}
// Passes the custom data (a comment, a modified date and a current dashboard state) to the server side.
// On the server side, the CustomDataCallback event is used to obtain and parse these values.
var saveButtonAction = function () {
var params = {
dashboardJson: JSON.stringify(innerControl.dashboard().getJSON()),
dateModified: new Date(Date.now()).toLocaleString(),
comment: $("#textBoxContainer").dxTextBox("instance").option("text"),
dashboardState: webDashboard.GetDashboardState()
}
sender.PerformDataCallback(JSON.stringify(params));
$("#popupContainer").dxPopup("instance").hide();
toolbox.menuVisible(false);
}
var cancelButtonAction = function () {
$("#popupContainer").dxPopup("instance").hide();
toolbox.menuVisible(false);
}
// Adds a menu item that will be used to perform a custom saving routine.
toolbox.addMenuItem(new DevExpress.Dashboard.DashboardMenuItem("save-as-item", "Save As", 108, 0, clickAction));
}
function onDashboardChanged(sender, e) {
// Displays the custom data contained in the UserData element.
// Note that CustomJSProperties event is used to pass data from the server to client side.
var form = $("#formContainer").dxForm({
formData: {
modified: webDashboard.cpDateModified,
comment: webDashboard.cpComment
},
items: ["modified", "comment"],
readOnly: true
});
// Applies a dashboard state obtained from the UserData element.
if(webDashboard.cpDashboardState !=null)
webDashboard.SetDashboardState(webDashboard.cpDashboardState);
}
Imports DevExpress.DashboardCommon
Imports DevExpress.DashboardWeb
Imports DevExpress.Web
Imports System
Imports System.Web.Script.Serialization
Imports System.Xml.Linq
Namespace ASPxDashboard_UserData
Partial Public Class [Default]
Inherits System.Web.UI.Page
Private dashboardStorage As New DashboardFileStorage("~/App_Data/Dashboards")
Private dateModified As String
Private comment As String
Private dashboardState As String
Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
' Sets a dashboard storage and loads the specified dashboard from this storage.
ASPxDashboard1.SetDashboardStorage(dashboardStorage)
ASPxDashboard1.InitialDashboardId = "dashboard2"
End Sub
' Handles the CustomDataCallback event that is used to obtain custom data from the client side.
' On the client side, the PerformDataCallback method is called to pass data and generate CustomDataCallback.
Protected Sub ASPxDashboard1_CustomDataCallback(ByVal sender As Object, ByVal e As CustomDataCallbackEventArgs)
Dim serializer As New JavaScriptSerializer()
Dim json As Object = serializer.Deserialize(Of Object)(e.Parameter)
Dim dashboardJson As String = json("dashboardJson").ToString()
Dim dateModified As String = json("dateModified").ToString()
Dim comment As String = json("comment").ToString()
Dim dashboardState As String = json("dashboardState").ToString()
Dim dashboardDocument As XDocument = DashboardJsonConverter.JsonToXml(dashboardJson)
Dim dashboard As New Dashboard()
dashboard.LoadFromXDocument(dashboardDocument)
Dim userData As New XElement("Root", New XElement("DateModified", dateModified), New XElement("Comment", comment), New XElement("DashboardState", dashboardState))
dashboard.UserData = userData
e.Result = DirectCast(dashboardStorage, IEditableDashboardStorage).AddDashboard(dashboard.SaveToXDocument(), dashboard.Title.Text)
End Sub
' Creates a set of client side properties used to pass custom data loaded from UserData to the client side.
Protected Sub ASPxDashboard1_CustomJSProperties(ByVal sender As Object, ByVal e As CustomJSPropertiesEventArgs)
e.Properties.Add("cpDateModified", dateModified)
e.Properties.Add("cpComment", comment)
e.Properties.Add("cpDashboardState", dashboardState)
End Sub
' Obtains the custom data from the UserData element when loading a dashboard.
Protected Sub ASPxDashboard1_DashboardLoading(ByVal sender As Object, ByVal e As DashboardLoadingWebEventArgs)
Dim dashboard As New Dashboard()
dashboard.LoadFromXDocument(e.DashboardXml)
Dim data As XElement = dashboard.UserData
If data IsNot Nothing Then
dateModified = data.Element("DateModified").Value
comment = data.Element("Comment").Value
dashboardState = data.Element("DashboardState").Value
End If
End Sub
End Class
End Namespace
<%@ Page Language="vb" AutoEventWireup="true" CodeBehind="Default.aspx.vb" Inherits="ASPxDashboard_UserData.Default" %>
<%@ Register Assembly="DevExpress.Dashboard.v17.1.Web, Version=17.1.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a"
Namespace="DevExpress.DashboardWeb" TagPrefix="dx" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<script type="text/javascript" src="<%=Page.ResolveClientUrl("~/Scripts/UserData.js")%>"></script>
<body>
<form id="form1" runat="server">
<div id="popupContainer">
<div id="textBoxContainer"></div>
</div>
<div id="formContainer" style="margin: 50px 80px 0 80px;"></div>
<div style="margin-top:50px;">
<dx:ASPxDashboard ID="ASPxDashboard1" runat="server"
ClientInstanceName="webDashboard"
ClientSideEvents-BeforeRender="onBeforeRender"
ClientSideEvents-DashboardChanged="onDashboardChanged"
OnCustomDataCallback="ASPxDashboard1_CustomDataCallback"
OnDashboardLoading="ASPxDashboard1_DashboardLoading"
OnCustomJSProperties="ASPxDashboard1_CustomJSProperties"
Height="800px" Width="100%">
</dx:ASPxDashboard>
</div>
</form>
</body>
</html>
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="ASPxDashboard_UserData.Default" %>
<%@ Register Assembly="DevExpress.Dashboard.v17.1.Web, Version=17.1.3.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a"
Namespace="DevExpress.DashboardWeb" TagPrefix="dx" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<script type="text/javascript" src="<%= Page.ResolveClientUrl("~/Scripts/UserData.js") %>"></script>
<body>
<form id="form1" runat="server">
<div id="popupContainer">
<div id="textBoxContainer"></div>
</div>
<div id="formContainer" style="margin: 50px 80px 0 80px;"></div>
<div style="margin-top:50px;">
<dx:ASPxDashboard ID="ASPxDashboard1" runat="server"
ClientInstanceName="webDashboard"
ClientSideEvents-BeforeRender="onBeforeRender"
ClientSideEvents-DashboardChanged="onDashboardChanged"
OnCustomDataCallback="ASPxDashboard1_CustomDataCallback"
OnDashboardLoading="ASPxDashboard1_DashboardLoading"
OnCustomJSProperties="ASPxDashboard1_CustomJSProperties"
Height="800px" Width="100%">
</dx:ASPxDashboard>
</div>
</form>
</body>
</html>
using DevExpress.DashboardCommon;
using DevExpress.DashboardWeb;
using DevExpress.Web;
using System;
using System.Web.Script.Serialization;
using System.Xml.Linq;
namespace ASPxDashboard_UserData {
public partial class Default : System.Web.UI.Page {
DashboardFileStorage dashboardStorage = new DashboardFileStorage(@"~/App_Data/Dashboards");
string dateModified;
string comment;
string dashboardState;
protected void Page_Load(object sender, EventArgs e) {
// Sets a dashboard storage and loads the specified dashboard from this storage.
ASPxDashboard1.SetDashboardStorage(dashboardStorage);
ASPxDashboard1.InitialDashboardId = "dashboard2";
}
// Handles the CustomDataCallback event that is used to obtain custom data from the client side.
// On the client side, the PerformDataCallback method is called to pass data and generate CustomDataCallback.
protected void ASPxDashboard1_CustomDataCallback(object sender, CustomDataCallbackEventArgs e) {
JavaScriptSerializer serializer = new JavaScriptSerializer();
dynamic json = serializer.Deserialize<dynamic>(e.Parameter);
string dashboardJson = json["dashboardJson"].ToString();
string dateModified = json["dateModified"].ToString();
string comment = json["comment"].ToString();
string dashboardState = json["dashboardState"].ToString();
XDocument dashboardDocument = DashboardJsonConverter.JsonToXml(dashboardJson);
Dashboard dashboard = new Dashboard();
dashboard.LoadFromXDocument(dashboardDocument);
XElement userData = new XElement("Root", new XElement("DateModified", dateModified), new XElement("Comment", comment), new XElement("DashboardState", dashboardState));
dashboard.UserData = userData;
e.Result = ((IEditableDashboardStorage)dashboardStorage).AddDashboard(dashboard.SaveToXDocument(), dashboard.Title.Text);
}
// Creates a set of client side properties used to pass custom data loaded from UserData to the client side.
protected void ASPxDashboard1_CustomJSProperties(object sender, CustomJSPropertiesEventArgs e) {
e.Properties.Add("cpDateModified", dateModified);
e.Properties.Add("cpComment", comment);
e.Properties.Add("cpDashboardState", dashboardState);
}
// Obtains the custom data from the UserData element when loading a dashboard.
protected void ASPxDashboard1_DashboardLoading(object sender, DashboardLoadingWebEventArgs e) {
Dashboard dashboard = new Dashboard();
dashboard.LoadFromXDocument(e.DashboardXml);
XElement data = dashboard.UserData;
if (data != null) {
dateModified = data.Element("DateModified").Value;
comment = data.Element("Comment").Value;
dashboardState = data.Element("DashboardState").Value;
}
}
}
}
function onBeforeRender(sender, e) {
// Gets an underlying part of the ASPxClientDashboard control and removes the 'Save' item from a standard menu.
var innerControl = sender.GetDashboardControl();
var toolbox = innerControl.findExtension("toolbox");
toolbox.removeMenuItem("save");
// Specifies which actions will be performed on clicking a custom menu item (which is added below using addMenuItem).
var clickAction = function () {
// Creates a popup that will display a text box allowing end-users to specify a comment to be appended to the dashboard XML file.
var popup = $("#popupContainer").dxPopup({
title: "Save As",
visible: true,
width: 600,
height: 200,
onShown: function () {
$("#textBoxContainer").dxTextBox({
placeholder: 'Enter any comment...',
showClearButton: true
});
},
toolbarItems: [{
toolbar: "bottom",
widget: "dxButton",
location: "after",
options: {
text: "Save",
onClick: saveButtonAction
}
}, {
toolbar: "bottom",
widget: "dxButton",
location: "after",
options: {
text: "Cancel",
onClick: cancelButtonAction
}
}]
});
popup.show();
}
// Passes the custom data (a comment, a modified date and a current dashboard state) to the server side.
// On the server side, the CustomDataCallback event is used to obtain and parse these values.
var saveButtonAction = function () {
var params = {
dashboardJson: JSON.stringify(innerControl.dashboard().getJSON()),
dateModified: new Date(Date.now()).toLocaleString(),
comment: $("#textBoxContainer").dxTextBox("instance").option("text"),
dashboardState: webDashboard.GetDashboardState()
}
sender.PerformDataCallback(JSON.stringify(params));
$("#popupContainer").dxPopup("instance").hide();
toolbox.menuVisible(false);
}
var cancelButtonAction = function () {
$("#popupContainer").dxPopup("instance").hide();
toolbox.menuVisible(false);
}
// Adds a menu item that will be used to perform a custom saving routine.
toolbox.addMenuItem(new DevExpress.Dashboard.DashboardMenuItem("save-as-item", "Save As", 108, 0, clickAction));
}
function onDashboardChanged(sender, e) {
// Displays the custom data contained in the UserData element.
// Note that CustomJSProperties event is used to pass data from the server to client side.
var form = $("#formContainer").dxForm({
formData: {
modified: webDashboard.cpDateModified,
comment: webDashboard.cpComment
},
items: ["modified", "comment"],
readOnly: true
});
// Applies a dashboard state obtained from the UserData element.
if(webDashboard.cpDashboardState !=null)
webDashboard.SetDashboardState(webDashboard.cpDashboardState);
}