Я пытаюсь сгенерировать пользовательскую подсказку, используя элементы управления Microsoft Chart. 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: Неожиданный токен 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 -OR- "\ n", вы не сможете редактировать "#VALX" позже из-за оценки во время выполнения. Таким образом, вы должны использовать экранированный символ новой строки при добавлении значения X, чтобы при получении #VALX оно уже было правильно отформатировано.
Спасибо