Sunday, 18 August 2013

Keyboard Command Gestures using Rx

This is another very beautiful use of Rx. The following program demonstrates how the app starts listening to commands when user presses space bar twice within the timespan of 1.5 seconds. To tell the user that I am listening, it can kick of a glowing animation, here I have just made a thick border visible. Now if the user stops and types nothing, the app stops listening. If the user continues to type, the next token entered is matched by any of the app commands and the subsequent token is then the command parameter. Line of business applications really become a lot more comforting to work on with such commanding flexibility:-

Enjoy Rx-ing!


using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApplication2
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            TaskScheduler _uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();

            List<string> commandList = new List<string> { "(DS)", "(DEAL)", "(DEALSEARCH)", "(DEALVIEW)", "(DEALFILTER)",
                "(SS)", "(SHIP)", "(PS)", "(PAR)" };
            string commandRegex = string.Format("^{0}",string.Join("|",commandList));

            InitializeComponent();
         
            string command = string.Empty;

            var textChangedEvent = Observable.FromEventPattern(this, "KeyUp");

            textChangedEvent.Subscribe(
                e =>
                {
                    var key = ((KeyEventArgs)e.EventArgs).Key.ToString();
                    command += key;
                }
                );

            textChangedEvent.Subscribe(
                t =>
                {
                    if (Regex.IsMatch(command, "^(Space)(Space)+"))
                    {

                        Task.Factory.StartNew(() => { border.BorderThickness = new Thickness(5); }, System.Threading.CancellationToken.None,
                               TaskCreationOptions.None, _uiScheduler
                               );
                    }
                }
            );

            textChangedEvent.Throttle(TimeSpan.FromMilliseconds(1500)).Subscribe(
                t =>
                {
                    if (Regex.IsMatch(command, "^(Space)(Space)+"))
                    {
                     
                        command = Regex.Replace(command, "^(Space)*", "");
                        if(Regex.IsMatch(command,commandRegex))
                            ExecuteCommand(Regex.Match(command, commandRegex).Value, Regex.Replace(command, commandRegex, "").Replace("Space", ""));
                                             

                        Task.Factory.StartNew(() => { border.BorderThickness = new Thickness(0); }, System.Threading.CancellationToken.None,
                             TaskCreationOptions.None, _uiScheduler
                             );

                    }

                    command = "";
                }
                );

        }

        private void ExecuteCommand(string command, string parameter)
        {
            MessageBox.Show(string.Format("Command={0} Parameter={1}", command, parameter));
        }

     

    }
}


Monday, 8 July 2013

Custom Markup Extensions & Type Converters

There are times when we need to extend the xaml to support some special features for our application. A very simple example is like We have a textbox which takes firstname and lastname and displays it in the format 'LastName, FirstName', We can obviously format the string, but just to demonstrate what Markup extensions can do:-

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

namespace WpfApplication3
{
    public class MyMarkupExtension:MarkupExtension
    {
        [ConstructorArgument("FirstName")]
        public string FirstName { get; set; }

        [ConstructorArgument("LastName")]
        public string LastName { get; set; }


        public MyMarkupExtension()
        {

        }

        public MyMarkupExtension(string FirstName, string LastName)
        {
            this.FirstName = FirstName;
            this.LastName = LastName;
        }



        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            return LastName + ", " + FirstName;
        }
    }
}



and in the xaml we write:-

<TextBlock Text="{local:MyMarkup FirstName=Shivakant, LastName=Upadhyay}"/>   


The result is visible even in the design time environment:-




Now for type converters, suppose you want to bind a special type to your program, for which there is no built in sonverter. For example you have a type called StringList which can hold string in comma seperated format and convert it back and forth to Enumerable. You want to supply this as ItemsSource of a list. For this you need the following TypeConverter


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

namespace WpfApplication3
{
    public class MyTypeconverter:TypeConverter
    {
        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            return sourceType == typeof(string);
        }

        public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
        {
            return destinationType == typeof(string);
        }

        public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
        {
            return value==null?string.Empty:string.Join(",", string.Join(",", ((StringList)value)));
        }

        public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
        {
            return new StringList((string)value);
        }

    }
}


Also you will need to decorate your type with TypeConverter attribute:-
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WpfApplication3
{
    [TypeConverter(typeof(MyTypeconverter))]
    public class StringList : IEnumerable<string>
    {
        private readonly IEnumerable<string> _enumerable;
        private readonly string _original;

        public StringList(string value)
        {
            _original = value;
            if (!string.IsNullOrEmpty(value))
            {
                _enumerable = value.Split(",;".ToCharArray()).
                  Where(i => !string.IsNullOrWhiteSpace(i)).Select(i => i.Trim());
            }
        }

        protected StringList(IEnumerable<string> value)
        {
            _enumerable = value;
            _original = string.Join(", ", value);
        }

        public StringList() { }

        public IEnumerator<string> GetEnumerator()
        {
            return _enumerable.GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return _enumerable.GetEnumerator();
        }

        public override string ToString()
        {
            return _original;
        }
    }
}


That's all, now you can use your type in xaml.


Friday, 5 July 2013

Special MVVM scenarios

You want to use a custom Binding but the control does not support binding in the area you want. What are your options? Which would you choose and why?


For example, you have a textbox and you want to associate a command to it which is fired for every key up event. Also you want another command on the same textbox to be fired on key return. What can you do?

Answer:-

The easiest solution is to create an attached behavior. Let us create a class with a dependency property


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

namespace SU.Behaviours
{
    public static class KeyUpBehaviour
    {
        public static DependencyProperty KeyUpCommandProperty = DependencyProperty.RegisterAttached("KeyUp",
                    typeof(ICommand),
                    typeof(KeyUpBehaviour),
                    new FrameworkPropertyMetadata(null, new PropertyChangedCallback(KeyUpBehaviour.KeyUpChanged)));

        public static void SetKeyUp(DependencyObject target, ICommand value)
        {
            target.SetValue(KeyUpBehaviour.KeyUpCommandProperty, value);
        }

        public static ICommand GetKeyUp(DependencyObject target)
        {
            return (ICommand)target.GetValue(KeyUpCommandProperty);
        }


        private static void KeyUpChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
        {
            UIElement element = target as UIElement;
            if (element != null)
            {
                // If we're putting in a new command and there wasn't one already
                // hook the event
                if ((e.NewValue != null) && (e.OldValue == null))
                {
                    element.KeyUp += new KeyEventHandler(element_KeyUp);
                }
                // If we're clearing the command and it wasn't already null
                // unhook the event
                else if ((e.NewValue == null) && (e.OldValue != null))
                {
                    element.KeyUp -= element_KeyUp;
                }
            }
        }

        static void element_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Down || e.Key == Key.Up)
                return;

            UIElement element = (UIElement)sender;
            ICommand command = (ICommand)element.GetValue(KeyUpBehaviour.KeyUpCommandProperty);
            command.Execute(null);
        }
    }

    //Creating our own Delegate Command
    public sealed class DelegateCommand : ICommand
    {
        public delegate void SimpleEventHandler();
        private SimpleEventHandler handler;
        private bool isEnabled = true;

        public event EventHandler CanExecuteChanged;

        public DelegateCommand(SimpleEventHandler handler)
        {
            this.handler = handler;
        }

        private void OnCanExecuteChanged()
        {
            if (this.CanExecuteChanged != null)
            {
                this.CanExecuteChanged(this, EventArgs.Empty);
            }
        }

        bool ICommand.CanExecute(object arg)
        {
            return this.IsEnabled;
        }

        void ICommand.Execute(object arg)
        {
            this.handler();
        }

        public bool IsEnabled
        {
            get
            {
                return this.isEnabled;
            }
            set
            {
                this.isEnabled = value;
                this.OnCanExecuteChanged();
            }
        }
    }

}


Similarly we can also have another one for key return:-


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

namespace SU.Behaviours
{
    public static class KeyReturnBehaviour
    {
        public static DependencyProperty KeyReturnCommandProperty = DependencyProperty.RegisterAttached("KeyReturn",
                    typeof(ICommand),
                    typeof(KeyReturnBehaviour),
                    new FrameworkPropertyMetadata(null, new PropertyChangedCallback(KeyReturnBehaviour.KeyReturnChanged)));

        public static void SetKeyReturn(DependencyObject target, ICommand value)
        {
            target.SetValue(KeyReturnBehaviour.KeyReturnCommandProperty, value);
        }

        public static ICommand GetKeyReturn(DependencyObject target)
        {
            return (ICommand)target.GetValue(KeyReturnCommandProperty);
        }


        private static void KeyReturnChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
        {
            UIElement element = target as UIElement;
            if (element != null)
            {
                // If we're putting in a new command and there wasn't one already
                // hook the event
                if ((e.NewValue != null) && (e.OldValue == null))
                {
                    element.KeyUp += new KeyEventHandler(element_KeyReturn);
                }
                // If we're clearing the command and it wasn't already null
                // unhook the event
                else if ((e.NewValue == null) && (e.OldValue != null))
                {
                    element.KeyUp -= element_KeyReturn;
                }
            }
        }

        static void element_KeyReturn(object sender, KeyEventArgs e)
        {
            if (e.Key != Key.Return)
                return;

            UIElement element = (UIElement)sender;
            ICommand command = (ICommand)element.GetValue(KeyReturnBehaviour.KeyReturnCommandProperty);
            command.Execute(null);
        }
    }

}



Formatting Strings in XAML with multibinding


          <TextBlock.Text>
            <MultiBinding StringFormat="{}{0} x {1} Test">
              <Binding ElementName="sl1" Path="Value" />
              <Binding ElementName="sl2" Path="Value" />
            </MultiBinding>

Sunday, 30 June 2013

Simple MVVM DialogService

If you are reading this, probably you know already that in MVVM we use services for displaying dialogs so that out code can stay loosely coupled and testable. A simple implementation of Dialog Service is given below:-

Interface:-

    public interface IDialogService
    {
        MessageBoxResult ShowMessageBox(string content,
        string title, MessageBoxButton buttons);
        void ShowDialog(ViewModelBase viewModel, Window dialog);
        ViewModelBase ViewModel { get; set; }
        Window DialogWindow { get; set; }
    }

Implementation:-

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using BP = BPCodeScreening.Infrastructure;
using BPCodeScreening.Infrastructure.Services;

namespace DialogServiceExample.Infrastructure.Services
{
 
    public class DialogService : IDialogService
    {
        public ViewModelBase ViewModel { get; set; }
        public Window DialogWindow { get; set; }
        public MessageBoxResult ShowMessageBox(string content,

        string title, MessageBoxButton buttons)
        {
            return MessageBox.Show(content, title, buttons);
        }

   
        public void ShowDialog(ViewModelBase viewModel, Window dialog)
        {
            DialogWindow = dialog;
            ViewModel = viewModel;
            dialog.Title = viewModel.Title;
            dialog.DataContext = ViewModel;
            dialog.Owner = Application.Current.MainWindow;
            dialog.ShowInTaskbar = false;
            dialog.ShowDialog();
        }
    }
}


Usage: A good way to use this is to ask the dependency injection container to give you the instance and then call ShowDialog() on it:-

var  _dialogService = container.Resolve<DialogService>();
_dialogService.ShowDialog(new ModalMessageBoxViewModel { Title = "Information", Message = m }, new MyDialogView()));

MyDialogView is just an empty window used to inject the DataTemplate of your viewModel. Do not forget to specify the data template for your dialog's view model in the app.xaml file:-

        <DataTemplate DataType="{x:Type local:ModalMessageBoxViewModel}">
            <views:MessageView/>
        </DataTemplate>


Easy, Isn't it?        

Thanks & Enjoy!


Fun with Concurrent Collections...

Recently, I was writing a program which used a collection which was accessed by many threads. My obvious choice was to use one of the .net thread safe collections. I chose ConcurrentBag and stumbled upon something. In-fact things could easily go wrong if you do not have proper understanding. I was basically using Concat operator to add collections returned from my threads. But the resulting bag was not showing up any item. Let's play around this little thingy and see how it works. Let us start with the following self contained program:-


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

namespace MyConsoleApplication
{
    public class Trade
    {
        public string TradeId { get; set; }
        public string Ticker { get; set; }
        public double Price { get; set; }
    }

    public class CSVLoader
    {
        public string path { get; set; }

        public List<Trade> LoadBlotter()
        {
            var trades = new List<Trade>();

            using (var reader = new StreamReader(File.OpenRead(path)))
            {
                while (!reader.EndOfStream)
                {
                    var tline = reader.ReadLine().Split(',');
                    Trade t = new Trade() { TradeId = tline[0], Ticker = tline[1], Price = Convert.ToDouble(tline[2]) };
                    trades.Add(t);
                }
            }

            return trades;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            List<CSVLoader> loaders = new List<CSVLoader>();
            loaders.Add(new CSVLoader { path = "Blotters\\blotter1.txt"});
            loaders.Add(new CSVLoader { path = "Blotters\\blotter2.txt" });
            loaders.Add(new CSVLoader { path = "Blotters\\blotter3.txt" });

            //List to store resultant trades
            List<Trade> alltrades = new List<Trade>();
            loaders.ForEach(l => alltrades.AddRange(l.LoadBlotter()));

            Console.WriteLine("Total trades read="+alltrades.Count);

            Console.ReadLine();

        }
    }
}




Blotter files are nothing but a bunch of dummy trades in txt file. I copy paste the following lines multiple times:-

1,AAAA,0.8
2,BBBB,0.95


Now we have a working program which runs great and load trades, but not in parallel. Now lets change the code from:-

            loaders.ForEach(l => alltrades.AddRange(l.LoadBlotter()));

To

            loaders.AsParallel.ForAll(l => alltrades.AddRange(l.LoadBlotter()));

Bingo!! It runs great (if you are lucky). But try to run it a few more times, it will surprise you with :-


Now what's that. We somehow knew that something was going to blow away as we never used a thread safe collection. But the error says index out of range!!! WTF??

This is because, unsafe collections are allocated size as and when required in chunks of exponents of two i.e. 2,4,8,16,32 etc.. whenever current size gets exhausted. In this case a thread came in, tried to allocate more memory but before that another thread tried to use it, which gets this exception.


Now What?? Use Concurrent Bag! But lets see how it works.

Lets include:-
using System.Collections.Concurrent;

and change the code from
List<Trade> alltrades = new List<Trade>();
To
ConcurrentBag<Trade> alltrades = new ConcurrentBag<Trade>();


Now the immediate problem we see is that ConcurrentBag doesn't have AddRange function, so I thought I would use Concat rather. Changed it to concat & to my surprise, what happened was:-



So it doesn't work, this is because theoretically only sequences can be concatenated!

Now what are our options?? Union doesn't work either. My way to cope up with this problem is describes as follows.


Change LoadBlotter function to accept ConcurrentBag


        public void LoadBlotter(ConcurrentBag<Trade> alltrades)
        {


            using (var reader = new StreamReader(File.OpenRead(path)))
            {
                while (!reader.EndOfStream)
                {                  
                    var tline = reader.ReadLine().Split(',');
                    Trade t = new Trade() { TradeId = tline[0], Ticker = tline[1], Price = Convert.ToDouble(tline[2]) };
                    alltrades.Add(t);
                }
            }
        }



and in your calling code:-
            ConcurrentBag<Trade> alltrades = new ConcurrentBag<Trade>();
            loaders.AsParallel().ForAll(l => l.LoadBlotter(alltrades));



So basically, you are passing the bag as a reference and threads will add to them one at a time. This works great and is probably the correct way of using a ConcurrentCollection.

There is one more collection which can be used here that is BlockingCollection. This is similar to ConcurrentBag in a way that both of them implement IPropducerConsumerCollection<T>. The difference between the two is however very important.


ConcurrentBag<T> Vs BlockingCollection<T>

Let's see what is the definition of BlockingCollection:-
BlockingCollection<T> is used as a wrapper for an IProducerConsumerCollection<T> instance, allowing removal attempts from the collection to block until data is available to be removed. Similarly, a BlockingCollection<T> can be created to enforce an upper-bound on the number of data elements allowed in the IProducerConsumerCollection<T

So this makes it clear that if we are just adding to collection and will need the collection only after we have added everything, we would rather use ConcurrentBag as it will be faster. BlockingCollection will only be required when we want readers to block unless the item is found. In other words, in circumstances when we know that some item is about to come and we can use them concurrently.


Any more suggestions and explanations regarding above behavior of concurrent collection is welcome!