Prash's Blog

Create Custom Routing Events in WPF May 19, 2010

Filed under: WPF — prazjain @ 10:46 pm
Tags: ,

WPF provides a ton of events in its library, but its not too tough if you have to create a custom event to support a specific scenario.
In a small example below we will create a custom event that would sort the text we enter in the textbox.
Screen before and after the command execution :

  • Create a new WPF project, name it CustomEvents.
  • Copy paste the XAML below in Window1.xaml file

<StackPanel>
 <TextBox Name="textBox" Margin="10,10" />
 <Button Name="btnSort" HorizontalAlignment="Center" Padding="10,3" FontWeight="Bold" Margin="10,3">Sort</Button>
 </StackPanel>

  • Create a custom command for our use:

/// <summary>
 /// Class that holds the custom command(s)
 /// </summary>
 public class SortCommand
 {
 /// <summary>
 /// Actual command object
 /// </summary>
 private static RoutedUICommand sortCommand;

 /// <summary>
 /// Property exposing the command object
 /// </summary>
 public static RoutedCommand Sort
 {
 get { return sortCommand; }
 }

 /// <summary>
 /// Static constructor initializing the input gestures that should invoke the custom command
 /// </summary>
 static SortCommand()
 {
 InputGestureCollection gestures = new InputGestureCollection();
 gestures.Add(new KeyGesture(Key.S, ModifierKeys.Control, "Control-S"));
 sortCommand = new RoutedUICommand("Sort Command", "Sort", typeof(SortCommand), gestures);
 }
 }

  • Now we have created a custom command and we have a UI in place. Now linkup the command object and the UI. Assuming you have not renamed Window1.xaml, paste the code below into your Window1.xaml.cs.

/// <summary>
 /// Interaction logic for Window1.xaml
 /// </summary>
 public partial class Window1 : Window
 {
 public Window1()
 {
 InitializeComponent();
// attach the command to the button so the command can be invoked on button click
 btnSort.Command = SortCommand.Sort;
// create a command binding and attach actual handlers to the command.
 CommandBinding binding = new CommandBinding();
 binding.Command = SortCommand.Sort;
 binding.CanExecute += new CanExecuteRoutedEventHandler(binding_CanExecute);
 binding.Executed += new ExecutedRoutedEventHandler(binding_Executed);
//add the command binding to window, so it would handle the execute event
 this.CommandBindings.Add(binding);
 }

 void binding_Executed(object sender, ExecutedRoutedEventArgs e)
 {
 char[] contents = textBox.Text.ToCharArray();
 Array.Sort(contents);
 textBox.Text = new string(contents);
 }

 void binding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
 {
// we sort only if there is some text
 e.CanExecute = textBox.Text.Length > 0;
 }
 }

When the button is clicked as there is no command binding associated with the Sort command there, the event is routed up the element tree
where the window handles the executed event.

 

Entity Framework 4.0 supports POCO May 13, 2010

Filed under: C#,Entity Framework — prazjain @ 8:49 pm
Tags: , ,

POCO – Plain Old CLR Object

In Entity Framework 3.5 an Entity Class had to extend EntityObject class which in turn implemented IEntityWithKey, IEntityWithChangeTracker, IEntityWithRelationships. All of this meant more persistence logic into a domain object, a place where it does not belong. It also made testing of these domain object a bit more complicated.

Entity Framework 4.0 now supports POCO, so simple implementation like below could be used with EF 4.0 (database used with this example is the Microsoft AutoLot database).


public class Customers {

public int CustID {   get;   set;   }

public string FirstName {   get;   set;   }

public string LastName {   get;   set;   }

}

This also makes the code easier to test, and it extracts the persistence logic out of domain objects.

 

New C# Language Features in .Net 4.0 May 7, 2010

Filed under: C# — prazjain @ 11:31 pm
Tags: , , , ,

.Net 4.0 has added couple of new language features in C#

Dynamic Lookup

C# has added a new static type named ‘dynamic’. It supports late binding, so any calls to methods, properties, fields are not resolved at compile time. Thus an error arising due to its use is also detected at runtime.


dynamic person = GetPerson();

// A runtime error would be generated if the object returned by GetPerson() method does not has Name property

person.Name="Prashant";

‘dynamic’ type provides a lot of help to programmers dealing with COM objects in C#

Optional Parameters

C# now provides the ability to assign default values to method parameters incase the caller does not intend to pass value for a parameter.


void Print(string car="Mini Cooper", int price=15000)

{      Console.Writeln(string.format("Car : {0}, Price : {1}",car, price));  }

void M1()

{   Print("VW Golf");  }

Upon invoking M1(), it would print : “Car : VW Golf, Price : 15000”

This shows the parameter ‘price’ assumed the default value.

Named Parameter

Method parameters can now be assigned names, so its no longer necessary that method arguments are passed in the same order as method parameters.


void Print(string car="Mini Cooper", int price=15000)

{      Console.Writeln(string.format("Car : {0}, Price : {1}",car, price));  }

void M1()

{   Print(price: 16000, car: "VW Golf");  }

Upon invoking M1(), it would print : “Car : VW Golf, Price : 16000”

Covariance

Covariance means that an object can be treated as less derived. This features is used to return values from methods that are more abstract.


class Vehicle { ... }

class Car : Vehicle { ... }

class Test {

static void Main(string[] args)

{

...

IEnumerable<Car> cars = GetCars();

// this is now possible in .Net 4.0

IEnumerable<Vehicle> vehicles = cars;

// prior to .Net 4.0 it would have required going through 'cars' collection and add every object into a new collection vehicles

}

}

To allow Covariance the IEnumerable type is defined with an ‘out’ keyword


IEnumerable<out T> { ... }

‘out’ keyword says that its fine to take values out from the collection, adding values is not allowed.

Contravariance

Contravariance allows a more derived type argument to be passed into a less derived type method parameter.


class Vehicle { ... }

class Car : Vehicle { ... }

class Test

{

// Contravariance is enabled by using 'in' keyword

delegate void MyHandler<in T> (T a);

static void Main(string[] args)

{

MyHandler<Vehicle> handler = (veh) => { Console.Writeln(veh); }

// below line is now allowed in .Net 4.0

MyHandler<Car> carHandler = handler;

}

}

All that it means is contravariance allows a Car (subtype) to be passed into a method that requires Vehicle (base type), which could do not harm to the execution of method. But this is only allowed when the delegate generic definition uses ‘in’ keyword, without ‘in’ it would fail in .Net 4.0 too!

Events

Events in C# look like fields / properties. Operators += and -= are overloaded to map to add and remove accessor methods.

Prior to C# 4.0, these generated accessors were synchronized across threads using ‘lock(this)’ as the auto generated code decorated accessors with MethodImpl(MethodImpl.Synchronized) attribute, that meant instead of synchronizing access on that invoke ‘add’ & ‘remove’ method, it would synchronized access across any thread that capture lock on ‘this’ object.

To get across this problem, C# 4.0 changes the way the code is generated for these accessors, it generates code to test for race conditions and updates delegate list accordingly.

This should be a non-breaking changes unless your code is dependent on the way synchronization was implemented earlier.

 

How to use Routing Service in Virtual Earth / Bing May 3, 2010

Filed under: Bing — prazjain @ 8:19 pm
Tags: , , , ,

In my previous article on using Geocoding service in Virtual Earth I gave an introduction on how to geo code the address. See here.

In this article I will show how to use that geocoded data and calculate route information using Bing. In this article we would use the Bing Maps keys to authenticate rather than the client token that we used in last article as that if for staging environment. But if you are using the staging environment then I suggest that you use the staging url for the service wsdl and use the VEStagingToken webservice for authenticate (as shown in geocoding service article).

1) Add a service in your VS solution pointing to : http://dev.virtualearth.net/webservices/v1/routeservice/routeservice.svc?wsdl and name it VERouterServiceReference.

2) Create a class RouteFetcher which would hold code to get route information for the locations passed by you.

3) Brief description of what the code does : It uses the Bing Maps key for authentication. It creates a WayPoint object for every location passed by you and send it to the webservice for calculating the route. In the end returning a string representation of instructions for the multi leg journey.

PS : Does anyone know how to paste code without losing indenting ! I have a real bad time pasting my codes here.

/// <summary>
 /// Plans a route through the locations passed in argument in the order specified.
 /// </summary>
 /// <param name="locations">array of string location formatted as (latitude,longitude)</param>
 /// <returns></returns>
 public string Route(string[] locations)
 {
 try
 {
 string results = "";
 RouteRequest routeRequest = new RouteRequest();
 routeRequest.Credentials = new Credentials();
 //routeRequest.Credentials.Token = _clientToken;
 routeRequest.Credentials.ApplicationId = _key;

 Waypoint[] wayPoints = new Waypoint[locations.Length];

 int pointIndex = -1;
 foreach (string point in locations)
 {
 pointIndex++;
 wayPoints[pointIndex] = new Waypoint();
 string[] digits = point.Split(',');
 // ignore the location if the string is not correctly formatted
 if (digits.Length!=2) continue;
 wayPoints[pointIndex].Location = new Location() { Latitude = double.Parse(digits[0].Trim()), Longitude = double.Parse(digits[1].Trim()) };
 if (pointIndex == 0)
 wayPoints[pointIndex].Description = "Start";
 else if (pointIndex == locations.Length)
 wayPoints[pointIndex].Description = "End";
 else
 wayPoints[pointIndex].Description = string.Format("Stop #{0}", pointIndex);

 }

 routeRequest.Waypoints = wayPoints;

 RouteServiceClient routeServiceClient = new RouteServiceClient();
 RouteResponse routeResponse = routeServiceClient.CalculateRoute(routeRequest);

 StringBuilder directions = new StringBuilder("");
 if (routeResponse.Result.Legs.Length > 0)
 {
 int instructionIndex = 0;
 int legIndex = 0;
 foreach (var leg in routeResponse.Result.Legs)
 {
 directions.Append(string.Format("Leg #{0}\n", ++legIndex));
 foreach (var itineraryItem in leg.Itinerary)
 {
 directions.Append(string.Format("{0}. {1}\n", ++instructionIndex, itineraryItem.Text));
 }
 Regex regex = new Regex("<[a-z/:]*>",RegexOptions.IgnoreCase);
 results = regex.Replace(directions.ToString(),string.Empty);
 }
 }
 else
 results = "No routes found";

 return results;

 }
 catch (Exception ex)
 {
 Console.WriteLine(ex.Message);
 return "Exception occurred";
 }

 }