WPF

Binding To Nullable Enums

This post will be a short post about how you can easily bind to nullable enums value in WPF. This is quite useful when you have optional values.

So lets start with a simple ViewModel shall we, it can be seen that this ViewModel uses a Nullable<ProductType> and that the ProductType itself uses the DescriptionAttribute

using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;


namespace WpfApplication1
{
    public enum ProductType
    {
        [Description("Wet Food")]
        WetFood=1,
 
        [Description("Dry Food")]
        DryFood=2
    }
    public class MainWindowViewModel : INotifyPropertyChanged
    {

        private ProductType? selectedProductType ;

        public ProductType? SelectedProductType
        {
          get
          {
              return selectedProductType;
          }
          set
          {
              selectedProductType = value;
              OnPropertyChanged();
          }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(
            [CallerMemberName] string propertyName = null)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null) handler(this, 
                new PropertyChangedEventArgs(propertyName));


        }
    }
}

All good so far, so now lets look at the XAML

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       xmlns:sys="clr-namespace:System;assembly=mscorlib"
       xmlns:local="clr-namespace:WpfApplication1"
       Title="MainWindow" Height="350" Width="525">


    <Window.Resources>

        <ObjectDataProvider x:Key="ProductTypeEnumProvider"
                MethodName="GetValues"
                ObjectType="{x:Type sys:Enum}">
            <ObjectDataProvider.MethodParameters>
                <x:Type TypeName="local:ProductType" />
            </ObjectDataProvider.MethodParameters>
        </ObjectDataProvider>
    </Window.Resources>



    <Grid>


        <ComboBox HorizontalAlignment="Center" VerticalAlignment="Center"
                  
                  
                SelectedItem="{Binding SelectedProductType, 
                    Converter={x:Static local:NullableEnumConverter.Instance}, 
                        ConverterParameter={x:Static local:ProductType.DryFood}}">
            <ComboBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock  Text="{Binding   Path=., Mode=OneWay, 
                        Converter={x:Static local:NullableEnumToFriendlyNameConverter.Instance}}"
                        Height="Auto"
                        Margin="0" 
                        VerticalAlignment="Center"/>
                </DataTemplate>
            </ComboBox.ItemTemplate>
            <ComboBox.ItemsSource>
                <CompositeCollection>
                    <x:Static Member="local:NullHelper.NullComboStringValue"/>
                    <CollectionContainer Collection="{Binding 
                        Source={StaticResource ProductTypeEnumProvider}}" />
                </CompositeCollection>
            </ComboBox.ItemsSource>
        </ComboBox>


    </Grid>
</Window>

Most of that is standard stuff. What is nice with my approach here is the use of the CompositeCollection which allows you to treat disparate sources as one overall source, in this case an empty string, and the actual enum values form the final ItemSource for the ComboBox

The empty string is within this small helper class

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WpfApplication1
{
    public class NullHelper
    {
        public static string NullComboStringValue
        {
            get
            {
                return "None";
            }
        }
    }
}

And there are also a couple of value converters that deal with the nullable enum value:

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Windows.Data;


namespace WpfApplication1
{
    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);
        }
    }
}

And also one that is responsible for showing the friendly name of the DescriptionAttribute that the enum values make use of:

using System;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Windows.Data;


namespace WpfApplication1
{
    /// <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 DescriptionAttribute, 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 =
                        (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
 
                    return ((attributes.Length > 0) &&
                            (!String.IsNullOrEmpty(attributes[0].Description)))
                               ?
                                   attributes[0].Description
                               : 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    
    }
}

Hope that helps you in some small way. I know this post was a small one, but hopefully its useful

Advertisements
Uncategorized

NetMQ : Documentation is there….Phew

I have been beavering away over the past 2 weeks, creating the NetMQ documentation. I am pleased to announce that the docs have come along quite nicely and you can read them all here :

http://netmq.readthedocs.org/en/latest/

 

You can also read them directly at GitHub too :

https://github.com/zeromq/netmq/tree/master/docs

 

I actually prefer the formatting on GitHub, but “ReadTheDocs” is what we have. But at least you have choices.

I hope that helps you in some way in your journeys with NetMQ. Oh it is worth mentioning that there are a couple of pages still to do, which Doron himself will be doing. These pages are

  • Stream
  • Devices
  • Beacon
  • Scheduler

I think the docs I wrote should cover the most common cases though.

There was also one user who has offered to translate the docs into French, so you can expect some French version some time in the future too

Enjoy

 

 

 

Uncategorized

NetMQ : Documentation II

I don’t know how many of you read my last post, but I have somehow managed to talk myself into becoming the official documentation writer for NetMQ. If you have not used NetMQ, it is a C# native port of ZeroMQ the socket library from outer space. I have really enjoyed learning about ZeroMQ (which I did by reading “The Guide”,  several times over) and playing around with NetMQ, where I even did a joint article about with NetMQs author Doron (who is a very smart guy indeed). Basically its a great library, and very interesting and lots of fun, and very light weight, with no dependencies at all.

Anway enough of the advertising, how is the documentation coming along? Well, over the past week I have made some good progress on the NetMQ documentation.

The following pages are now semi-ready (pretty much there truth be told)

Over the next week I hope to finish some more. I will notify you all when I have done some more, and again when it all gets released to become the final “official” docs.

If you have not used NetMQ I urge you to have a look, experiment, that is how I started, and now I love it, and can honestly see many places where it is a excellent fit

Anyway enjoy, over and out for now

Distributed Systems

NetMQ : Documentation

I don’t know how many of you managed to read my series of articles on NetMQ

https://sachabarbs.wordpress.com/distributed-systems/

Or followed my last codeproject article, which made use of NetMQ to create a streaming server/client(s).

http://www.codeproject.com/Articles/853476/NetMQplus-RX-Streaming-Data-Demo-App-of

I did this one with the help of the author of NetMQ Doron. After we did that article Doron and I had a small chat about me possibly becoming more active on NetMQ in general. I suggested one way in which I might be able to help, was to write some documentation for NetMQ, as this is one area where sadly this great library is lacking a bit.

Doron liked this idea (guess documentation aint for everyone huh)

 

Doron (NetMQ author) and I will be working on this together, and I will be running any documentation I write by him first, but that is one area where I will be helping out, so you can expect to see me post a few more posts here from time to time, saying that some new documentation is available for NetMQ.

I hope that makes at least a few folks happy out there

 

 

 

 

 

 

C#, CodeProject

Scheduling With Quartz.Net

The other day I have a requirement to schedule something in my app to run at certain times, and at fixed intervals there after. Typically I would just solve this using either a simple Timer, or turn to my friend Reactive Extensions by way of Observable.Timer(..).

Thing is I decided to have a quick look at something I have always known about but never really used, for scheduling, which is Quartz.net, which actually does have some pretty good documentation up already:

http://www.quartz-scheduler.net/documentation/quartz-2.x/tutorial/index.html

For me I just wanted to get something very basic up and running, so I gave it a blast.

Step 1 : Install Quartz.net

This is as easy as installing the following NuGet package “Quartz

Step 2 Create A Job Class

This again is fairly easy thanks to Quartz nice API. Here is my job class

using System;
using Quartz;

namespace FooBar
{
    public class LoggingJob : IJob
    {
        public void Execute(IJobExecutionContext context)
        {


            Common.Logging.LogManager.Adapter.GetLogger("LoggingJob").Info(
                string.Format("Logging job : {0} {1}, and proceeding to log", 
                    DateTime.Now.ToShortDateString(), DateTime.Now.ToLongTimeString()));

        }
    }
}

That is all you need for a job really. The context object gives you access to a lot of useful stuff.

Step 3 : Setting up a schedule

Again this was mega easy, all I had to do was something like this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Common.Logging;

using Quartz;
using Quartz.Impl;

namespace FooBar
{
    class Program
    {

        private static ILog Log = LogManager.GetCurrentClassLogger();

        static void Main(string[] args)
        {
            try
            {
                // construct a scheduler factory
                ISchedulerFactory schedFact = new StdSchedulerFactory();

                // get a scheduler
                IScheduler sched = schedFact.GetScheduler();
                sched.Start();

                IJobDetail job = JobBuilder.Create<LoggingJob>()
                    .WithIdentity("myJob", "group1")
                    .Build();

                ITrigger trigger = TriggerBuilder.Create()
                    .WithDailyTimeIntervalSchedule
                    (s =>
                        s.WithIntervalInSeconds(10)
                            .OnEveryDay()
                            .StartingDailyAt(TimeOfDay.HourAndMinuteOfDay(10, 15))
                    )
                    .Build();

                sched.ScheduleJob(job, trigger);
            }
            catch (ArgumentException e)
            {
                Log.Error(e);
            }


        }
    }
}

And that was enough for my job to get scheduled, every 10 seconds starting at 10:15 AM.

I was fairly happy with Quartz, and I will certainly make more use of it, when I have bigger, bolder, badder scheduling needs.

MVP

MVP 2015 : New Years Treat

So I have been enjoiying my XMAS period off, and have not touched my computer in a while, and when I did finally check my email, I was quite pleased to find an email saying that I have been selected as an MVP again.

I never take this award for granted, and it is nice to get it, so I do actually feel quite privileged to have this award.

So thanks Microsoft.