Render in MVC a link with image and text

Hi guys, I want in MVC to render a text with an image as an ActionLink. For creating a simple anchor tag, we use Html.ActionLink() helper which generates anchor tag for us.

If you want to create something a bit more complicated, you must create you own component. For this reason, I created the following code. It allows you to create an anchor with an image and a text.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace PSC.MVC.Helpers
{
    public static class CustomHtmlHelpers
    {
        /// 
        /// Enum ImageAndText
        /// 
        public enum ImageAndText
        {
            /// 
            /// Image on the left, text on the right
            /// 
            ImageOnTheLeft,

            /// 
            /// Text on the left, image on the right
            /// 
            ImageOnTheRight
        }

        /// 
        /// Images the action link.
        /// 
        /// The HTML helper.
        /// The link text.
        /// The action.
        /// The controller.
        /// The route values.
        /// The HTML attributes.
        /// The image source.
        /// The alternate text.
        /// The text style.
        /// The image style.
        /// The image position.
        /// IHtmlString.
        public static IHtmlString ImageActionLink(
               this HtmlHelper htmlHelper, string linkText, string action, 
               string controller, object routeValues, object htmlAttributes, 
               string imageSrc, string alternateText = "", 
               string textStyle = "", string imageStyle = "", 
               ImageAndText imagePosition = ImageAndText.ImageOnTheLeft)
        {
            var urlHelper = new UrlHelper(
                    htmlHelper.ViewContext.RequestContext);

            // create the image
            var img = new TagBuilder("img");
            img.Attributes.Add("src", 
                    VirtualPathUtility.ToAbsolute(imageSrc));
            if (!string.IsNullOrEmpty(alternateText))
                img.Attributes.Add("alt", alternateText.Trim());
            if (!string.IsNullOrEmpty(imageStyle))
                img.Attributes.Add("style", imageStyle);

            // create a render for the image and the text
            string render = "";
            if (imagePosition == ImageAndText.ImageOnTheLeft)
                render = img.ToString(TagRenderMode.SelfClosing) + linkText;
            else
                render = linkText + img.ToString(TagRenderMode.SelfClosing);

            // create the anchor with image and text
            var anchor = new TagBuilder("a") {
                InnerHtml = render
            };
            if (!string.IsNullOrEmpty(textStyle))
                anchor.AddCssClass(textStyle);

            // add reference to the anchor
            anchor.Attributes["href"] = urlHelper.Action(action, 
                                                         controller, 
                                                         routeValues);
            anchor.MergeAttributes(new RouteValueDictionary(htmlAttributes));

            return MvcHtmlString.Create(anchor.ToString());
        }
    }
}

In your MVC code you have to add:

@using PSC.MVC.Helpers;

and then you can call your component:
@Html.ImageActionLink("Your text", "Index", "Home", null, null, 
                      "~/Content/images/img.png", "Logo", "navbar-brand", 
                      "width: 40px;")

Xamarin Forms Components

Hello guys!

From today on Nuget there are 4 new components for Xamarin Forms created by me.

Happy coding!

Creating reusable HTML components in ASP.NET MVC using Razor

Whilst working on a side project I started to notice I was using a lot of the same HTML to create floating boxes. Whilst these boxes looked the same, the content of them changed quite dramatically; for instance, some of the content boxes contained forms, others contained straight text, like so:

<div class="panel">
         <div class=panel-inner">
             <h2 class="panel-title">Panel Title</h2>
             <div class="panel-content">
                 /* Can I pass content to be rendered in here here? */
             </div>
         </div>
     </div>
</div>

 

As my side project progressed and grew, I found myself making more and more modifications to these HTML components so I started to look how I can encapsulate the component for greater flexibility and extensibility as my project progressed.

The solution I ended up with was creating a HTML extension modelled off of the way the the Html.BeginForm() extension works, by writing directly to the view's context and then returning an instance of IDisposable, with the call to disposing of the context writing the closing HTML statements of my component to the view context - essentially wrapping the contents passed into the HTML extension in my HTML component.

Below is an example of what the code looks like:

namespace System.Web.Mvc
{
    public static class HtmlHelperExtensions
    {
        public static HtmlPanelComponent PanelComponent(this HtmlHelper html, string title)
        {
            html.ViewContext.Writer.Write(
            "<div class=\"panel\">" +
            "<div class=\"panel-inner\">" +
            "<h2 class=\"panel-title\">" + title + "</h2>" +
            "<div class=\"panel-content\">"
            );

            return new HtmlPanelComponent(html.ViewContext);
        }
    }

    public class HtmlPanelComponent : IDisposable
    {
        private readonly ViewContext _viewContext;
        public HtmlPanelComponent(ViewContext viewContext)
        {
            _viewContext = viewContext;
        }
        public void Dispose()
        {
            _viewContext.Writer.Write(
            "</div>" +
            "</div>" +
            "</div>"
            );
        }
    }
}

Using this new HTML extension I'm now able to reuse my HTML component and fill the panel's content in with whatever I please, like so:

@using (Html.PanelComponent("Panel Title"))
{
    <p>Welcome back, please select from the following options</p>
    <a href="#">Profile</a>
    <a href="#">My Defails</a>
}

C# Console Progress Bar

At work, I sometimes find myself needing to make Console applications which take some time. For example, I have a few console applications which parse dump files into objects and then insert the data into a database. Usually, I represent the progress of these applications with a simple incremental percentage display, however I thought I'd create a generic method which would display an ASCII progress bar.

ConsoleApp_ProgressBar

At work, I sometimes find myself needing to make Console applications which take some time. For example, I have a few console applications which parse dump files into objects and then insert the data into a database. Usually, I represent the progress of these applications with a simple incremental percentage display, however I thought I'd create a generic method which would display an ASCII progress bar.

ProgressBar Class
  1. using System;
  2. using System.Text;
  3. using System.Threading;
  4.  
  5. namespace ConsoleApplication1
  6. {
  7.     /// <summary>
  8.     /// An ASCII progress bar
  9.     /// </summary>
  10.     public class ProgressBar : IDisposable, IProgress<double>
  11.     {
  12.         private const int blockCount = 10;
  13.         private readonly TimeSpan animationInterval = TimeSpan.FromSeconds(1.0 / 8);
  14.         private const string animation = @"|/-\";
  15.         private bool showProgressBar = true;
  16.  
  17.         private readonly Timer timer;
  18.  
  19.         private double currentProgress = 0;
  20.         private string currentText = string.Empty;
  21.         private bool disposed = false;
  22.         private int animationIndex = 0;
  23.  
  24.         public ProgressBar(bool ShowProgressBar = true)
  25.         {
  26.             showProgressBar = ShowProgressBar;
  27.             timer = new Timer(TimerHandler);
  28.  
  29.             // A progress bar is only for temporary display in a console window.
  30.             // If the console output is redirected to a file, draw nothing.
  31.             // Otherwise, we'll end up with a lot of garbage in the target file.
  32.             if (!Console.IsOutputRedirected)
  33.             {
  34.                 ResetTimer();
  35.             }
  36.         }
  37.  
  38.         public void Report(double value)
  39.         {
  40.             // Make sure value is in [0..1] range
  41.             value = Math.Max(0, Math.Min(1, value));
  42.             Interlocked.Exchange(ref currentProgress, value);
  43.         }
  44.  
  45.         private void TimerHandler(object state)
  46.         {
  47.             lock (timer)
  48.             {
  49.                 if (disposed) return;
  50.  
  51.                 string text = "";
  52.                 if (showProgressBar)
  53.                 {
  54.                     int progressBlockCount = (int)(currentProgress * blockCount);
  55.                     int percent = (int)(currentProgress * 100);
  56.                     text = string.Format("[{0}{1}] {2,3}% {3}",
  57.                            new string('#', progressBlockCount), new string('-', blockCount - progressBlockCount),
  58.                            percent,
  59.                            animation[animationIndex++ % animation.Length]);
  60.                 }
  61.                 else
  62.                 {
  63.                     text = animation[animationIndex++ % animation.Length].ToString();
  64.                 }
  65.                 UpdateText(text);
  66.  
  67.                 ResetTimer();
  68.             }
  69.         }
  70.  
  71.         private void UpdateText(string text)
  72.         {
  73.             // Get length of common portion
  74.             int commonPrefixLength = 0;
  75.             int commonLength = Math.Min(currentText.Length, text.Length);
  76.             while (commonPrefixLength < commonLength && text[commonPrefixLength] == currentText[commonPrefixLength])
  77.             {
  78.                 commonPrefixLength++;
  79.             }
  80.  
  81.             // Backtrack to the first differing character
  82.             StringBuilder outputBuilder = new StringBuilder();
  83.             outputBuilder.Append('\b', currentText.Length - commonPrefixLength);
  84.  
  85.             // Output new suffix
  86.             outputBuilder.Append(text.Substring(commonPrefixLength));
  87.  
  88.             // If the new text is shorter than the old one: delete overlapping characters
  89.             int overlapCount = currentText.Length - text.Length;
  90.             if (overlapCount > 0)
  91.             {
  92.                 outputBuilder.Append(' ', overlapCount);
  93.                 outputBuilder.Append('\b', overlapCount);
  94.             }
  95.  
  96.             Console.Write(outputBuilder);
  97.             currentText = text;
  98.         }
  99.  
  100.         private void ResetTimer()
  101.         {
  102.             timer.Change(animationInterval, TimeSpan.FromMilliseconds(-1));
  103.         }
  104.  
  105.         public void Dispose()
  106.         {
  107.             lock (timer)
  108.             {
  109.                 disposed = true;
  110.                 UpdateText(string.Empty);
  111.             }
  112.         }
  113.     }
  114. }

 

Program.cs
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading;
  6. using System.Threading.Tasks;
  7.  
  8. namespace ConsoleApplication1
  9. {
  10.     class Program
  11.     {
  12.         static void Main(string[] args)
  13.         {
  14.             Console.Write("Performing some task... ");
  15.             using (var progress = new ProgressBar())
  16.             {
  17.                 for (int i = 0; i <= 1000; i++)
  18.                 {
  19.                     progress.Report((double)i / 100);
  20.                     Thread.Sleep(20);
  21.                 }
  22.             }
  23.             Console.WriteLine("Done.");
  24.         }
  25.     }
  26. }

The code itself is pretty self explanatory and probably more verbose than it really needs to be, but it gets the job done and looks good.

Download ReportViewer 2010, ReportViewer 11 and SQLSysClrTypes

Have you tried to install ReportViewer on a server? If you as me receive a similar error, I have a solution.

When you have to install the Report Viewer on a server, it's quite difficult to find the install file and a reference for Report Viewer 11 (SQL System Clear Tyle).

Here you can download the last ReportViewer with its dependencies.

SQLSysClrTypes.zip (1.4MB)
ReportViewer.zip (6.1MB)
ReportViewer2010.zip (4.5MB)

Advertsing

125X125_06

Calendar

<<  July 2017  >>
MonTueWedThuFriSatSun
262728293012
3456789
10111213141516
17181920212223
24252627282930
31123456

View posts in large calendar

Tag cloud

Month List