TagBuilder.MergeAttributes не работает должным образом
Я пытаюсь создать HtmlHelper и мне нужно разрешить пользователям добавлять свои собственные атрибуты в тег html.
Я попытался сделать это с помощью класса TagBuilder, но, похоже, вместо объединения атрибутов он просто заменяет их.
Это то, что я сделал в C#:
public static MvcHtmlString List(HtmlHelper helper, object htmlAttributes)
{
var attributes = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
var tag = new TagBuilder("div");
tag.AddCssClass("myClass");
tag.MergeAttributes(attributes, false);
// tag class property has value "myClass", not "myClass testClass"
return new MvcHtmlString("<div>");
}
Это мой взгляд:
@Html.List(new { @class = "testClass" })
Что я делаю неправильно?
3 ответа
TagBuilder.MergeAttributes
метод не работает так, как вы ожидаете. Это точный код этого метода:
public void MergeAttributes<TKey, TValue>(IDictionary<TKey, TValue> attributes, bool replaceExisting)
{
if (attributes != null)
{
foreach (var entry in attributes)
{
string key = Convert.ToString(entry.Key, CultureInfo.InvariantCulture);
string value = Convert.ToString(entry.Value, CultureInfo.InvariantCulture);
MergeAttribute(key, value, replaceExisting);
}
}
}
public void MergeAttribute(string key, string value, bool replaceExisting)
{
if (String.IsNullOrEmpty(key))
{
throw new ArgumentException(CommonResources.Argument_Cannot_Be_Null_Or_Empty, "key");
}
if (replaceExisting || !Attributes.ContainsKey(key))
{
Attributes[key] = value;
}
}
Как видите, он добавляет только новые атрибуты в коллекцию (если replaceExisting
установлен в true, он также заменяет те, которые уже есть в коллекции). Он не выполняет и атрибуты логики слияния значений. Если вы хотите объединить значения, вам нужно сделать это самостоятельно:
public static MvcHtmlString List(this HtmlHelperhelper, object htmlAttributes)
{
var attributes = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);
if (attributes.ContainsKey("class"))
attributes["class"] = "myclass " + attributes["class"];
else
attributes.Add("class", "myClass");
var tag = new TagBuilder("div");
tag.MergeAttributes(attributes, false);
return new MvcHtmlString(tag.ToString(TagRenderMode.Normal));
}
MergeAttributes переопределяет атрибуты, уже имеющиеся в теге, AddCssClass добавляет имя в значение класса.
Так что просто включите его, и он будет работать;
tag.MergeAttributes(attributes, false);
tag.AddCssClass("myClass");
AddCssClass добавится к именам классов, слитых над ним.
Мне нужно было объединить другие атрибуты (кроме просто класса), поэтому AddCssClass() было недостаточно. Я написал метод расширения, чтобы сделать то, что, как я думал, должен делать MergeAttributes:
public static class TagBuilderExtensions
{
public static void TrueMergeAttributes(this TagBuilder tagBuilder, IDictionary<string, object> attributes)
{
foreach (var attribute in attributes)
{
string currentValue;
string newValue = attribute.Value.ToString();
if (tagBuilder.Attributes.TryGetValue(attribute.Key, out currentValue))
{
newValue = currentValue + " " + newValue;
}
tagBuilder.Attributes[attribute.Key] = newValue;
}
}
}