Action Image MVC3 มีดโกน


119

วิธีที่ดีที่สุดในการแทนที่ลิงก์ด้วยรูปภาพโดยใช้ Razor ใน MVC3 คืออะไร ฉันเพิ่งทำสิ่งนี้ในขณะนี้:

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

มีวิธีที่ดีกว่า?


15
ไม่เกี่ยวข้องโดยตรง แต่ขอแนะนำอย่างยิ่งให้คุณใช้ไฟล์ PNG หรือ JPG (ขึ้นอยู่กับเนื้อหารูปภาพ) แทนไฟล์ BMP และเช่นเดียวกับที่ @jgauffin แนะนำให้ลองใช้เส้นทางสัมพัทธ์ของแอปพลิเคชัน ( ~/Content) เส้นทางที่../../Contentอาจจะไม่ถูกต้องจากเส้นทางที่แตกต่างกัน (เช่น/, /Home, /Home/Index)
Lucas

ขอบคุณลูคัส ฉันใช้ png แต่คำแนะนำในการใช้ URL เนื้อหาคือสิ่งที่ฉันกำลังมองหา โหวตขึ้น :)
davy

คำตอบ:


217

คุณสามารถสร้างวิธีการขยายสำหรับ HtmlHelper เพื่อลดความซับซ้อนของโค้ดในไฟล์ CSHTML ของคุณ คุณสามารถแทนที่แท็กของคุณด้วยวิธีการดังนี้:

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

นี่คือตัวอย่างวิธีการขยายสำหรับโค้ดด้านบน:

// 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
ตัวอย่างที่ยอดเยี่ยม ใครก็ตามที่ต้องการใช้สิ่งนี้กับ T4MVC เพียงแค่เปลี่ยนประเภทของrouteValuesเป็นActionResultจากนั้นในurl.Actionฟังก์ชั่นเปลี่ยนrouteValuesเป็นrouteValues.GetRouteValueDictionary()
JConstantine

12
@ Kasper Skov: วางเมธอดในคลาสแบบคงที่จากนั้นอ้างอิงเนมสเปซของคลาสนั้นใน Web.config ใน/configuration/system.web/pages/namespacesองค์ประกอบ
Umar Farooq Khawaja

4
ดี! แทนที่จะaltยอมรับฉันยอมรับวัตถุเพื่อรับคุณสมบัติ html โดยใช้วัตถุที่ไม่ระบุตัวตนvar attributes = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);ในที่สุดforeach (var attr in attributes){ imgBuilder.MergeAttribute(attr.Key, attr.Value.ToString());}
guzart

7
ฉันไม่สามารถทำงานนี้ได้จนกว่าฉันจะรู้ว่าเนื่องจากฉันใช้พื้นที่การอ้างอิงถึงเนมสเปซของคลาส (ตามที่ Umar ชี้ให้เห็น) จำเป็นต้องเพิ่มลงในไฟล์ web.config ทั้งหมดในโฟลเดอร์ Views สำหรับทุกพื้นที่เช่นเดียวกับ/Viewsโฟลเดอร์ระดับบนสุด
Mark_Gibson

2
หากคุณต้องการสิ่งนี้ในหน้าเดียวแทนที่จะเปลี่ยนไฟล์ Web.config คุณสามารถเพิ่มคำสั่ง @using ใน. cshtml และอ้างอิงเนมสเปซ
JML

64

คุณสามารถใช้Url.Contentสิ่งที่ใช้ได้กับลิงก์ทั้งหมดเนื่องจากแปลเครื่องหมายทิลเดอ~เป็นรูท uri

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

3
ใช้งานได้ดีใน MVC3 ขอบคุณ! <a href="@Url.Action("Index","Home")"><img src="@Url.Content("~/Content/images/myimage.gif")" alt="Home" /></a>
rk1962

24

จากคำตอบของ Lucas ข้างต้นนี่คือโอเวอร์โหลดที่ใช้ชื่อคอนโทรลเลอร์เป็นพารามิเตอร์คล้ายกับ ActionLink ใช้โอเวอร์โหลดนี้เมื่อรูปภาพของคุณเชื่อมโยงกับการดำเนินการในคอนโทรลเลอร์อื่น

// 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
ไม่มีความคิดเห็นเกี่ยวกับการเพิ่มของคุณที่นี่ ... ฉันบอกว่าการปรับเปลี่ยนรหัสที่ให้มานั้นดี +1 จากฉัน
Zack Jannsen

11

คุณสามารถใช้โซลูชัน @Lucas ได้ แต่ก็มีวิธีอื่นเช่นกัน

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

ตอนนี้เพิ่มคลาสนี้ในไฟล์ CSS หรือในเพจของคุณ:

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

ด้วยคลาสนั้นลิงก์ใด ๆ ก็จะมีรูปภาพที่คุณต้องการ


2
@KasperSkov ฉันลืมปัญหาเล็กน้อยนี้ไป ด้วยเหตุผลบางประการการแทนที่ตัวช่วย actionLink โดยเฉพาะนี้ใช้ไม่ได้กับตัวอย่างด้านบน คุณต้องControllerNameลงมือทำ ดังนี้@Html.ActionLink("Update", "Update", "*Your Controller*",*object values*, new {@class = "imgLink"})
AdrianoRR

3

สิ่งนี้กลายเป็นกระทู้ที่มีประโยชน์มาก

สำหรับผู้ที่แพ้เครื่องมือจัดฟันแบบลอนนี่คือคำตอบของ Lucas 'และ Crake เวอร์ชัน VB.NET:

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

วิธีการขยายนี้ใช้งานได้เช่นกัน (วางไว้ในคลาสคงที่สาธารณะ):

    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

หากต้องการเพิ่มให้กับงาน Awesome ทั้งหมดที่เริ่มโดยลุคฉันกำลังโพสต์อีกหนึ่งงานที่ใช้ค่าคลาส css และถือว่าคลาสและ alt เป็นพารามิเตอร์เสริม (ใช้ได้ภายใต้ ASP.NET 3.5+) วิธีนี้จะช่วยให้สามารถใช้งานได้มากขึ้น แต่ลดจำนวนวิธีการที่มากเกินไปที่จำเป็น

// 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);
    }

นอกจากนี้สำหรับทุกคนที่เพิ่งเริ่มใช้ MVC คำแนะนำที่เป็นประโยชน์ - ค่าของ routeValue shoudl เป็น @ RouteTable.Routes ["Home"] หรือ id "route" ของคุณที่อยู่ใน RouteTable
Zack Jannsen

1

การปรับเปลี่ยนสไลด์เปลี่ยน 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);
    }

CSS คลาส

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

สร้างลิงค์เพียงแค่ส่งชื่อคลาส

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

0

ฉันได้เข้าร่วมคำตอบจาก Lucas และ " ASP.NET MVC Helpers การรวมวัตถุ htmlAttributes สองตัวเข้าด้วยกัน " และบวก controllerName เข้ากับรหัสต่อไปนี้:

// ตัวอย่างการใช้งานใน CSHTML

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

และคลาสส่วนขยายสำหรับโค้ดด้านบน:

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

นี่จะเป็นการทำงานที่ดีมาก

<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>
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.