Mouse Double Click for WPF in MVVM using a clean Behavior with Command Binding

I wanted to capture the double click event, which is actually the MouseLeftButtonDown with the e.ClickCount ==2.

Since I transitioned to a new WPF project, handed off the Silverlight work, I have been trying to keep the same MVVM pattern. I wanted to get the double click off of my TreeViewItem so the child node could invoke the ViewModel to execute a Command.

Here is the behavior I wrote to handle this simple task.

Snippet

using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Controls;

namespace Seekford.Behaviors
{
    public static class MouseDoubleClickBehavior
    {
        /// <summary>
        /// Hooks up a weak event against the source Selectors MouseDoubleClick
        /// if the Selector has asked for the HandleDoubleClick to be handled
        ///�
        /// If the source Selector has expressed an interest in not having its
        /// MouseDoubleClick handled the internal reference
        /// </summary>
        private static void OnHandleDoubleClickCommandChanged(DependencyObject d,
            DependencyPropertyChangedEventArgs e)
        {
            FrameworkElement ele = d as FrameworkElement;
            if (ele != null)
            {
                ele.MouseLeftButtonDown -= OnMouseDoubleClick;
                if (e.NewValue != null)
                {
                    ele.MouseLeftButtonDown += OnMouseDoubleClick;
                }
            }
        }

        /// <summary>
        /// TheCommandToRun : The actual ICommand to run
        /// </summary>
        public static readonly DependencyProperty DoubleClickCommandProperty =
            DependencyProperty.RegisterAttached("DoubleClickCommand",
                typeof(ICommand),
                typeof(MouseDoubleClickBehavior),
                new FrameworkPropertyMetadata((ICommand)null,
                    new PropertyChangedCallback(OnHandleDoubleClickCommandChanged)));

        /// <summary>
        /// Gets the TheCommandToRun property. �
        /// </summary>
        public static ICommand GetDoubleClickCommand(DependencyObject d)
        {
            return (ICommand)d.GetValue(DoubleClickCommandProperty);
        }

        /// <summary>
        /// Sets the TheCommandToRun property. �
        /// </summary>
        public static void SetDoubleClickCommand(DependencyObject d, ICommand value)
        {
            d.SetValue(DoubleClickCommandProperty, value);
        }

        #region Handle the event

        /// <summary>
        /// Invoke the command we tagged.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private static void OnMouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            //check for double clicks.
            if (e.ClickCount != 2)
                return;
            FrameworkElement ele = sender as FrameworkElement;

            DependencyObject originalSender = e.OriginalSource as DependencyObject;
            if (ele == null || originalSender == null)
                return;

            ICommand command = (ICommand)(sender as DependencyObject).GetValue(DoubleClickCommandProperty);

            if (command != null)
            {
                if (command.CanExecute(null))
                    command.Execute(null);
            }
        }
        #endregion
    }

}

Hopefully this helps you.

Oh, how to use. Almost forgot:

Snippet

xmlns:infraBehaviors="clr-namespace:Seekford.Behaviors;assembly=Seekford"

Snippet

 <Grid infraBehaviors:MouseDoubleClickBehavior.DoubleClickCommand="{Binding MyCommand}"  HorizontalAlignment="Stretch" >
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto"/>       �
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition></RowDefinition>
                </Grid.RowDefinitions>
                <TextBlock Text="{Binding Name}" TextWrapping="Wrap" FontWeight="Bold"  Grid.Column="0"  />
            </Grid>

Of course, make your own namespace and correct accordingly. But you already knew that.

Happy Coding!

Config file issue to make you rip hair out

I spent about 2 hours staring at this lovely cryptic error:
Extension element ‘silverlightFaults’ cannot be added to this element.  Verify that the extension is registered in the extension collection at system.serviceModel/extensions/behaviorExtensions

I had it setup correctly, but why would the system not compile it?

This was the registration:

<add name="silverlightFaults"
type="Seekford.SilverlightFaultBehavior.SilverlightFaultBehavior,Seekford.SilverlightFaultBehavior, Version=1.0.0.0, Culture=neutral, PublicKeyToken=7073c134a4dabf61" />

So? What is wrong with this picture? Nothing unless you are an unforgiving parse engine that exists to make life difficult.

I had to add a space. Yes, a space between the class and assembly name and BAM!, it worked.

<add name="silverlightFaults"
type="Seekford.SilverlightFaultBehavior.SilverlightFaultBehavior, Seekford.SilverlightFaultBehavior, Version=1.0.0.0, Culture=neutral, PublicKeyToken=7073c134a4dabf61" />

What a pile of #$%!!

Anyway, remember your spacing.

Happy Coding!

DateTimePicker Validation Error Block Calendar Button

I had a lot of user complaints about the tooltip for the DateTime Picker for Silverlight showing the error tooltip over the Calendar button. It made it so that it was next to impossible to actually select a date, since you couldn’t click the button.

I opened the DateTimePicker template and voila! The tard who made such a nice control set the error template to sit next to the TextBox instead of the Button.

Simple fix. Just generate the  DateTimePicker template (Expression Blend) and change the following section:
i.e. Search for ToolTipService.ToolTip

<ToolTipService.ToolTip>
<ToolTip x:Name="validationTooltip" Template="{StaticResource CommonValidationToolTipTemplate}" Placement="Right" PlacementTarget="{Binding ElementName=Button}" DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}">
<ToolTip.Triggers>
<EventTrigger RoutedEvent="Canvas.Loaded">
<BeginStoryboard>
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="validationTooltip" Storyboard.TargetProperty="IsHitTestVisible">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<System:Boolean>true</System:Boolean>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ToolTip.Triggers>
</ToolTip>
</ToolTipService.ToolTip>

Using Change the above to Button instead of TextBox. Super easy!

Happy Coding!

Deep Clone objects in Silverlight with simple extension method and Serialization

I had the need to clone objects to do original vs modified delta checks. I decided that I could either do a lot of work to make copies or go the easy route. As always, smarter over harder prevailed.

Here is a simple extension class to put into your infrastructure. Enjoy!


using System;
using System.IO;
using System.Xml.Serialization;

namespace Seekford.Extensions
{
public static class ObjectCopyMachine
{
/// <summary>
/// Extension to perform a deep Copy of the object specified.
/// </summary>
/// <typeparam name="T">The type of object being copied.</typeparam>
/// <param name="source">The object instance to copy.</param>
/// <returns>The copied object.</returns>
public static T Clone<T>(this T source)
{
if (!typeof(T).IsSerializable)
{
throw new ArgumentException("The type must be serializable.", "source");
}

// Don't serialize a null object, simply return the default for that object
if (Object.ReferenceEquals(source, null))
{
return default(T);
}
XmlSerializer serializer = new XmlSerializer(source.GetType());
Stream stream = new MemoryStream();
using (stream)
{
serializer.Serialize(stream, source);
stream.Seek(0, SeekOrigin.Begin);
return (T)serializer.Deserialize(stream);
}
}
}
}


Now you can just call any object and say. Abracadabra……      myObject.Clone();

Happy Coding!

ToObservableCollection for Linq and other purposes

Easily convert your Lists and enumerable collections and queries into an observable collection. I use this all the time for simplifying my Linq statements for inline calls.


using System.Collections.Generic;
using System.Collections.ObjectModel;

namespace Seekford.Extensions
{
/// <summary>
/// Class for helping the conversion of types to observable collections, easier linq coding.
/// </summary>
public static  class ObservableExtension
{
/// <summary>
/// Exports the observable collection.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="collection">The collection.</param>
/// <returns></returns>
public static ObservableCollection<T> ToObservableCollection<T>(this IEnumerable<T> collection)
{
return new ObservableCollection<T>(collection);
}

/// <summary>
/// Exports the observable collection.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="list">The list.</param>
/// <returns></returns>
public static ObservableCollection<T> ToObservableCollection<T>(this List<T> list)
{
return new ObservableCollection<T>(list);
}


}
}

Happy Coding!

Dynamic service endpoint binding for Silverlight using WCF

As part of my continuing effort in create a high quality line of business application in Silverlight, I am laying out a nice foundation for the repository layer. The services interaction is being shielded from the higher layers.

The main hurdle that was annoying me was having to change the endpoint the Silverlight application was pointing by editing a configuration file that was embedded in the application. Mainly, the fact that this required a recompile when going from local build to server. What a pain!!! Bad Microsoft…Bad..

I decided to just write a simple addition to my factory to generate the endpoints on the fly, no more recompile per site required. This also lets the application easily be moved server to server without any pains. Relative WCF URLS should have been a mandatory addition, but alas their not. If Microsoft had thought of everything, I wouldn’t have a job I guess.

Here is the simple code to do a dynamic endpoint in Silverlight. Enjoy!

using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Windows;

namespace Seekford.Repository.MyServices
{
    internal class MyServiceFactory
    {
        private const string myServiceLocation = "../Services/MyCService.svc";

        /// <summary>
        /// Creates the binding.
        /// </summary>
        /// <returns></returns>
        private static CustomBinding CreateBinding()
        {
            CustomBinding binding = new CustomBinding();
            binding.Name = "SilverlightBindingGoodTimes";
           binding.Elements.Add(new BinaryMessageEncodingBindingElement());
            binding.Elements.Add(new HttpTransportBindingElement()
                {
                    MaxBufferSize = int.MaxValue,
                    MaxReceivedMessageSize = int.MaxValue
                }
            );

            binding.OpenTimeout = new TimeSpan(0, 5, 0);
            binding.CloseTimeout = new TimeSpan(0, 5, 0);
            binding.ReceiveTimeout = new TimeSpan(0, 5, 0);
            binding.SendTimeout = new TimeSpan(0, 5, 0);         

            return binding;
        }

        /// <summary>
        /// Creates the aand C service client.
        /// </summary>
        /// <returns></returns>
        public static MyServiceClient CreateMyServiceClient()
        {
            var binding = CreateBinding();
            return new MyServiceClient (binding, new EndpointAddress(
                new Uri(Application.Current.Host.Source, myServiceLocation )));
        }       

    }
}

You will obviously need to tailor to your needs, but the idea is pretty straight forward.

Happy coding!