Exporting A Html Canvas Data To Image

As Part of a bigger project I am doing right now, I wanted to be able to store data from a HTML Canvas as a byte[] and save it in Azure blog storage. I thought that this by iteself may make an interesting post. I have not posted up any code this time, but all you should need will be available as snippets here

So the first thing I did was start a new ASP MVC project, which gave me all that I needed to start

Next I added a changed Index.Html page to look like the following

@{
    ViewBag.Title = "Home Page";
}


@section Scripts {
    <script src="~/Scripts/Index.js"></script>
}

<br/>
<p>This small example saves the canvas to blob storage</p>
<div style="border:  1px solid black; margin: 10px;">
    <canvas id="canv" width="600" height="600"></canvas>
</div>
<br/>

<div id="savedImageDiv" style="display:none">
    <img id="savedImage" width="100" height="100"/>
</div>
<button type="button" id="saveCanvas" >Save Canvas TO Blob</button>

See how there is a Canvas element, and a initially hidden Div, where the Div contains an image. This Div will get shown and the image will get filled in with a valid Azure blog storage Url when the Canvas is saved to blob storage.

So how does this happen. There are not that many moving parts there is basically the following 4 things needed

  • An Azure storage account (you set this in the Web.Config), though if you want to try this out, you can just use the Azure storage emulator, and a reference to the Azure Storage dlls, which you can grab via Nuget
  • A page with a Canvas on it (shown above)
  • Some Javascript to post the canvas data over to a MVC controller
  • A controller
  • Lets have a look at each of these in turn

    The Web.Config

    You will need something like this in your app

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
    
      <appSettings>
    
        .....
        .....
        .....
    
        <!-- TODO : This would need to change to live azure value when deployed -->
        <add key="azureStorageConnectionString" value="UseDevelopmentStorage=true;" />
    
    
    
      </appSettings>
    
    
    .....
    .....
    .....
    </configuration>
    

    And you would need to install the following Nuget package “WindowsAzure Storage”

    Javascript

    With the pages html in place, we need some JavaScript to post the Canvas data to the server side controller action. This client side javascript is shown below

    $(document).ready(function () {
        
        fillCanvas();
    
        $("#saveCanvas").on("click", function () {
    
            saveCanvas();
    
        });
    });
    
    
    
    function saveCanvas() {
    
        var canvas = document.getElementById('canv');
        var imageData = canvas.toDataURL('image/jpeg', 1);
    
        $.ajax({
            type: "POST",
            url: "/Home/StoreImage",
            dataType: "json",
            data: { ImageData: imageData, ImageType: "jpeg" },
            success: function (data) {
    
                if (data.StoredOk) {
    
                    $('#savedImageDiv').show();
                    $('#savedImage').attr("src", data.Uri);
                    alert("success :-)");
                } else {
                    alert("fail :-(");
                }
    
                
            },
            error: function () {
                alert("fail :-(");
            }
        });
    }
    
    
    //Draws random stuff on the canvas
    function fillCanvas() {
        var canvas = document.getElementById('canv');
        var context = canvas.getContext('2d');
    
    
        context.fillStyle = "rgb(255,255,255)";
        context.fillRect(0, 0, 600, 600);
    
    
        context.fillStyle = "rgb(150,29,28)";
        context.fillRect(10, 10, 80, 80);
    
        context.fillStyle = "rgb(100,55,28)";
        context.fillRect(200, 200, 20, 80);
    }
    

    All that is then left to do is the server side (MVC Controller Action), which is shown below

    Server side code

    p>The server side controller action to save the canvas byte[] into blob storage is shown below. It will also return a JSON object which includes the Blob Uri is stored successfully. Then the javascript will examine this JSOn response, and decide whether to unhide the Div containing the image, and set the image Uri to the stored canvas data. Which is now stored in a Azure blob as an image.

    using System;
    using System.Collections.Generic;
    using System.Configuration;
    using System.IO;
    using System.Linq;
    using System.Web;
    using System.Web.Helpers;
    using System.Web.Mvc;
    
    using CanvasToBlob.Models;
    
    using Microsoft.WindowsAzure.Storage;
    using Microsoft.WindowsAzure.Storage.Blob;
    
    namespace CanvasToBlob.Controllers
    {
        public class HomeController : Controller
        {
    
            private readonly string azureStorageConnectionString;
            private readonly CloudStorageAccount storageAccount;
    
            public HomeController()
            {
                azureStorageConnectionString = 
    		ConfigurationManager.AppSettings["azureStorageConnectionString"];
    
                storageAccount = 
    		CloudStorageAccount.Parse(azureStorageConnectionString);
            }
    
    
            public ActionResult Index()
            {
                return View();
            }
    
    
            [HttpPost]
            public JsonResult StoreImage(ImageToStore imageToStore)
            {
                try
                {
    
                     CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
     
                    // Retrieve a reference to a container. 
                    CloudBlobContainer container = blobClient.GetContainerReference("images");
                    container.CreateIfNotExists();
                    container.SetPermissions(
                       new BlobContainerPermissions
                       {
                           PublicAccess = BlobContainerPublicAccessType.Blob
                       });
    
                    CloudBlockBlob blockBlob = container.GetBlockBlobReference(
    			string.Format("{0}.{1}", Guid.NewGuid().ToString(), imageToStore.ImageType));
                    string marker = string.Format("data:image/{0};base64,", imageToStore.ImageType);
                    string dataWithoutJpegMarker = imageToStore.ImageData.Replace(marker, String.Empty);
                    byte[] filebytes = Convert.FromBase64String(dataWithoutJpegMarker);
    
                    blockBlob.UploadFromByteArray(filebytes, 0, filebytes.Length);
    
    
                    JsonImageResult result = new JsonImageResult(true, blockBlob.Uri.ToString());
                    return this.Json(result);
                }
                catch (Exception e)
                {
                    JsonImageResult result = new JsonImageResult(false, "");
                    return this.Json("");
                }
            }
        }
    }
    

    Anyway that is all there is too it, I hope you can use this somehow. Enjoy

A Look At NServiceBus Sagas

I have just written a small article that talks about how to use the interprocess bus NServiceBus to perform potentially long running workflows (Called Sagas in NServiceBus).

The article talks about

  • NServiceBus general ideas/principles
  • How to host NServiceBus
  • How to set up a commander
  • How to set up a subscriber
  • How to work with Sagas
  • How to persist Sagas
  • How to deal with Saga data

If you want to know more you can read the full article over here:

http://www.codeproject.com/Articles/731007/A-Look-At-NServiceBus-Sagas

I think this is quite a useful article to get you up and running with NServiceBus

 

 

 

AutoMocking Container

At work I am lucky enough to work with a few bright chaps (sadly some of them are a lot youger than me, which is making me question my existence :-( , but on the other hand it is always good to learn new things).

One of those new things for me happened the other day, where this dude at work showed me MSpec for TDD/BDD, and I have to say it was pretty awesome. The thing that I liked the most was the “AutoMocking” feature

So what is this “AutoMocking” that I am talking about, and why is it cool? Well quite simply it eliviates the brittle relationship with code and tests in their infancy, and allows tests to create constructor injection parameters automatically

I should point out that this pattern really suits new code bases, that may still be a bit in flux, it is not really that much use for well established code bases that have been around and settled for a while

It is also worth noting that this pattern can be used with code that doesn’t use any IOC/dependency injection at all, it is purely a testing concern

So what is it all about?

Well say you have this class

public class Autobooker
{
    private readonly ILogger logger;
    private readonly IRateProvider rateProvider;
    private readonly IBooker booker;

    public Autobooker(ILogger logger, IRateProvider rateProvider, IBooker booker)
    {
        this.logger = logger;
        this.rateProvider = rateProvider;
        this.booker = booker;
    }


    public void BookDeal(string ccy1, string ccy2, decimal amount)
    {
        logger.Log(string.Format("Booked deal for {0}/{1}", ccy1, ccy2));
        decimal rate = rateProvider.GetRate(string.Join("", ccy1, ccy2));
        booker.Book(ccy1, ccy2, rate, amount);

    }
}

Which you may write a test case for something like this (I am using NUnit and Moq, but you may prefer you own tools to these)

[TestFixture]
public class TestCases
{
    private IWindsorContainer container;

    [SetUp]
    public void SetUp()
    {
        container = new WindsorContainer();
        container.Install(new BookerInstaller());
    }

    [TestCase("EUR", "GBP", 1500)]
    [TestCase("GBP", "EUR", 2200)]
    public void TypicalTestCase(string ccy1, string ccy2, decimal amount)
    {
        //setup
        string ccyPair = string.Join("", ccy1, ccy2);
        var rate = 1;
        var loggerMock = new Mock<ILogger>();
        var rateProviderMock = new Mock<IRateProvider>();
        var bookerMock = new Mock<IBooker>();

        rateProviderMock
            .Setup(x => x.GetRate(ccyPair)).Returns(1);

        var autobooker = new Autobooker(loggerMock.Object, rateProviderMock.Object, bookerMock.Object);
        autobooker.BookDeal(ccy1, ccy2, amount);

        //assert
        loggerMock
            .Verify(x => x.Log(string.Format("Booked deal for {0}/{1}", ccy1, ccy2)),
                Times.Exactly(1));

        rateProviderMock
            .Verify(x => x.GetRate(string.Join("", ccy1, ccy2)), Times.Exactly(rate));

        bookerMock
            .Verify(x => x.Book(ccy1, ccy2, rate, amount), Times.Exactly(1));
    }
}

The problem with this code is that it is extremely coupled to the design. What would happen if the Autobooker class needed to take a new constructor dependency say something like this

public class Autobooker
{
    private readonly ILogger logger;
    private readonly IRateProvider rateProvider;
    private readonly IBooker booker;
    private readonly IPricer pricer;

    public Autobooker(ILogger logger, IRateProvider rateProvider, IBooker booker, IPricer pricer)
    {
        this.logger = logger;
        this.rateProvider = rateProvider;
        this.booker = booker;
        this.pricer = pricer;
    }
}

This should immediately ring alarm bells that your existing test cases will now break, but what can we do about it? This is where “AutoMocking” can help. Let us take a look at this shall we.

So the first step is to decide on a nice IOC container that you think is fit for the job. For me this is Castle Windsor. So that is that decision made, so what do we need to do now that we have made that decision? Well all we really need to do is get it to automatically create our Mocks for us. SO what does that look like? Well for me it looks like this

public class AutoMoqServiceResolver : ISubDependencyResolver
{
    private IKernel kernel;

    public AutoMoqServiceResolver(IKernel kernel)
    {
        this.kernel = kernel;
    }

    public bool CanResolve(
        CreationContext context,
        ISubDependencyResolver contextHandlerResolver,
        ComponentModel model,
        DependencyModel dependency)
    {
        return dependency.TargetType.IsInterface;
    }

    public object Resolve(
        CreationContext context,
        ISubDependencyResolver contextHandlerResolver,
        ComponentModel model,
        DependencyModel dependency)
    {
        var mock = typeof(Mock<>).MakeGenericType(dependency.TargetType);
        return ((Mock)kernel.Resolve(mock)).Object;
    }
}

The next step is to create some sort of IOC registration for the system under test (SOT), which for me means the Autobooker type. So we do that as follows

public class BookerInstaller : IWindsorInstaller
{
    public void Install(
        IWindsorContainer container,
        IConfigurationStore store)
    {
        container.Kernel.Resolver.AddSubResolver(new AutoMoqServiceResolver(container.Kernel));
        container.Register(Component.For(typeof(Mock<>)));

        container.Register(Classes
            .FromAssemblyContaining<Booker.Autobooker>()
            .Pick()
            .WithServiceSelf()
            .LifestyleTransient());
    }
}

With that all in place I can now write non brittle code, that will get the object I want to test from the IOC container, where all its dependencies will try to be satified by the automocking IOC container. So my test case now looks like this

[TestCase("EUR", "GBP", 1500)]
[TestCase("GBP", "EUR", 2200)]
public void TestBooking(string ccy1, string ccy2, decimal amount)
{
    var autobooker = container.Resolve<Autobooker>();
    string ccyPair = string.Join("", ccy1, ccy2);
    var rate = 1;
            
    //arrange
    container.Resolve<Mock<IRateProvider>>()
        .Setup(x => x.GetRate(ccyPair)).Returns(1);

    autobooker.BookDeal(ccy1,ccy2,amount);

    //assert
    container.Resolve<Mock<ILogger>>()
        .Verify(x => x.Log(string.Format("Booked deal for {0}/{1}", ccy1, ccy2)),
            Times.Exactly(1));

    container.Resolve<Mock<IRateProvider>>()
        .Verify(x => x.GetRate(string.Join("", ccy1, ccy2)), Times.Exactly(rate));
            
    container.Resolve<Mock<IBooker>>()
        .Verify(x => x.Book(ccy1,ccy2,rate,amount), Times.Exactly(1));

}

See how I no longer need to declare the mocks, I just define their behavior, which I think is cool

WPF : DatePicker With Holiday Blackouts And ToolTips

Where I work we deal with FX (Foreign Exchange), and as such we have to deal with a lot of different holidays both for all the countries of the world and the 2 currencies normally involved in a FX deal. We would also typically like to show this to theuser by way of a blacked out Date within the standard WPF DatePicker. Luckily the standard WPF DatePicker does support the idea of a BlackoutDate collection which makes the WPF DatePicker Calendar look like this:

 

image

 

All good so far, but our users would like to know WHY they can’t do a trade on this date. Some sort of ToolTip would be nice. This blog will show you how to achieve that.

 

So how can we do that exactly?

Step 1

We need some sort of NonWorking day item that we could use to bind against. Here is one I think fits the bill

 

 
[DataContract]
[DebuggerDisplay("{Date.ToShortDateString()}({Description})")]
public class NonWorkingDayDto : IEquatable<NonWorkingDayDto>
{
    public NonWorkingDayDto(DateTime date, string description)
    {
        Date = date;
        Description = description;
    }

    [DataMember]
    public DateTime Date { get; set; }

    [DataMember]
    public string Description { get; set; }

    public bool Equals(NonWorkingDayDto other)
    {
        if (ReferenceEquals(null, other))
        {
            return false;
        }
        if (ReferenceEquals(this, other))
        {
            return true;
        }
        return this.Date.Equals(other.Date);
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj))
        {
            return false;
        }
        if (ReferenceEquals(this, obj))
        {
            return true;
        }
        if (obj.GetType() != this.GetType())
        {
            return false;
        }
        return Equals((NonWorkingDayDto)obj);
    }

    public override int GetHashCode()
    {
        return this.Date.GetHashCode();
    }

    public static bool operator ==(NonWorkingDayDto left, NonWorkingDayDto right)
    {
        return Equals(left, right);
    }

    public static bool operator !=(NonWorkingDayDto left, NonWorkingDayDto right)
    {
        return !Equals(left, right);
    }
}



public class NonWorkingDayComparer : IEqualityComparer<NonWorkingDayDto>
{
    public bool Equals(NonWorkingDayDto x, NonWorkingDayDto y)
    {
        return x.Date == y.Date;
    }

    public int GetHashCode(NonWorkingDayDto obj)
    {
        return obj.Date.GetHashCode();
    }
} 

Step 2

We need to create a few attached properties for working with the Calendar. You will notice that one is going to be some sort of text lookup. We will be using that for the tooltips later. It is an Attached property that we can hook into. The 2nd one allows us to bind a number of NonWorkingDayDto objects, which will then create the DatePicker/Calendar BlackoutDate collection. This collection should be treated with a lot of care, as if you attempt to Clear() the collection and then add the new items in again you will see very bad prerformance. There must be an aweful lot of binding stuff going on based on that, it also seems to be a factor if you have opened several Calendar months from the UI, the DatePicker seems to cache these previously shown Calendar instances internally. I found the best way was to do some set type intersections and just remove the ones I didn’t want anymore, and add the ones I wanted that were not present right now

 
public static class CalendarBehavior
{
    #region BlackOutDatesTextLookup

    public static readonly DependencyProperty BlackOutDatesTextLookupProperty =
        DependencyProperty.RegisterAttached("BlackOutDatesTextLookup",
            typeof(Dictionary<DateTime, string>), typeof(CalendarBehavior),
                new FrameworkPropertyMetadata(new Dictionary<DateTime, string>()));


    public static Dictionary<DateTime, string> GetBlackOutDatesTextLookup(DependencyObject d)
    {
        return (Dictionary<DateTime, string>)d.GetValue(BlackOutDatesTextLookupProperty);
    }

    public static void SetBlackOutDatesTextLookup(DependencyObject d, Dictionary<DateTime, string> value)
    {
        d.SetValue(BlackOutDatesTextLookupProperty, value);
    }

    #endregion

    #region NonWorkingDays

    public static readonly DependencyProperty NonWorkingDaysProperty =
        DependencyProperty.RegisterAttached("NonWorkingDays",
            typeof(IEnumerable<NonWorkingDayDto>), typeof(CalendarBehavior),
                new FrameworkPropertyMetadata(null, OnNonWorkingDaysChanged));


    public static IEnumerable<NonWorkingDayDto> GetNonWorkingDays(DependencyObject d)
    {
        return (IEnumerable<NonWorkingDayDto>)d.GetValue(NonWorkingDaysProperty);
    }

    public static void SetNonWorkingDays(DependencyObject d, IEnumerable<NonWorkingDayDto> value)
    {
        d.SetValue(NonWorkingDaysProperty, value);
    }

    private static void OnNonWorkingDaysChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {


        DatePicker datePicker = d as DatePicker;
        if (e.NewValue != null && datePicker != null)
        {
            IEnumerable<NonWorkingDayDto> localNonWorkingDays = (IEnumerable<NonWorkingDayDto>)e.NewValue;
            Dictionary<DateTime, string> blackoutDatesTextLookup = new Dictionary<DateTime, string>();

            // IMPORTANT NOTE
            // Due to the way the DatePicker Calendar BlackoutDates collection works
            // It is dog slow to clear the BlackoutDates collection and add items in one by one
            // so we have to perform some voodoo, where we remove the Blackout dates that are not 
            // in the new NonWorking value, and then add in ONLY those that are missing from the new
            // NonWorking days value into the BlackoutDates collection. It sucks but it makes a BIG difference
            // Using Clear() and Add in for loop its like 1500ms (Per DatePicker), and using this method its down to
            // something like 35ms (Per DatePicker).......So please do not change this logic
            var toRemove = datePicker.BlackoutDates.Select(x => x.Start).Except(localNonWorkingDays.Select(y => y.Date)).ToList();

            foreach (DateTime dateTime in toRemove)
            {
                datePicker.BlackoutDates.Remove(datePicker.BlackoutDates.Single(x => x.Start == dateTime));
            }

            foreach (NonWorkingDayDto nonWorkingDay in localNonWorkingDays)
            {
                if (!datePicker.BlackoutDates.Contains(nonWorkingDay.Date))
                {
                    CalendarDateRange range = new CalendarDateRange(nonWorkingDay.Date);
                    datePicker.BlackoutDates.Add(range);
                }
                blackoutDatesTextLookup[nonWorkingDay.Date] = nonWorkingDay.Description;
            }
            datePicker.SetValue(BlackOutDatesTextLookupProperty, blackoutDatesTextLookup);
        }


    }
    #endregion
}

Step 3

We also need a simple value converter which we can use to obtain the ToolTip. This simply looks up the text from the attached properties we declared above

 
public class CalendarToolTipConverter : IMultiValueConverter
{
    private CalendarToolTipConverter()
    {

    }

    static CalendarToolTipConverter()
    {
        Instance = new CalendarToolTipConverter();
    }

    public static CalendarToolTipConverter Instance { get; private set; }


    #region IMultiValueConverter Members

    /// <summary>
    /// Gets a tool tip for a date passed in. Could also return null
    /// </summary>
    /// <remarks>
    /// The 'values' array parameter has the following elements:
    /// 
    /// values[0] = Binding #1: The date to be looked up. This should be set up as a pathless binding; 
    /// the Calendar control will provide the date.
    /// 
    /// values[1] = Binding #2: A binding reference to the DatePicker control that is invoking this converter.
    ///
    /// values[2] = Binding #3: Attached property CalendarBehavior.BlackOutDatesTextLookup for DatePicker
    /// </remarks>
    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        // Exit if values not set
        if (values[0] == null || values[1] == null || values[2] == null)
            return null;

        // Get values passed in
        DateTime targetDate = (DateTime)values[0];
        DatePicker dp = (DatePicker)values[1];
        Dictionary<DateTime, string> blackOutDatesTextLookup = (Dictionary<DateTime, string>)values[2];
        string tooltip = null;
        blackOutDatesTextLookup.TryGetValue(targetDate, out tooltip);
        return tooltip;
    }

    /// <summary>
    /// Not used.
    /// </summary>
    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
    {
        return new object[0];
    }
    #endregion
}

Step 4

We would need to create a collection of NonWorking days and add them to a DatePicker. This would normally be a ViewModel bindings, but for brevity I have just done this in code as follows:

 
List<NonWorkingDayDto> nonWorkingDayDtos = new List<NonWorkingDayDto>();
nonWorkingDayDtos.Add(new NonWorkingDayDto(DateTime.Now.AddDays(1).Date, "Today +1 is no good"));
nonWorkingDayDtos.Add(new NonWorkingDayDto(DateTime.Now.AddDays(2).Date, "Today +2 is no good"));

dp.SetValue(CalendarBehavior.NonWorkingDaysProperty, nonWorkingDayDtos);

Step 5

Next we need a custom CalendarStyle for the DatePicker

<Grid x:Name="LayoutRoot">
	<DatePicker x:Name="dp" HorizontalAlignment="Left" Margin="192,168,0,0" VerticalAlignment="Top" 
		CalendarStyle="{StaticResource NonWorkingDayCalendarStyle}"/>
</Grid>

Step 6

The last piece to the puzzle is how to apply the ToolTip to the Calendar, which is done below have a look at the Calendar which uses a special “CalendarDayButtonStyle” which is the specific Style that deals with showing the ToolTip

 

 
<Style x:Key="NonWorkingDayTooltipCalendarDayButtonStyle" 
        TargetType="{x:Type CalendarDayButton}">
    <Setter Property="MinWidth" Value="5"/>
    <Setter Property="MinHeight" Value="5"/>
    <Setter Property="FontSize" Value="10"/>
    <Setter Property="HorizontalContentAlignment" Value="Center"/>
    <Setter Property="VerticalContentAlignment" Value="Center"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type CalendarDayButton}">
                <Grid x:Name="ToolTipTargetBorder">
                    .......
                    .......
                    .......
                    .......
                    <Rectangle x:Name="TodayBackground" 
                                Fill="#FFAAAAAA" 
                                Opacity="0" 
                                RadiusY="1" 
                                RadiusX="1"/>
                    <Rectangle x:Name="SelectedBackground" 
                                Fill="#FFBADDE9" 
                                Opacity="0" 
                                RadiusY="1" 
                                RadiusX="1"/>
                    <Border BorderBrush="{TemplateBinding BorderBrush}" 
                            BorderThickness="{TemplateBinding BorderThickness}" 
                            Background="{TemplateBinding Background}"/>
                    <Rectangle x:Name="HighlightBackground" 
                                Fill="#FFBADDE9" 
                                Opacity="0" 
                                RadiusY="1" 
                                RadiusX="1"/>
                    <ContentPresenter x:Name="NormalText" 
                                        TextElement.Foreground="Black" 
                                        HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
                                        Margin="5,1,5,1" 
                                        VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                    <Path x:Name="Blackout" 
                            Data="M8.1772461,11.029181 L10.433105,11.029181 L11.700684,12.801641 .....z" 
				Fill="Black"  
				HorizontalAlignment="Stretch" 
				Margin="3" 
				Opacity="0" 
				RenderTransformOrigin="0.5,0.5" 
				Stretch="Fill" 
				VerticalAlignment="Stretch"/>
                    <Rectangle x:Name="DayButtonFocusVisual" 
                                IsHitTestVisible="false" 
                                RadiusY="1" 
                                RadiusX="1" 
                                Stroke="Black" 
                                Visibility="Collapsed"/>
                </Grid>

                <ControlTemplate.Triggers>
                    <Trigger Property="IsBlackedOut" Value="True">
                        <Setter TargetName="ToolTipTargetBorder" Property="ToolTip">
                            <Setter.Value>
                                <MultiBinding Converter="{x:Static local:CalendarToolTipConverter.Instance}">
                                    <MultiBinding.Bindings>
                                        <Binding />
                                        <Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type DatePicker}}" />
                                        <Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type DatePicker}}" 
                                            Path="(local:CalendarBehavior.BlackOutDatesTextLookup)" />
                                    </MultiBinding.Bindings>
                                </MultiBinding>
                            </Setter.Value>
                        </Setter>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>



<Style x:Key="NonWorkingDayCalendarStyle" TargetType="{x:Type Calendar}">
    <Setter Property="CalendarDayButtonStyle" 
            Value="{StaticResource NonWorkingDayTooltipCalendarDayButtonStyle}"/>
    <Setter Property="Foreground" Value="Black"/>
    <Setter Property="Background" Value="WhiteSmoke"/>
    <Setter Property="BorderBrush" Value="Black"/>
    <Setter Property="BorderThickness" Value="1"/>

</Style>

 

As always here is a small demo project : https://dl.dropboxusercontent.com/u/2600965/Blogposts/2013/DatepickerWithWorkingDayTooltips.zip

XAML : Binding To Nullable Enums With Friendly Names

I was at work the other day and I had a situation where I needed to use a nullable enum. I wanted this to be available within a ComboBox but It was not compulsary for the users to select something. I also wanted to allow the ComboBox to print a friendly name of the Enum value.

The friendly name thing is something I have covered before in a previous article Binding-and-Using-Friendly-Enums-in-WPF but I have never really come across a time where I needed to allow a ComboBox with null selection support for the user.

I did not want to polute my enum values with a special “None” value, as that is really what the nullable aspect of it was doing. So I started to explore things a bit, and this is what I ended up with

My ViewModel and Enum

public enum Animals
{
    [EnumMember(Value = "Its a nice kitty")]
    Cat=1,

    [EnumMember(Value = "Its a bow wow")]
    Dog = 2
}

public class MainWindowViewModel : INPCBase
{
    private Animals? selectedAnimal;

    public MainWindowViewModel()
    {
        SelectedAnimal = null;
    }

    public Animals? SelectedAnimal
    {
        get { return this.selectedAnimal; }
        set
        {
            RaiseAndSetIfChanged(ref this.selectedAnimal, value, () => this.SelectedAnimal);
            MessageBox.Show(
                "SelectedAnimal: " + (!selectedAnimal.HasValue ?
                    NullHelper.NullComboStringValue : selectedAnimal.ToString()));
        }
    }

}

Next up was my View. The interesting points here are

  1. We use a ObjectDataProvider to supply the enum values
  2. We use a CompositeCollection (which doesn’t work with Binding ie ItemsSource being bound) where we get the Enum values and also a special “Null” value from a helper class
  3. We use a special NullableEnumToFriendlyNameConverter value converter to supply the friendly name lookup value for the enum (providing its not the special “Null” value
  4. We use a special NullableEnumConverter to convetr back to either null or a picked enum value for the ViewModel property setter
<Window x:Class="NullEnumCombo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:nullEnumCombo="clr-namespace:NullEnumCombo"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        Title="MainWindow" Height="350" Width="525">

    <Window.Resources>

        <ObjectDataProvider x:Key="animalTypeFromEnum"
                            MethodName="GetValues"
                            ObjectType="{x:Type sys:Enum}">
            <ObjectDataProvider.MethodParameters>
                <x:Type TypeName="nullEnumCombo:Animals" />
            </ObjectDataProvider.MethodParameters>
        </ObjectDataProvider>
    </Window.Resources>

    <Grid>
        <ComboBox Width="150" Height="20" 
            HorizontalAlignment="Center" 
            VerticalAlignment="Center"
            SelectedItem="{Binding SelectedAnimal, 
                Converter={x:Static nullEnumCombo:NullableEnumConverter.Instance},
                    ConverterParameter={x:Static nullEnumCombo:Animals.Cat}}">
            <ComboBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock  Text="{Binding   Path=., Mode=OneWay,
                        Converter={x:Static 
                           nullEnumCombo:NullableEnumToFriendlyNameConverter.Instance}}"
                        Height="Auto"
                        Margin="0"
                        VerticalAlignment="Center"/>
                </DataTemplate>
            </ComboBox.ItemTemplate>

            <ComboBox.ItemsSource>
                <CompositeCollection>
                    <x:Static Member="nullEnumCombo:NullHelper.NullComboStringValue"/>
                    <CollectionContainer
                        Collection="{Binding Source={StaticResource animalTypeFromEnum}}" />
                </CompositeCollection>
            </ComboBox.ItemsSource>

        </ComboBox>
    </Grid>
</Window>

Here are the 2 value converters and the small helper class

public class NullableEnumConverter : IValueConverter
{
    private NullableEnumConverter()
    {

    }

    static NullableEnumConverter()
    {
        Instance = new NullableEnumConverter();
    }

    public static NullableEnumConverter Instance { get; private set; }

    public object Convert(object value, Type targetType, 
           object parameter, CultureInfo culture)
    {
        if (value == null)
        {
            return NullHelper.NullComboStringValue;
        }
        return value;
    }

    public object ConvertBack(object value, Type targetType, 
           object parameter, CultureInfo culture)
    {
        Type enumType = parameter.GetType();
        if (value.ToString().Equals(NullHelper.NullComboStringValue))
        {
            return null;
        }
        object rawEnum = Enum.Parse(enumType, value.ToString());
        return System.Convert.ChangeType(rawEnum, enumType);
    }
}

/// <summary>
/// This class simply takes an enum and uses some reflection to obtain
/// the friendly name for the enum. Where the friendlier name is
/// obtained using the EnumMemberAttribute, which hold the localized
/// value read from the resource file for the enum
/// </summary>
[ValueConversion(typeof(object), typeof(String))]
public class NullableEnumToFriendlyNameConverter : IValueConverter
{

    private NullableEnumToFriendlyNameConverter()
    {

    }

    static NullableEnumToFriendlyNameConverter()
    {
        Instance = new NullableEnumToFriendlyNameConverter();
    }

    public static NullableEnumToFriendlyNameConverter Instance { get; private set; }

    #region IValueConverter implementation

    /// <summary>
    /// Convert value for binding from source object
    /// </summary>
    public object Convert(object value, Type targetType, 
           object parameter, CultureInfo culture)
    {
        // To get around the stupid wpf designer bug
        if (value != null && !string.IsNullOrEmpty(value.ToString()) && 
             !value.ToString().Equals(NullHelper.NullComboStringValue))
        {
            FieldInfo fi = value.GetType().GetField(value.ToString());

            // To get around the stupid wpf designer bug
            if (fi != null)
            {
                var attributes =
                    (EnumMemberAttribute[])fi.GetCustomAttributes(typeof(EnumMemberAttribute), false);

                return ((attributes.Length > 0) &&
                        (!String.IsNullOrEmpty(attributes[0].Value)))
                            ?
                                attributes[0].Value
                            : value.ToString();
            }
        }

        return NullHelper.NullComboStringValue;
    }

    /// <summary>
    /// ConvertBack value from binding back to source object
    /// </summary>
    public object ConvertBack(object value, Type targetType, 
           object parameter, CultureInfo culture)
    {
        throw new Exception("Cant convert back");
    }
    #endregion
}

public class NullHelper
{
    public static string NullComboStringValue
    {
        get
        {
            return "(None)";
        }
    }
}