Microsoft Chart Controls を使用してカスタム ツールチップを生成しようとしています。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 は double で、#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 がそれを取得したときに既に適切にフォーマットされています。