5

私はこれが一種の強迫観念であることを知っていますが、TagBuilderクラスが呼び出すときにHTMLタグの属性をレンダリングする順序を制御する方法はありますToString()か?

つまり、そのように

var tb = new TagBuilder("meta");            
tb.Attributes.Add("http-equiv", "Content-Type");            
tb.Attributes.Add("content", "text/html; charset=utf-8");    
tb.ToString(TagRenderMode.SelfClosing)

戻ります

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

いいえ

<meta content="text/html; charset=utf-8" http-equiv="Content-Type" />

属性を追加する順序を変更しても変更されません。アルファベット順にレンダリングされているようです

4

3 に答える 3

3

TagBuilderを継承し、ToStringメソッドをオーバーライドするこのクラスを使用して、属性からSortedDictionaryを構築し、そのディクショナリを使用してレンダリングしてみてください。

    public class MyTagBuilder : TagBuilder
    {
        //required to inherit from TagBuilder
        public MyTagBuilder(string tagName) : base(tagName){}

        //new hides the original ToString(TagRenderMode renderMode) 
        //The only changes in this method is that all calls to GetAttributesString
        //have been changed to GetMyAttributesString 
        public new string ToString(TagRenderMode renderMode)
        {
            switch (renderMode)
            {
                case TagRenderMode.StartTag:
                    return string.Format(CultureInfo.InvariantCulture, "<{0}{1}>", new object[] { this.TagName, this.GetMyAttributesString() });

                case TagRenderMode.EndTag:
                    return string.Format(CultureInfo.InvariantCulture, "</{0}>", new object[] { this.TagName });

                case TagRenderMode.SelfClosing:
                    return string.Format(CultureInfo.InvariantCulture, "<{0}{1} />", new object[] { this.TagName, this.GetMyAttributesString() });
            }
            return string.Format(CultureInfo.InvariantCulture, "<{0}{1}>{2}</{0}>", new object[] { this.TagName, this.GetMyAttributesString(), this.InnerHtml });
        }

        //Implement GetMyAttributesString where the Attributes are changed to a SortedDictionary
        private string GetMyAttributesString()
        {
            var builder = new StringBuilder();
            var myDictionary = new SortedDictionary<string, string>();     //new
            foreach (KeyValuePair<string, string> pair in this.Attributes) //new
            {                                                              //new
                myDictionary.Add(pair.Key, pair.Value);                    //new
            }                                                              //new 
            //foreach (KeyValuePair<string, string> pair in this.Attributes)
            foreach (KeyValuePair<string, string> pair in myDictionary)    //changed
            {
                string key = pair.Key;
                if (!string.Equals(key, "id", StringComparison.Ordinal) || !string.IsNullOrEmpty(pair.Value))
                {
                    string str2 = HttpUtility.HtmlAttributeEncode(pair.Value);
                    builder.AppendFormat(CultureInfo.InvariantCulture, " {0}=\"{1}\"", new object[] { key, str2 });
                }
            }
            return builder.ToString();
        }
    }
于 2010-08-12T08:03:43.613 に答える
1

Reflector で逆アセンブルTagBuilder.ToString()しました。これが重要なコードです。

foreach (KeyValuePair<string, string> pair in this.Attributes)
{
    string key = pair.Key;
    string str2 = HttpUtility.HtmlAttributeEncode(pair.Value);
    builder.AppendFormat(CultureInfo.InvariantCulture, " {0}=\"{1}\"", new object[] { key, str2 });
}

MSDNによると、「アイテムが返される順序は定義されていません」と列挙するthis.Attributesと、インターフェイスではありません。IDictionary<string,string>

于 2010-08-12T07:24:20.087 に答える
0

並べ替えの動作を変更するためにそのすべてのコードをオーバーライドしたくなかったので、代わりに属性プロパティをリフレクションを使用して通常の並べ替えられていない辞書に変更しました

private class MyTagBuilder: TagBuilder
{
    private static readonly MethodInfo tagBuilderAttrSetMethod = typeof(TagBuilder).GetProperty(nameof(Attributes)).SetMethod;

    public MyTagBuilder(string tagName) : base(tagName)
    {
        // TagBuilder internally uses SortedDictionary, render attributes according to the order they are added instead
        tagBuilderAttrSetMethod.Invoke(this, new object[] { new Dictionary<string, string>() });
    }
}
于 2018-01-12T15:49:38.460 に答える