我正在尝试使用 Microsoft 图表控件生成自定义工具提示。Microsoft Chart Controls 支持使用关键字的功能,这有助于自动化您希望显示的数据。
例如,
string toolTip = string.Format("<div> {0}: {1} {3} ({2}) </div>", seriesName, "#VALY", "#VALX", "<br>");
series.MapAreaAttributes = "onfocus=\"if(this.blur)this.blur();\" onmouseover=\"DisplayTooltip('" + JavaScriptStringLiteral(toolTip) + "');\" onmouseout=\"DisplayTooltip('');\"";
在上面的代码中,“#VALY”和“#VALX”是关键字。在运行时,这些关键字将替换为实际值。在我的场景中,#VALY 是双精度,#VALX 是日期时间。
观察:
现在,如果我使用数据系列的工具提示属性,这将非常有效。不幸的是,Firefox 和Opera不(容易)支持多行工具提示。我试图通过使用自定义工具提示来非法使用此功能。
因此,我有 onmouseover 和 onmouseout 代码——这是负责工具提示的 JavaScript 代码。
问题是当 #VALX 被评估时,它包含非法的 JavaScript 字符。这会导致错误消息“Uncaught SyntaxError: Unexpected token ILLEGAL”
请注意,我已经使用 JavaScriptStringLiteral 方法包装了工具提示。这是效用函数:
private static readonly Regex scriptTagRegex = new Regex("script", RegexOptions.IgnoreCase | RegexOptions.Multiline);
/// <summary>
/// Processes the provided string, creating a quoted JavaScript string literal.
/// </summary>
/// <param name="str">The string to process</param>
/// <returns>A string containing a quoted JavaScript string literal</returns>
public static string JavaScriptStringLiteral(string str)
{
var sb = new StringBuilder();
sb.Append("\"");
foreach (char c in str)
{
switch (c)
{
case '\"':
sb.Append("\\\"");
break;
case '\\':
sb.Append("\\\\");
break;
case '\b':
sb.Append("\\b");
break;
case '\f':
sb.Append("\\f");
break;
case '\n':
sb.Append("\\n");
break;
case '\r':
sb.Append("\\r");
break;
case '\t':
sb.Append("\\t");
break;
default:
int i = (int)c;
if (i < 32 || i > 127)
{
sb.AppendFormat("\\u{0:X04}", i);
}
else
{
sb.Append(c);
}
break;
}
}
sb.Append("\"");
// If a JavaScript tag contains "</script>", then it terminates a
// script block. Start by replacing each 's'/'S' with an escape
// sequence so it doesn't trigger this.
return scriptTagRegex.Replace(
sb.ToString(),
m => (m.Value[0] == 's' ? "\\u0073" : "\\u0053") + m.Value.Substring(1));
}
如果 #VALX 没有在运行时进行评估,我相信这个实用方法可以解决我的问题。但是,因此,实用程序函数将“#VALX”评估为字符串文字。然后,在过滤掉任何非法字符后,评估#VALX 并将非法字符放入我的 JavaScript。
有没有办法防止这个问题?相当于 C# 中路径的“@”字符的东西?
我想出了解决方案,它很愚蠢。
foreach (HistoricalDataValue value in data)
{
series.Points.AddXY(string.Format("{0:d}{1}{0:T}", value.TimeStamp, "\\n"), value.AttributeValue);
}
请注意,这表示“\\n”。这曾经是说Environment.NewLine,但这不起作用。此外,如果您使用 Environment.NewLine -或- "\n",则由于运行时评估,您不能稍后编辑 "#VALX"。因此,您必须在添加 X 值时使用转义换行符,以便当 #VALX 获取它时,它已经正确格式化。