Hình ảnh hành động MVC3 Razor


119

Cách tốt nhất để thay thế liên kết bằng hình ảnh bằng Razor trong MVC3 là gì. Tôi chỉ đơn giản làm điều này vào lúc này:

<a href="@Url.Action("Edit", new { id=MyId })"><img src="../../Content/Images/Image.bmp", alt="Edit" /></a> 

Có cách nào tốt hơn?


15
Không liên quan trực tiếp, nhưng tôi thực sự khuyên bạn nên sử dụng tệp PNG hoặc JPG (tùy thuộc vào nội dung hình ảnh) thay vì tệp BMP. Và giống như @jgauffin đã đề xuất, hãy thử sử dụng các đường dẫn tương đối của ứng dụng ( ~/Content). Đường dẫn ../../Contentcó thể không có giá trị từ tuyến đường khác nhau (ví dụ /, /Home, /Home/Index).
Lucas

Cảm ơn Lucas. Tôi sử dụng png nhưng lời khuyên cho việc sử dụng URL.Content là những gì tôi đang tìm kiếm. bình chọn :)
davy

Câu trả lời:


217

Bạn có thể tạo một phương thức mở rộng cho HtmlHelper để đơn giản hóa mã trong tệp CSHTML của mình. Bạn có thể thay thế các thẻ của mình bằng một phương pháp như sau:

// Sample usage in CSHTML
@Html.ActionImage("Edit", new { id = MyId }, "~/Content/Images/Image.bmp", "Edit")

Đây là một phương pháp mở rộng mẫu cho đoạn mã trên:

// Extension method
public static MvcHtmlString ActionImage(this HtmlHelper html, string action, object routeValues, string imagePath, string alt)
{
    var url = new UrlHelper(html.ViewContext.RequestContext);

    // build the <img> tag
    var imgBuilder = new TagBuilder("img");
    imgBuilder.MergeAttribute("src", url.Content(imagePath));
    imgBuilder.MergeAttribute("alt", alt);
    string imgHtml = imgBuilder.ToString(TagRenderMode.SelfClosing);

    // build the <a> tag
    var anchorBuilder = new TagBuilder("a");
    anchorBuilder.MergeAttribute("href", url.Action(action, routeValues));
    anchorBuilder.InnerHtml = imgHtml; // include the <img> tag inside
    string anchorHtml = anchorBuilder.ToString(TagRenderMode.Normal);

    return MvcHtmlString.Create(anchorHtml);
}

5
Đoạn trích xuất sắc. Bất cứ ai muốn sử dụng điều này với T4MVC chỉ có thay đổi loại của routeValuesđể ActionResultvà sau đó trong url.Actionsự thay đổi chức năng routeValuesđểrouteValues.GetRouteValueDictionary()
JConstantine

12
@Kasper Skov: Đặt phương thức trong một lớp tĩnh, sau đó tham chiếu không gian tên của lớp đó trong Web.config trong /configuration/system.web/pages/namespacesphần tử.
Umar Farooq Khawaja

4
Tuyệt vời !, thay vì alt, tôi chấp nhận một đối tượng để nhận các thuộc tính html bằng cách sử dụng một đối tượng ẩn danh sau đó var attributes = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);và cuối cùngforeach (var attr in attributes){ imgBuilder.MergeAttribute(attr.Key, attr.Value.ToString());}
guzart

7
Tôi không thể làm cho điều này hoạt động cho đến khi tôi nhận ra rằng vì tôi đang sử dụng Khu vực nên tham chiếu đến không gian tên của lớp (như được chỉ ra bởi Umar) cần được thêm vào TẤT CẢ các tệp web.config trong thư mục Chế độ xem cho tất cả các Khu vực cũng như /Viewsthư mục cấp cao nhất
Mark_Gibson

2
Nếu bạn chỉ cần điều này trong một trang duy nhất, thay vì thay đổi các tập tin Web.config, bạn có thể thêm một tuyên bố @using trong .cshtml và tham khảo các namespace
JML

64

Bạn có thể sử dụng Url.Contentcái nào phù hợp với tất cả các liên kết vì nó dịch dấu ngã ~sang tiếng tiểu gốc.

<a href="@Url.Action("Edit", new { id=MyId })">
    <img src="@Url.Content("~/Content/Images/Image.bmp")", alt="Edit" />
</a>

3
Điều này hoạt động tốt trong MVC3. Cảm ơn bạn! <a href="@Url.Action("Index","Home")"><img src="@Url.Content("~/Content/images/myimage.gif")" alt="Home" /></a>
rk1962

24

Dựa trên câu trả lời của Lucas ở trên, đây là một quá tải lấy tên bộ điều khiển làm tham số, tương tự như ActionLink. Sử dụng quá tải này khi hình ảnh của bạn liên kết với một Hành động trong một bộ điều khiển khác.

// Extension method
public static MvcHtmlString ActionImage(this HtmlHelper html, string action, string controllerName, object routeValues, string imagePath, string alt)
{
    var url = new UrlHelper(html.ViewContext.RequestContext);

    // build the <img> tag
    var imgBuilder = new TagBuilder("img");
    imgBuilder.MergeAttribute("src", url.Content(imagePath));
    imgBuilder.MergeAttribute("alt", alt);
    string imgHtml = imgBuilder.ToString(TagRenderMode.SelfClosing);

    // build the <a> tag
    var anchorBuilder = new TagBuilder("a");

    anchorBuilder.MergeAttribute("href", url.Action(action, controllerName, routeValues));
    anchorBuilder.InnerHtml = imgHtml; // include the <img> tag inside
    string anchorHtml = anchorBuilder.ToString(TagRenderMode.Normal);

    return MvcHtmlString.Create(anchorHtml);
}

1
không có bình luận nào về sự bổ sung của bạn ở đây ... tôi nói rằng sửa đổi tốt cho mã đã cho. +1 từ tôi.
Zack Jannsen

11

Chà, bạn có thể sử dụng giải pháp @Lucas, nhưng cũng có một cách khác.

 @Html.ActionLink("Update", "Update", *Your object value*, new { @class = "imgLink"})

Bây giờ, hãy thêm lớp này vào tệp CSS hoặc trong trang của bạn:

.imgLink
{
  background: url(YourImage.png) no-repeat;
}

Với lớp đó, bất kỳ liên kết nào cũng sẽ có hình ảnh mong muốn của bạn.


2
@KasperSkov Tôi đã quên vấn đề nhỏ này. Vì một số lý do, phần ghi đè cụ thể này của trình trợ giúp actionLink, không hoạt động với ví dụ trên. Bạn phải ControllerNamethực hiện hành động của mình. Như thế này:@Html.ActionLink("Update", "Update", "*Your Controller*",*object values*, new {@class = "imgLink"})
AdrianoRR

3

Điều này hóa ra là một chủ đề rất hữu ích.

Đối với những người bị dị ứng với dấu ngoặc nhọn, đây là phiên bản VB.NET của câu trả lời của Lucas 'và Crake:

Public Module ActionImage
    <System.Runtime.CompilerServices.Extension()>
    Function ActionImage(html As HtmlHelper, Action As String, RouteValues As Object, ImagePath As String, AltText As String) As MvcHtmlString

        Dim url = New UrlHelper(html.ViewContext.RequestContext)

        Dim imgHtml As String
        'Build the <img> tag
        Dim imgBuilder = New TagBuilder("img")
        With imgBuilder
            .MergeAttribute("src", url.Content(ImagePath))
            .MergeAttribute("alt", AltText)
            imgHtml = .ToString(TagRenderMode.Normal)
        End With

        Dim aHtml As String
        'Build the <a> tag
        Dim aBuilder = New TagBuilder("a")
        With aBuilder
            .MergeAttribute("href", url.Action(Action, RouteValues))
            .InnerHtml = imgHtml 'Include the <img> tag inside
            aHtml = aBuilder.ToString(TagRenderMode.Normal)
        End With

        Return MvcHtmlString.Create(aHtml)

    End Function

    <Extension()>
    Function ActionImage(html As HtmlHelper, Action As String, Controller As String, RouteValues As Object, ImagePath As String, AltText As String) As MvcHtmlString

        Dim url = New UrlHelper(html.ViewContext.RequestContext)

        Dim imgHtml As String
        'Build the <img> tag
        Dim imgBuilder = New TagBuilder("img")
        With imgBuilder
            .MergeAttribute("src", url.Content(ImagePath))
            .MergeAttribute("alt", AltText)
            imgHtml = .ToString(TagRenderMode.Normal)
        End With

        Dim aHtml As String
        'Build the <a> tag
        Dim aBuilder = New TagBuilder("a")
        With aBuilder
            .MergeAttribute("href", url.Action(Action, Controller, RouteValues))
            .InnerHtml = imgHtml 'Include the <img> tag inside
            aHtml = aBuilder.ToString(TagRenderMode.Normal)
        End With

        Return MvcHtmlString.Create(aHtml)

    End Function

End Module

1

Phương thức mở rộng này cũng hoạt động (được đặt trong một lớp tĩnh công khai):

    public static MvcHtmlString ImageActionLink(this AjaxHelper helper, string imageUrl, string altText, string actionName, object routeValues, AjaxOptions ajaxOptions)
    {
        var builder = new TagBuilder("img");
        builder.MergeAttribute("src", imageUrl);
        builder.MergeAttribute("alt", altText);
        var link = helper.ActionLink("[replaceme]", actionName, routeValues, ajaxOptions);
        return new MvcHtmlString( link.ToHtmlString().Replace("[replaceme]", builder.ToString(TagRenderMode.SelfClosing)) );
    }

1

Để thêm vào tất cả tác phẩm Tuyệt vời do Luke bắt đầu, tôi sẽ đăng một tác phẩm nữa lấy giá trị lớp css và coi class và alt là các tham số tùy chọn (hợp lệ theo ASP.NET 3.5+). Điều này sẽ cho phép nhiều chức năng hơn nhưng giảm số lượng các phương thức quá tải cần thiết.

// Extension method
    public static MvcHtmlString ActionImage(this HtmlHelper html, string action,
        string controllerName, object routeValues, string imagePath, string alt = null, string cssClass = null)
    {
        var url = new UrlHelper(html.ViewContext.RequestContext);

        // build the <img> tag
        var imgBuilder = new TagBuilder("img");
        imgBuilder.MergeAttribute("src", url.Content(imagePath));
        if(alt != null)
            imgBuilder.MergeAttribute("alt", alt);
        if (cssClass != null)
            imgBuilder.MergeAttribute("class", cssClass);

        string imgHtml = imgBuilder.ToString(TagRenderMode.SelfClosing);

        // build the <a> tag
        var anchorBuilder = new TagBuilder("a");

        anchorBuilder.MergeAttribute("href", url.Action(action, controllerName, routeValues));
        anchorBuilder.InnerHtml = imgHtml; // include the <img> tag inside
        string anchorHtml = anchorBuilder.ToString(TagRenderMode.Normal);

        return MvcHtmlString.Create(anchorHtml);
    }

Ngoài ra, đối với bất kỳ ai mới sử dụng MVC, gợi ý hữu ích - giá trị của routeValue nên là @ RouteTable.Routes ["Home"] hoặc bất kỳ id "route" nào của bạn trong teh RouteTable.
Zack Jannsen

1

sửa đổi slide đã thay đổi Helper

     public static IHtmlString ActionImageLink(this HtmlHelper html, string action, object routeValues, string styleClass, string alt)
    {
        var url = new UrlHelper(html.ViewContext.RequestContext);
        var anchorBuilder = new TagBuilder("a");
        anchorBuilder.MergeAttribute("href", url.Action(action, routeValues));
        anchorBuilder.AddCssClass(styleClass);
        string anchorHtml = anchorBuilder.ToString(TagRenderMode.Normal);

        return new HtmlString(anchorHtml);
    }

Lớp CSS

.Edit {
       background: url('../images/edit.png') no-repeat right;
       display: inline-block;
       height: 16px;
       width: 16px;
      }

Tạo liên kết chỉ cần chuyển tên lớp

     @Html.ActionImageLink("Edit", new { id = item.ID }, "Edit" , "Edit") 

0

Tôi đã tham gia câu trả lời từ Lucas và " Người trợ giúp ASP.NET MVC, Hợp nhất hai đối tượng htmlAttributes với nhau " và cộng với controllerName vào mã sau:

// Cách sử dụng mẫu trong CSHTML

 @Html.ActionImage("Edit",
       "EditController"
        new { id = MyId },
       "~/Content/Images/Image.bmp",
       new { width=108, height=129, alt="Edit" })

Và lớp mở rộng cho đoạn mã trên:

using System.Collections.Generic;
using System.Reflection;
using System.Web.Mvc;

namespace MVC.Extensions
{
    public static class MvcHtmlStringExt
    {
        // Extension method
        public static MvcHtmlString ActionImage(
          this HtmlHelper html,
          string action,
          string controllerName,
          object routeValues,
          string imagePath,
          object htmlAttributes)
        {
            ///programming/4896439/action-image-mvc3-razor
            var url = new UrlHelper(html.ViewContext.RequestContext);

            // build the <img> tag
            var imgBuilder = new TagBuilder("img");
            imgBuilder.MergeAttribute("src", url.Content(imagePath));

            var dictAttributes = htmlAttributes.ToDictionary();

            if (dictAttributes != null)
            {
                foreach (var attribute in dictAttributes)
                {
                    imgBuilder.MergeAttribute(attribute.Key, attribute.Value.ToString(), true);
                }
            }                        

            string imgHtml = imgBuilder.ToString(TagRenderMode.SelfClosing);

            // build the <a> tag
            var anchorBuilder = new TagBuilder("a");
            anchorBuilder.MergeAttribute("href", url.Action(action, controllerName, routeValues));
            anchorBuilder.InnerHtml = imgHtml; // include the <img> tag inside            
            string anchorHtml = anchorBuilder.ToString(TagRenderMode.Normal);

            return MvcHtmlString.Create(anchorHtml);
        }

        public static IDictionary<string, object> ToDictionary(this object data)
        {
            ///programming/6038255/asp-net-mvc-helpers-merging-two-object-htmlattributes-together

            if (data == null) return null; // Or throw an ArgumentNullException if you want

            BindingFlags publicAttributes = BindingFlags.Public | BindingFlags.Instance;
            Dictionary<string, object> dictionary = new Dictionary<string, object>();

            foreach (PropertyInfo property in
                     data.GetType().GetProperties(publicAttributes))
            {
                if (property.CanRead)
                {
                    dictionary.Add(property.Name, property.GetValue(data, null));
                }
            }
            return dictionary;
        }
    }
}

0

Điều này sẽ rất tốt

<a href="<%:Url.Action("Edit","Account",new {  id=item.UserId }) %>"><img src="../../Content/ThemeNew/images/edit_notes_delete11.png" alt="Edit" width="25px" height="25px" /></a>
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.