2011-02-10 28 views
23

TagBuilder là một triển khai tốt đẹp để xây dựng các phần tử HTML. Nhưng một số yếu tố HTML có thể có một yếu tố khác (tôi gọi là trẻ em). Tôi không thể tìm thấy bất kỳ lớp học từ các lớp học Mvc.Nested TagBuilder -as TagBuilderTree-

Câu hỏi; Tôi có nên triển khai một vài lớp (TagBuilderTree và TagBuilderNode) để hỗ trợ các thẻ lồng nhau hoặc tôi đã bỏ lỡ điều gì đó không?

Trả lời

39

Bạn có thể tạo các phần tử con trong các Trình tạo thẻ riêng biệt và đặt HTML được tạo của chúng trong Trình tạo thẻ chính của cha mẹ.

Dưới đây là một ví dụ: Một <select> với một số <option> s (ví dụ de-fatted cho terseness)

TagBuilder select = new TagBuilder("select"); 

foreach (var language in languages) // never ye mind about languages 
{ 
    TagBuilder option = new TagBuilder("option"); 
    option.MergeAttribute("value", language.ID.ToString()); 

    if (language.IsCurrent) 
    { 
     option.MergeAttribute("selected", "selected"); 
    } 

    option.InnerHtml = language.Description; 
    // And now, the money-code: 
    select.InnerHtml += option.ToString(); 
} 
+0

Tôi thích triển khai TagBuilderTree và TagBuilderNode nó sẽ đóng gói các thẻ lồng nhau cho các dự án của chúng tôi nhưng tôi cố gắng tìm câu trả lời tại sao Razor không phục vụ chúng? Bởi vì nó trông giống như cần thiết cho tất cả người dùng Razor –

+0

Bạn có nghĩa là các trang Web, chứ không phải Dao cạo. Nó không cần thiết cho tất cả các nhà phát triển; bạn có thể sử dụng trình trợ giúp tĩnh thay thế. – SLaks

+0

bạn nói đúng, tôi nói về lớp System.Web.Mvc.TagBuilder. Nó không có liên quan trực tiếp với công cụ Razor. Tất cả các công cụ có thể sử dụng nó .. Tôi tự hỏi tại sao chúng ta không có TagBuilder như cây và tôi nên sử dụng TagBuilder cho các thẻ html lồng nhau. Hoặc tôi có nên triển khai các lớp TagBuilderTree và TagBuilderNode của riêng mình không? –

2

OK, tôi quyết định làm một thử nghiệm nhỏ trong cơ sở mã của riêng tôi.

tôi so hai phương pháp để tạo ra chính xác cùng HTML thức:

  1. thủ tạo ra html sử dụng một StringBuilder
  2. Sử dụng nhiều TagBuilders và làm tổ nội dung

thủ tạo ra html sử dụng một StringBuilder:

 

    var sb = new StringBuilder(); 
    sb.AppendLine("<div class='control-group'>"); 
    sb.AppendFormat(" <label class='control-label' for='{0}_{1}'>{2}</label>", propObj.ModelType, propObj.ModelProperty, propObj.LabelCaption); 
    sb.AppendLine(" <div class='controls'>"); 
    sb.AppendFormat(" <input id='{0}_{1}' name='{0}[{1}]' value='{2}' />", propObj.ModelType, propObj.ModelProperty, propObj.PropertyValue); 
    sb.AppendLine(" </div>"); 
    sb.AppendLine("</div>"); 

    return new HtmlString(sb.ToString()); 
 

U hát nhiều TagBuilder và hợp nhất nội dung:


    TagBuilder controlGroup = new TagBuilder("div"); 
    controlGroup.AddCssClass("control-group"); 

    TagBuilder label = new TagBuilder("label"); 
    label.AddCssClass("control-label"); 
    label.InnerHtml = propObj.LabelCaption; 

    TagBuilder controls = new TagBuilder("div"); 

    TagBuilder input = new TagBuilder("input"); 
    input.Attributes["id"] = propObj.ModelType + "_" + propObj.ModelProperty; 
    input.Attributes["name"] = propObj.ModelType + "[" + propObj.ModelProperty + "]"; 
    input.Attributes["value"] = propObj.PropertyValue; 

    controls.InnerHtml += input; 

    controlGroup.InnerHtml += label; 
    controlGroup.InnerHtml += controls; 

    return new HtmlString(controlGroup.ToString()); 

Với tôi, # 1 dễ đọc hơn và ngắn gọn hơn nhiều, nhưng tôi cũng có thể đánh giá cao cấu trúc của số 2.

+0

# 1 cũng là một cách có thể để tiêm script nếu bạn không cẩn thận để khử trùng, tôi chỉ muốn thêm. – Bon

+2

Tôi nghĩ rằng số 1 dễ bị lỗi hơn vì nó dựa vào việc nhập đúng HTML với vị trí chính xác của các thẻ đóng, dấu ngoặc đơn kép dấu ngoặc kép, vv Cộng với TagBuilder có nhiều intelliSense hơn. Ví dụ khi thêm một lớp CSS, trình xây dựng chuỗi sẽ không cung cấp bất kỳ intellisense nào để thêm một lớp trong khi TagBulder có phương thức AddCSSClass có intellisense. Ngoài ra tôi tìm thấy # 2 dễ đọc hơn nhiều. Tất cả các trình giữ chỗ trong phương pháp # 1 làm cho mọi thứ ít rõ ràng hơn. –

-2

Sự cố mà tôi có với TagBuilder để tạo thẻ là có vẻ rất không thể bảo trì. Mặt khác, AppendFormat của StringBuilder không chỉ làm cho mã duy trì được, mà còn chạy với hiệu quả tốt.

Tôi đã cải thiện một chút so với phương pháp # 1 của MattSlay. Tôi chỉ sử dụng một cuộc gọi đến phương thức AppendFormat của StringBuilder và sử dụng ký tự chuỗi C# để xác định định dạng. Kết quả là định dạng kết thúc lên trông giống hệt như kết quả mong muốn và chạy với hiệu quả.

var sb = new StringBuilder(); 
    sb.AppendFormat(
    @"<div class='control-group'> 
      <label class='control-label' for='{0}_{1}'>{2}</label> 
      <div class='controls'> 
      <input id='{0}_{1}' name='{0}[{1}]' value='{3}' /> 
      </div> 
     </div>", 
     propObj.ModelType, 
     propObj.ModelProperty, 
     propObj.LabelCaption, 
     propObj.PropertyValue); 

    return new HtmlString(sb.ToString()); 

Hy vọng điều này sẽ hữu ích!

+0

đó là câu hỏi cũ. đề xuất của bạn thay đổi các lớp học như 'nhãn kiểm soát' là gì. tất cả đều được mã hóa cứng như các trang aspas (không phải asp.net). tôi luôn nghĩ rằng sự bảo trì quan trọng hơn mã. –

+0

Điều này có vẻ như không hoạt động vì giá trị của đầu vào sẽ được đặt thành chú thích của nhãn. Lưu ý rằng phiên bản của MattSlay sử dụng hai danh sách tham số khác nhau. Bạn có thể loại bỏ các bản sao của ModelType và ModelProperty và truy cập PropertyValue dưới dạng {3} – Robert

+0

@Robert Tôi chỉ đơn giản là cố gắng chứng minh rằng bạn có thể nhận được hiệu quả của TagBuilder và khả năng bảo trì mã bằng cách sử dụng một cuộc gọi đến AppendFormat thay vì nhiều cuộc gọi để AppendFormat như MattSlay. Ngoài một cuộc gọi duy nhất đến AppendFormat, hãy chú ý cách chuỗi ký tự của C# cho phép bạn xác định chuỗi được định dạng với khoảng trắng để có thể đọc được. Một lần nữa, tôi chỉ cố gắng cải thiện phương pháp của MattSlay :) –