Wednesday, January 04, 2012

Linq is awesome and always makes tasks easier!  Here is a great tip that you might not know about.

Today I needed to compare two generic lists… SequenceEqual() to the rescue.  To show how it works, here is some sample code:

[Test]
public void SuccessfullyMatchesTwoListsOfInts()
{
    List<int> ints1 = new List<int>();
    ints1.Add(1);
    ints1.Add(2);
    ints1.Add(3);

    List<int> ints2 = new List<int>();
    ints2.Add(1);
    ints2.Add(2);
    ints2.Add(3);

    Assert.That(ints1.SequenceEqual(ints2), Is.True);
}

SequenceEqual loops through the 2 lists and compares each item to make sure they match.  Just for kicks I put it through the paces.  Here are some other unit tests that I wrote.  This helps show what you can do:

using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;

namespace SequenceEqual
{
    [TestFixture]
    public class SequenceEqualTests
    {
        [Test]
        public void SuccessfullyMatchesTwoListsOfInts()
        {
            List<int> ints1 = new List<int>();
            ints1.Add(1);
            ints1.Add(2);
            ints1.Add(3);

            List<int> ints2 = new List<int>();
            ints2.Add(1);
            ints2.Add(2);
            ints2.Add(3);

            Assert.That(ints1.SequenceEqual(ints2), Is.True);
        }

        [Test]
        public void SuccessfullyFailsTwoListsOfInts()
        {
            // these two don't match!
            List<int> ints1 = new List<int>();
            ints1.Add(1);
            ints1.Add(2);
            ints1.Add(3);

            List<int> ints2 = new List<int>();
            ints2.Add(1);
            ints2.Add(4);
            ints2.Add(3);

            Assert.That(ints1.SequenceEqual(ints2), Is.False);
        }

        [Test]
        public void SuccessfullyFailsTwoListsOfIntsOutOfOrder()
        {
            // these two don't match. They have the same contents but the order is changed.
            List<int> ints1 = new List<int>();
            ints1.Add(3);
            ints1.Add(2);
            ints1.Add(1);

            List<int> ints2 = new List<int>();
            ints2.Add(1);
            ints2.Add(2);
            ints2.Add(3);

            Assert.That(ints1.SequenceEqual(ints2), Is.False);
        }

        [Test]
        public void SuccessfullyFailsTwoListsOfStrings()
        {
            // these two lists of strings don't match
            List<string> strings1 = new List<string>();
            strings1.Add("one");
            strings1.Add("two");
            strings1.Add("three");

            List<string> strings2 = new List<string>();
            strings2.Add("one");
            strings2.Add("lasjdflkajsdf");
            strings2.Add("three");

            Assert.That(strings1.SequenceEqual(strings2), Is.False);
        }

        [Test]
        public void SuccessfullyMatchesTwoListsOfStrings()
        {
            // two matching lists of strings.
            List<string> strings1 = new List<string>();
            strings1.Add("one");
            strings1.Add("two");
            strings1.Add("three");

            List<string> strings2 = new List<string>();
            strings2.Add("one");
            strings2.Add("two");
            strings2.Add("three");

            Assert.That(strings1.SequenceEqual(strings2), Is.True);
        }

        [Test]
        public void SuccessfullyMatchesTwoListsOfObjects()
        {
            // works for objects too.
            List<TestObject> objects1 = new List<TestObject>();
            objects1.Add(new TestObject { Property1 = "1" });
            objects1.Add(new TestObject { Property1 = "2" });
            objects1.Add(new TestObject { Property1 = "3" });

            Assert.That(objects1.SequenceEqual(objects1), Is.True);
        }

        [Test]
        public void SuccessfullyFailsTwoListsOfObjects()
        {
            // these two lists of objects may "look" the same, but they aren't
            // the same object (reference equals!)
            List<TestObject> objects1 = new List<TestObject>();
            objects1.Add(new TestObject { Property1 = "1" });
            objects1.Add(new TestObject { Property1 = "2" });
            objects1.Add(new TestObject { Property1 = "3" });

            List<TestObject> objects2 = new List<TestObject>();
            objects2.Add(new TestObject { Property1 = "1" });
            objects2.Add(new TestObject { Property1 = "2" });
            objects2.Add(new TestObject { Property1 = "3" });

            Assert.That(objects1.SequenceEqual(objects2), Is.False);
        }

        [Test]
        public void SuccessfullyMatchesTwoListsOfObjectsWithCustomComparer()
        {
            // here I use a custom comparer to see if the 
            // two lists of objects have the same content.
            List<TestObject> objects1 = new List<TestObject>();
            objects1.Add(new TestObject { Property1 = "1" });
            objects1.Add(new TestObject { Property1 = "2" });
            objects1.Add(new TestObject { Property1 = "3" });

            List<TestObject> objects2 = new List<TestObject>();
            objects2.Add(new TestObject { Property1 = "1" });
            objects2.Add(new TestObject { Property1 = "2" });
            objects2.Add(new TestObject { Property1 = "3" });

            Assert.That(objects1.SequenceEqual(objects2, new TestObjectComparer()), Is.True);
        }

        [Test]
        public void SuccessfullyFailsTwoListsOfObjectsWithCustomComparer()
        {
            // making sure the custome comparer fails when they don't match
            List<TestObject> objects1 = new List<TestObject>();
            objects1.Add(new TestObject { Property1 = "1" });
            objects1.Add(new TestObject { Property1 = "2" });
            objects1.Add(new TestObject { Property1 = "3" });

            List<TestObject> objects2 = new List<TestObject>();
            objects2.Add(new TestObject { Property1 = "1" });
            objects2.Add(new TestObject { Property1 = "asdfsadf" });
            objects2.Add(new TestObject { Property1 = "3" });

            Assert.That(objects1.SequenceEqual(objects2, new TestObjectComparer()), Is.False);
        }
    }

    public class TestObject
    {
        public string Property1 { get; set; }
    }

    public class TestObjectComparer : IEqualityComparer<TestObject>
    {
        public bool Equals(TestObject x, TestObject y)
        {
            return (x.Property1 == y.Property1);
        }

        public int GetHashCode(TestObject obj)
        {
            return obj.GetHashCode();
        }
    }
}

Today I needed to compare to generic lists. I guessed that Linq would provide a way to do this and sure enough it did: SequenceEqual() to the rescue. To show how it work

 |  | 
Wednesday, January 04, 2012 10:23:16 PM (Eastern Standard Time, UTC-05:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Friday, December 09, 2011

I’m using TeamCity, MSBuild, and SVN together to do some pretty cool stuff around continuous integration and automated builds.  It’s been working well, untouched, for well over a year!  But all of a sudden my deployment process failed. Checking the logs with TeamCity, I found this:

[11:18:06]:   Error validating server certificate for 'https://[xxx].com:443':
[11:18:06]:    - The certificate is not issued by a trusted authority. Use the
[11:18:06]:      fingerprint to validate the certificate manually!
[11:18:06]:   Certificate information:
[11:18:06]:    - Hostname: [xxx]
[11:18:06]:    - Valid: from Mon, 29 Mar 2010 17:44:04 GMT until Thu, 26 Mar 2020 17:44:04 GMT
[11:18:06]:    - Issuer: [xxx]
[11:18:06]:    - Fingerprint: [xxx]
[11:18:06]:   (R)eject, accept (t)emporarily or accept (p)ermanently? svn: OPTIONS of 'https://[xxx]': Server certificate verification failed: issuer is not trusted (https://[xxx].com)

The best part about this was that, for a change, this error message was very clear.  Although I don’t know why the certificate failed.  Did it change or expire?  Did one of the network guys make a change to something?  I didn’t really care.  I just wanted to get my build working again.

Here is the line of MSBuild Script that caused the issue: (I’m using the SVN stuff from MSBuild Community Tasks)

<SvnClient Command="ls $(SvnRepository)/tags/$(BuildNumber) Username="$(SvnUserName)" password="$(SvnPassword)" ContinueOnError="true">
  <Output TaskParameter="ExitCode" PropertyName="Value"/>
</SvnClient>

Since the Command of SvnClient accepts any SVN command (in other words, anything that I can type at a command prompt), I searched the SVN Documentation.  It wasn’t hard to find that I just needed to update to this:

<SvnClient Command="ls $(SvnRepository)/tags/$(BuildNumber) --non-interactive --trust-server-cert" Username="$(SvnUserName)" password="$(SvnPassword)" ContinueOnError="true">
  <Output TaskParameter="ExitCode" PropertyName="Value"/>
</SvnClient>

This worked great but my build still failed.  That is because I have other SVN actions in my script and they don’t seem to know that I accepted the certificate. However, my other tasks are not using the very generic and flexible SvnClient Command, they are using tasks such as SvnCopy or SvnCommit, etc.  For instance:

<SvnCopy SourcePath="$(SvnRepository)/$(SvnProjectLocation)/"
    DestinationPath="$(SvnRepository)/tags/$(BuildNumber)"
    Message="Auto-tagging Revision: $(BuildNumber)"
    Username="$(SvnUserName)" password="$(SvnPassword)" />

So how could I tell SVN to accept the certificate.  I checked the MSBuild Community Tasks documentation, took a guess and got lucky on the first try…sweet.  I added this:

    <SvnCopy SourcePath="$(SvnRepository)/$(SvnProjectLocation)/"
        DestinationPath="$(SvnRepository)/tags/$(BuildNumber)"
        Message="Auto-tagging Revision: $(BuildNumber)"
        Username="$(SvnUserName)" password="$(SvnPassword)"
        Arguments="--non-interactive --trust-server-cert" />

I added the Arguments to all of my other SVN Tasks in my script and it worked perfectly!

Friday, December 09, 2011 9:23:56 AM (Eastern Standard Time, UTC-05:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Friday, April 01, 2011

Last night I had the pleasure of presenting “Unit Testing Made Easy” at NoDeNUG (Northern Delaware .Net User Group).  I’ll be doing the same demo at Philly.Net Code Camp next week.  The NoDeNUG crowd was great and asked good questions.  That made the demo fun for me and I think it went very well.  I hope it goes over great at Code Camp too. 

I’m attaching a zip file containing my slides and Visual Studio Solution.  The demo should work fine on it’s own, the references to NUnit, MOQ, and StructureMap are all included.  But if you don’t have VS2010 with Premium or Ultimate and Feature Pack 2, the CodedUI (testing for Silverlight UIs) won’t work.  I hope it will build and run ok though.  If not, let me know and I’ll upload the solution without references to the Coded UI stuff.  Also, the demo uses a Silverlight application for the front end.  If you don’t have the Silverlight tools set up, you can either add them to Visual Studio, or simply exclude the Silverlight projects.  You’ll still be able to run the services and the unit tests, even if you can’t see how the UI looks.

If you’ve just come across this and haven’t heard my presentation you have two options:

1. Come to Philly.Net Code Camp next week (April 9) and hear the presentation then!

2. Just open the enclosed solution and have a look!  I’ve got sample code in there to demonstrate using Dependency Injection to make services easier to unit test, sample unit tests, and sample tests using mocking of dependencies.  I’m coding my tests with NUnit, using StructureMap for my IOC, and MOQ as my mocking framework.

Here is the code:  UnitTestingMadeEasy.zip

Again, if you have any problems with the solution, let me know and I’ll upload a copy without the Coded UI, or even without the Silverlight part.

 |  |  |  |  |  |  |  | 
Friday, April 01, 2011 7:51:28 PM (Eastern Standard Time, UTC-05:00)  #    Disclaimer  |  Comments [1]  |  Trackback
 Sunday, December 26, 2010

In a previous post I wrote about some tips for creating WP7 apps which included using the CameraCaptureTask.  A reader responded, asking how to save the picture.  So I figured I’d write a more detailed response with some samples.

In this post I’ll show 3 easy sample:

  1. How to simply use the camera and display a photo.
  2. How to save an image to IsolatedStorage (and change the size of the photo too!)
  3. How to save an image to the phone’s media library.

All of these are pretty simple.  I’m sure once you get started you can easily modify this code to do more creative things. 

First, you’ll need to define a CameraCaptureTask.  You should always do so as a class level variable.   You should also wire up the Completed handler in the constructor  These steps are important for dealing with application tombstoning.  For more on this, please read this article.

private CameraCaptureTask _cameraCaptureTask;

public MainPage()
{
    InitializeComponent();

    _cameraCaptureTask = new CameraCaptureTask();
    _cameraCaptureTask.Completed += CameraCaptureTaskCompleted;

}

How to simply use the camera and display a photo:

You’ll need to kick off the camera task, I’m using a button.  
private void SimpleTest_Click(object sender, EventArgs e)
{
    try
    {
        _cameraCaptureTask.Show();
    }
    catch (InvalidOperationException ex)
    {
        // Catch the exception, but no handling is necessary.
    }

}
In my XAML, I’ve defined an Image named MainImage
<Image x:Name="MainImage" />

Now when the CameraCaptureTask is complete, just bind the results of the task to the Image as I’m doing here:

void CameraCaptureTaskCompleted(object sender, PhotoResult e)
{
    if (e.TaskResult == TaskResult.OK)
    {
        //simply use the picture.
        BitmapImage bitmapImage = new BitmapImage();
        bitmapImage.SetSource(e.ChosenPhoto);
        MainImage.Source = bitmapImage;
    }
}

Easy, right?

How to save an image to IsolatedStorage (and change the size of the photo too!)

In this case I want to save the image to IsolatedStorage.  In addition, the app I was creating didn’t need full size images.  So I figured, why waste space in the user’s IsolatedStorage?  So I use a WritableBitmap and change the size of the image.  You’ll notice that after I save the image, I read it back and bind the results to another image named SmallerImage.  That’s just to prove that saving it really worked!

void CameraCaptureTaskCompleted(object sender, PhotoResult e)
{
    if (e.TaskResult == TaskResult.OK)
    {
        //here I save the image to Isolated Storage.  Also I am changing the size of it to not waste space!
        WriteableBitmap writeableBitmap = new WriteableBitmap(200, 200);
        writeableBitmap.LoadJpeg(e.ChosenPhoto);

        string imageFolder = "Images";
        string imageFileName = "TestImage.jpg";
        using (var isoFile = IsolatedStorageFile.GetUserStoreForApplication())
        {

            if (!isoFile.DirectoryExists(imageFolder))
            {
                isoFile.CreateDirectory(imageFolder);
            }

            string filePath = Path.Combine(imageFolder, imageFileName);
         using (var stream = isoFile.CreateFile(filePath))
            {
                writeableBitmap.SaveJpeg(stream, writeableBitmap.PixelWidth, writeableBitmap.PixelHeight, 0, 100);
            }
        }

        //now read the image back from storage to show it worked...
        BitmapImage imageFromStorage = new BitmapImage();

        using (var isoFile = IsolatedStorageFile.GetUserStoreForApplication())
        {
            string filePath = Path.Combine(imageFolder, imageFileName);
            using (var imageStream = isoFile.OpenFile(
                filePath, FileMode.Open, FileAccess.Read))
            {
                imageFromStorage.SetSource(imageStream);
            }
        }
        SmallerImage.Source = imageFromStorage;
    }
}

How to save an image to the phone’s media library.

This one is pretty easy too.  Just remember to add a reference to Microsoft.Xna.Framework or you can’t access the Media Library. Also, you’ll need this using statement:

using Microsoft.Xna.Framework.Media;
void CameraCaptureTaskForSavingToLibraryCompleted(object sender, PhotoResult e)
{
    byte[] imageBits = new byte[(int)e.ChosenPhoto.Length];
    e.ChosenPhoto.Read(imageBits, 0, imageBits.Length);
    e.ChosenPhoto.Seek(0, SeekOrigin.Begin);
    MediaLibrary library = new MediaLibrary();
    library.SavePicture("TestPhoto", imageBits);
}

Hopefully you’ll see that using this feature is pretty easy.

Sunday, December 26, 2010 11:10:27 PM (Eastern Standard Time, UTC-05:00)  #    Disclaimer  |  Comments [1]  |  Trackback
 Tuesday, November 16, 2010

I recently started writing my first Windows Phone 7 Application.  I was shocked at how easy it was to get started although I’ll admit that has a lot to do with my existing knowledge of Silverlight.  If you don’t know Silverlight, now is a great time to learn it.  You can write apps for the web, desktop, and Windows Phone 7 too! 

As I wrote my application, I compiled a list of tips to share.  I spent a bunch of time tracking some of these down or figuring them out.  I hope this will be helpful to other people.  Plus, I’ll use this as a reference for myself when I create my next app!

Here you go.  The first two are pretty basic, but worth mentioning.

Tip:  Go For It!

The best advice is to install the tools and try it out for yourself.  If you create an application from one of the templates (you’ll get them after you install the tools for Visual Studio) you find that the templates themselves are a great learning tool.  Some include samples for styling, data binding, design time data binding, navigation, and more!  I recommend trying each of the templates out.

Tip: Install the Free Tools

This isn’t really a tip.  You can’t create apps without doing this!  Visit the App Hub to download the free tools.  You get all this for free: VS 2010 Express, the Windows Phone Emulator, Expression Blend for Windows Phone, and more!  Also, don’t forget to install Silverlight for Windows Phone Toolkit from the CodePlex site.  It includes some additional controls that are great like AutoCompleteBox, ContextMenu, GestureListener and more!  By the way, when you are at the App Hub, check out all the great learning resources.  By the way, you should keep in mind that Windows Phone 7 is a subset of Silverlight 3!  That means that most features of 3 are there but not all.  And Silverlight 4 features are obviously not included.

Tip: Using the Software Input Panel

The Software Input Panel (SIP) is the “on screen” keyboard that users use to key in data.  It’s pretty cool and has some great features.  First, you don’t need to turn it on.  If you include a TextBox in your app, when it gets focus the SIP will appear.  But there are many versions of the SIP and you can easily configure which one appears by setting the InputScope property of your TextBox.  You can get a full list of the options here.  If you want users to enter numbers, set InputScope to Digits.  For email address entry, try EmailNameOrAddress and the keyboard will include the @ sign.  Some choices are more subtle.  Choosing AddressCountryName may seem like the typical keyboard but the first letter typed will be capitalized, remaining character will be lower case.  There are many cool and smart features like that.  Also, options like Text or Chat will include word suggestions!  Here are some code samples and screen shots:

<TextBox InputScope="EmailNameOrAddress" Height="75" />
<TextBox InputScope="Text" Height="75" />

image     image

The first screenshot is the SIP when the EmailNameOrAddress version has focus.  In the second screen shot (TextBox InputScope set to Text), I typed a few letters and you can see the word suggestions!

Tip:  Orientation

If you want your application to support both portrait and landscape mode (when the user tilts the phone over), you need to set up each page’s SupportedOrientations property to do so as follows.  Set the default value in the Orientation property.

<phone:PhoneApplicationPage 
    x:Class="WindowsPhoneApplication1.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    SupportedOrientations="PortraitOrLandscape"  Orientation="Portrait"

Tip: UI Design

First, you should check out the UI Design and Interaction Guide for tips on how to properly design and style the look and feel of your application.  Also, you should try to use the standard styles provided when you create an application.  Setting the style in this way will give your application a consistent look.  Here are a few samples:

<TextBlock x:Name="ApplicationTitle" Text="Demo" Style="{StaticResource PhoneTextNormalStyle}"/>
<TextBlock x:Name="PageTitle" Text="first page" Style="{StaticResource PhoneTextTitle1Style}"/>

Tip: Using Isolated Storage

For simple values, you can easily get in and out of IsolatedStorageSettings.ApplicationSettings (Dictionary). For more complex data, you can put it into IsolatedStorage.  Since there is no database available in Wp7, one common approach to saving data is to simple serialize your model and save it as a file.  To do so, make sure you mark all of your Model’s classes with the attribute DataContract and make sure the properties have the DataMember attribute.  Here’s a sample class called ListOfStuff as well as the methods I use to read/write it to/from IsolatedStorage:

[DataContract]
public class ListOfStuff : Observable
{
    [DataMember]
    public string Title
    {
        get { return _title; }
        set
        {
            if (_title != value)
            {
                _title = value;
                NotifyPropertyChanged("Title");
            }
        }
    }
    private string _title;

    [DataMember]
    public ObservableCollection<ListCategory> Categories
    {
        get { return _categories; }
        set
        {
            if (_categories != value)
            {
                _categories = value;
                NotifyPropertyChanged("Categories");
            }
        }
    }
    private ObservableCollection<ListCategory> _categories = new ObservableCollection<ListCategory>();
}
public static void SaveToFile(ListOfStuff listOfStuff)
{
    using (IsolatedStorageFile isolatedStorageFile =
    IsolatedStorageFile.GetUserStoreForApplication())
    {
        using (IsolatedStorageFileStream stream =
        new IsolatedStorageFileStream(string.Format("{0}.dat", listOfStuff.Title), FileMode.Create, isolatedStorageFile))
        {
            DataContractSerializer serializer = new DataContractSerializer(typeof(ListOfStuff));
            serializer.WriteObject(stream, listOfStuff);
        }
    }
}

public static ListOfStuff LoadFromFile(string listName)
{
    ListOfStuff listOfStuff = null;
    using (IsolatedStorageFile isf =
    IsolatedStorageFile.GetUserStoreForApplication())
    {
        using (IsolatedStorageFileStream stream = 
        new IsolatedStorageFileStream(string.Format("{0}.dat", listName), FileMode.OpenOrCreate, isf))
        {
            if (stream.Length > 0)
            {
                DataContractSerializer serializer = new DataContractSerializer(typeof(ListOfStuff));
                listOfStuff = serializer.ReadObject(stream) as ListOfStuff;
            }
        }
    }
    return listOfStuff;
}

Tip: Using the Phone’s Camera

Using the phone couldn’t be simpler, just use the CameraCaptureTask as follows:

**NOTE: As reader Andy Wilkinson pointed out in a comment to this post, I’m not following best practices here.  The way I declare my CameraCaptureTask could lead to problems with tombstoning.  He points out a nice article on MSDN that explains the proper use, please read it here.  Thanks, Andy, for the assistance!

**Another Note:  Another user asked about saving the results of the CameraCaptureTask.  So I’ve written another post that you may find useful.  Please check it out here.

private void Camera_Click(object sender, RoutedEventArgs e)
{
    CameraCaptureTask cameraCaptureTask = new CameraCaptureTask();
    cameraCaptureTask.Completed += cameraCaptureTask_Completed;
    cameraCaptureTask.Show();
}
After the picture is taken, you can access it later, as a Stream.  You can assign it to an Image, save it, or do whatever you want.
void cameraCaptureTask_Completed(object sender, PhotoResult e)
{
    var photoStream = e.ChosenPhoto;
}

Tip: Using Gestures

Of course, you want your application to react when users use common phone Gestures such as Flick, Pinch, Hold, etc.  Doing so is easy too!  The Silverlight Toolkit for Windows Phone (mentioned in second tip above) provides the GestureListener that you will need.  You can see how simple it is to wire up in the following example. In this case, I want the user to be able to hold their finger down on an image to go to “edit mode” where a description TextBox will appear.  In the NoteHold() method (not shown), you can imaging all I need to do is set the description TextBox to be visible.

<Image Source="{Binding Image}">
    <ToolkitControls:GestureService.GestureListener>
        <ToolkitControls:GestureListener Hold="NoteHold" />
    </< span>ToolkitControls:GestureService.GestureListener>
</< span>Image>

Now go start creating apps!

Tuesday, November 16, 2010 10:53:00 PM (Eastern Standard Time, UTC-05:00)  #    Disclaimer  |  Comments [7]  |  Trackback
 Tuesday, September 21, 2010

If you’ve been searching the web for a good sample of how to drag and drop data from one DataGrid to another in Silverlight, you’ve probably found some great samples out there, showing “how easy” it can be by just surrounding your DataGrid with DataGridDragDropTarget tags.  In fact, if you do that, you can drag and drop data from one grid to the other.  The problem is that most of these demos are about the visual aspect of drag and drop.  But in the real world, there is more work to be done.  Most of the samples that I found did not deal with how to save the data once it was dropped in the other grid.  I’m using the MVVM pattern so basically what I need to do is, once the drop is complete, update my ViewModel.

The tricky part was figuring out what information was actually dropped on my target DataGrid.  It’s not at all obvious how to do that.  The Drop event uses DragEventArgs which has a Data property.  You’d think this would be the data from the other DataGrid, but you’d be wrong.  Data has a GetData() method but you need to provide it a parameter specifying the format of the Data.  Once you figure out how to do that, you’ll find that GetData() doesn’t actually give you the data!  It give you ItemDragEventArgs, which also has a Data property.  Is this Data the data you want?  Not exactly, but you are getting close.  This Data can be cast as a SelectionCollection – that is because a DataGrid supports multiple selections at the same time!  And each Selection in the collection is the data you actually want.  Is it me, or is that pretty confusing? 

I wouldn’t have gotten this far, but searching the web for a while, I stumbled across a post on StackOverflow that was helpful.  The response also references a blog post found here as well. 

Those samples I found were really helpful but it seemed like it could be made easier.  Starting with sample code from the blog post mentioned above, I created a very simple, reusable, Extension Method that uses Generics and does all of the heavy lifting for you!  This should make things pretty easy now.

Here is some of the sample code and a sample solution is attached here.   

First, here is the extension method that gets the underlying data that was dropped on the target:

public static IEnumerable<T> GetData<T>(this DragEventArgs args)
{
    IEnumerable<T> results = null;

    // Get the dropped data from the Data property and cast it to the first format. 
    ItemDragEventArgs dragEventArgs = args.Data.GetData(args.Data.GetFormats()[0]) as ItemDragEventArgs;

    if (dragEventArgs == null)
        return results;

    // Get the collection of items
    SelectionCollection selectionCollection = dragEventArgs.Data as SelectionCollection;
    if (selectionCollection != null)
    {
        // cast each item to what is expected
        results = selectionCollection.Select(selection => selection.Item).OfType<T>();
    }

    return results;
}

Here is the XAML for the two grids.  Note that in this sample (you can change this of course) I’m using AllowedSourceEffects.Copy so that the data remains in the first grid and is copied to the second.

<Toolkit:DataGridDragDropTarget AllowedSourceEffects="Copy"
                                Grid.Column="0" Grid.Row="0">
    <Controls:DataGrid x:Name="Data"
                        ItemsSource="{Binding Data}" 
                        AutoGenerateColumns="False">
        <Controls:DataGrid.Columns>
            <Controls:DataGridTextColumn Header="Id" Binding="{Binding Id}" />
            <Controls:DataGridTextColumn Header="First Name" Binding="{Binding FirstName}" />
            <Controls:DataGridTextColumn Header="Last Name" Binding="{Binding LastName}" />
        </Controls:DataGrid.Columns>
    </Controls:DataGrid>
</Toolkit:DataGridDragDropTarget>

<Toolkit:DataGridDragDropTarget AllowedSourceEffects="Copy"
                                Drop="DataGridDragDropTarget_Drop"
                                Grid.Column="1" Grid.Row="0">
    <Controls:DataGrid x:Name="MoreData"
                        ItemsSource="{Binding MoreData}" 
                        AutoGenerateColumns="False" 
                        AllowDrop="True">
        <Controls:DataGrid.Columns>
            <Controls:DataGridTextColumn Header="Id" Binding="{Binding Id}" />
            <Controls:DataGridTextColumn Header="First Name" Binding="{Binding FirstName}" />
            <Controls:DataGridTextColumn Header="Last Name" Binding="{Binding LastName}" />
        </Controls:DataGrid.Columns>
    </Controls:DataGrid>
</Toolkit:DataGridDragDropTarget>

Lastly, here is the code behind piece that handles the Drop event, get’s the data and passes it to my ViewModel.  Note here that I specify e.Handled = true.  Without that, the DragDropTarget would automatically copy the data again.

private void DataGridDragDropTarget_Drop(object sender, Microsoft.Windows.DragEventArgs e)
{
    //use the extension method to get the data from the DragEventArgs
    var data = e.GetData<Person>();

    foreach (var item in data)
    {
        _viewModel.AddToMoreData(item);
    }
    e.Handled = true;
}

Once again, here is a link to a complete sample project

Tuesday, September 21, 2010 11:18:14 PM (Eastern Standard Time, UTC-05:00)  #    Disclaimer  |  Comments [7]  |  Trackback
 Monday, August 23, 2010

I love working with other developers, whether it be formal “paired programming” or just one person helping the other with a problem.  I love it so much because I always learn something new.  Sometimes what I learn is some major, powerful technique for doing something complicated but usually it is not.  Usually it is one of those simple, cool, helpful tidbits.  You probably know what I mean.  You sit with a coworker and without any fanfare they type some keystroke and you say, “Whoa, I didn’t know you could do that… how did you do that?”  Here’s an example of something I do that I’ve noticed many developers aren’t aware of. It’s nothing fancy, but I find it helpful.

Like many developers, I like to surround my code in collapsible regions.  I don’t get too carried away with this technique, but I usually have a region for Public Properties, another for Public Methods, maybe one for Class Level variables.  Stuff like that.  Anyway, most people label the top of the region but I’ve found that many developers don’t know you can label the bottom.  That extra label on the bottom is really helpful when you are scrolled down far.  Without the label, you find an #endregion and you don’t know what region it is the end of.  This is especially tricky when working with nested tags.  How do you do it?  Just type the label :).

#endregion with label:
#region Public Methods
// put stuff here...
#endregion Public Methods

I think the reason people don’t do this more is that (I’m pretty sure) you could NOT do this with some earlier version of Visual Studio.  Those of us that have worked with VS for a long time just got used to doing #endregions without the label.  Back then I used to put a comment at the end of my region like this, but it isn’t necessary anymore:

#region Public Methods
// put stuff here...
#endregion //Public Methods

But at some point, maybe VS2008, we were allowed to just put the label at the end. 

But wait, there’s more…

Recently I had the idea to update the code snippet for “Surround with Region”.  You can use this built in Visual Studio snippet by highlighting some code and hitting “Ctrl + s”, then select #region from the dropdown.  When you do, your code is automatically surrounded by the #region and #endregion, plus you’ll be prompted for the text for the label.  I tweaked it so it puts the label at the beginning and the end. 

  • You can find your snippets by going to the Code Snippets Manager (Tools > Code Snippets Manager, or Ctrl + k, Ctrl + b).
  • Then select Visual C# (or VB I guess, I don’t use it :) )
  • When you click on the folder or the name of the snippet, the path is shown in the window.  See the screen shot below…
  • In my case, and I think it is pretty standard, I open the snippet in Notepad at the following path: C:\Program Files\Microsoft Visual Studio 10.0\VC#\Snippets\1033\Visual C#\pp_region.snippet
  • Then change the snippet and use the XML listed below.
  • The only thing I changed was the 24th line.  After “#endregion” I put in the $name$ variable.  The variable was already used in the snippet on line 22 so it was easy. 
  • Note: If you can’t save this snippet with notepad, make sure Visual Studio is closed and run notepad “as administrator”.
Snippet XML:

<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets  xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
    <CodeSnippet Format="1.0.0">
        <Header>
            <Title>#region</Title>
            <Shortcut>#region</Shortcut>
            <Description>Code snippet for #region</Description>
            <Author>Microsoft Corporation</Author>
            <SnippetTypes>
                <SnippetType>Expansion</SnippetType>
                <SnippetType>SurroundsWith</SnippetType>
            </SnippetTypes>
        </Header>
        <Snippet>
            <Declarations>
                <Literal>
                    <ID>name</ID>
                    <ToolTip>Region name</ToolTip>
                    <Default>MyRegion</Default>
                </Literal>
            </Declarations>
            <Code Language="csharp"><![CDATA[#region $name$
        $selected$ $end$
    #endregion $name$]]>
            </Code>
        </Snippet>
    </CodeSnippet>
</CodeSnippets>

Code Snippets Manager:

image

Code Snippets are really cool and easy to use.  For more information, please see this post.

Monday, August 23, 2010 9:30:05 PM (Eastern Standard Time, UTC-05:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Friday, August 13, 2010

I’ve seen a few posts describing how to use a Uri as a source for a BitmapImage, and then the BitmapImage as the source for the WriteableBitmap.  But that didn’t work so well until I figured out the trick.  Here goes…

First, here is the code that I THOUGHT would work, but did not.

Uri uri = new Uri("http://somedomain.com/someimage.png");
BitmapImage bitmapImage = new BitmapImage(uri);
WriteableBitmap writeableBitmap = new WriteableBitmap(bitmapImage);

When you run that, you’ll most likely get an exception (I did) because the BitmapImage is not set when it is used for the WriteableBitmap.  My hypothesis was that the BitmapImage doesn’t render itself until it is needed.  I started looking through the properties of the BitmapImage, luckily there aren’t too many, when I came across the CreateOptions property – that sounded interesting!  It is an Enum with 3 values: DelayCreation, IgnoreImageCache, and None.  Guess which one is set as the default?  DelayCreation!  Here was my next pass at the code:

Uri uri = new Uri("http://somedomain.com/someimage.png");
BitmapImage bitmapImage = new BitmapImage();
bitmapImage.CreateOptions = BitmapCreateOptions.None;
bitmapImage.UriSource = uri;
WriteableBitmap writeableBitmap = new WriteableBitmap(bitmapImage);

That’s it, pretty simple and it works.  But I took it one step further just in case.  I’m not positive this is necessary but I like to play it safe.  When inspecting the properties of the BitmapImage, I saw there is an ImageOpened event. I was thinking that some images may load slowly and I wasn’t sure if that happens asynchronously or not.  Would my application wait around for them to finish loading?  I don’t really know but it sure sounds like the ImageOpened event would be a way to make sure my images were loaded.  Here is my final take:

public void SomeMethod()
{
    Uri uri = new Uri("http://somedomain.com/someimage.png");
    BitmapImage bitmapImage = new BitmapImage();
    bitmapImage.CreateOptions = BitmapCreateOptions.None;
    bitmapImage.ImageOpened += ImageOpened;
    bitmapImage.UriSource = uri;
}

void ImageOpened(object sender, RoutedEventArgs e)
{
    BitmapImage bm = (BitmapImage)sender;

    WriteableBitmap wbm = new WriteableBitmap(bm);

    //now I can use wbm for whatever I need...
}
Good luck with your WriteableBitmaps!
Friday, August 13, 2010 9:22:52 PM (Eastern Standard Time, UTC-05:00)  #    Disclaimer  |  Comments [5]  |  Trackback