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
 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
 Wednesday, August 04, 2010

I’m a big fan of the MVVM Pattern for Silverlight development, so naturally I was excited about Silverlight 4 having support for Commanding.  I recently upgraded my current project to Silverlight 4 and I found that binding my buttons to my View Model commands was pretty easy.  However, it wasn’t long before I needed to create a custom control and I wasn’t sure how the Command Binding would work.  I searched the web for some samples but found none so I was on my own.  It wasn’t too hard to figure out the solution, here is how I did it.

The setup… For the sake of this demo, I’ll need a resuable control that combines 2 buttons:  Save and Cancel.  I’ll call it a SaveCancel control :).  The control is simple enough.  Thanks to Silverlight 4, buttons already support the command binding – all you have to do is bind the command in your View Model to the Command property of the button (and optionally the CommandParameter property).  If you aren’t familiar with the basics of commanding, I suggest you check out this blog post by John Papa.  Anyway, when it is time to use the SaveCancel control on another page/control, it becomes pretty clear that you can’t access the individual button’s properties to bind to them!  The individual buttons are not publicly available since they are “child” controls of the SaveCancel control.  The solution:  The Command and CommandParameter properties of each button are just DependencyProperties so all you have to do is create matching properties on the new control that “wrap” the internal properties.

Here’s how it’s done…

First, the XAML of the SaveCancel control is pretty straightforward:

<UserControl x:Class="CustomControlWithCommanding.SaveCancel"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d" >
    
    <StackPanel x:Name="LayoutRoot" Orientation="Horizontal" >
        <Button x:Name="Save" Width="50" Height="25" Content="Save" Margin="0,0,5,0" />
        <Button x:Name="Cancel" Width="50" Height="25" Content="Cancel" />
    </StackPanel>
</UserControl>

Next the Code Behind of the SaveCancel control.  Here is where all of the wiring is done for each button’s commands. There are a few parts.  First is the DependencyProperty for the Save button’s command.  Like any dependency property, you need a public property with a Get/Set that sets the value of the Dependency Property as well as a DependencyProperty:

public ICommand SaveCommand
{
    get { return (ICommand)GetValue(SaveCommandProperty); }
    set { SetValue(SaveCommandProperty, value); }

}
public static readonly DependencyProperty SaveCommandProperty =
    DependencyProperty.Register("SaveCommand", typeof(ICommand), typeof(SaveCancel), 
                                new PropertyMetadata(null, OnSaveCommandChanged));

Note that in the PropertyMetaData argument for the SaveCommandProperty we are passing in a callback reference (OnSaveCommandChanged).  We’ll use that method to set the value of the new DependencyProperty to the actual Save button.  Here is the code:

private static void OnSaveCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    SaveCancel sc = (SaveCancel)d;
    sc.Save.Command = (ICommand)e.NewValue;
}

To be complete, we’ll do some similar work to make sure that we can wire up the CommandParameter to the Save button as well, even though we don’t really need it to make the button work for this sample.  

public object SaveCommandParameter
{
    get { return GetValue(SaveCommandParameterProperty); }
    set { SetValue(SaveCommandParameterProperty, value); }

}

public static readonly DependencyProperty SaveCommandParameterProperty =
    DependencyProperty.Register("SaveCommandParameter", typeof(object), typeof(SaveCancel), 
        new PropertyMetadata(null, OnSaveCommandParameterChanged));

private static void OnSaveCommandParameterChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    SaveCancel sc = (SaveCancel)d;
    sc.Save.CommandParameter = e.NewValue;
}

To use the new SaveCancel control in another Silverlight control, all I need is some code like the sample below.  It works perfectly with no events wired up and no code behind on the page where it is used!

<CustomControlWithCommanding:SaveCancel SaveCommand="{Binding SaveCommand}" 
                                        CancelCommand="{Binding CancelCommand}" />

Of course, my ViewModel must have the commands (SaveCommand and CancelCommand) to support this as well.  But that is just normal ViewModel commanding.  Again, if you aren’t familiar with that, check out John Papa’s blog post.

Complete Source Code:

To see the complete sample solution, download it here.

Wednesday, August 04, 2010 9:05:17 PM (Eastern Standard Time, UTC-05:00)  #    Disclaimer  |  Comments [1]  |  Trackback
 Sunday, July 25, 2010

There seems to be a bug in Visual Studio 2010 when adding references to Silverlight projects.  You can add “regular” .Net references just fine using the add reference dialog.  However if you use the browse feature to find a reference in an “unusual” location, Visual Studio is supposed to record that location along with the reference in the .csproj file.  It includes the location via the HintPath property.

At my company, we use build machines and we don’t like to install a lot of software on them.  So in source control we have a folder (assets\lib) that includes all of the necessary .dll files that we need to build or projects.  When we add references to our project, like for a Silverlight control library, we add it from the assets\lib\Silverlight folder, even though that library is installed on my local machine.  Anyway, when I tried doing this in Visual Studio 2010 (I’m upgrading our existing 2008 solution), VS 2010 isn’t including the HintPath.  If you aren’t careful, you may not realize this is happening.  That’s because since the library is installed on my machine, the build works just fine, except it pulls the .dll from the wrong place.  If I were to try this build from my build server, it would fail though. 

Anyway, here is the workaround.  It’s a pain but it works…

  1. Add your references as you would normally do it via Visual Studio.
  2. Right click the project file in the Solution Explorer and choose Unload Project.
  3. Once the project is unloaded, right click again and chose edit.  This will open the file, and xml document, in Visual Studio.
  4. Find the incorrect reference in the file and edit it manually.  You’ll need to make it look something like this:
    <Reference Include="System.Windows.Controls, Version=2.0.5.0, Culture=neutral, 
    PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL
    " > <HintPath>..\..\..\Assets\lib\Silverlight\System.Windows.Controls.dll</HintPath> </Reference>
  5. Save the file and close it.
  6. Reload the project.

When you are done you can verify that it works.  Here’s how…

  1. In Visual Studio, choose Tools > Options.
  2. Find the Projects and Solutions section and select Build and Run.
  3. In the section “MsBuild Project build output verbosity”, select “Detailed”.
  4. Now build your project.  When you do so, you’ll see a lot of details of what goes on in the Output Window.  You’ll need to find the output that relates to the file that you specified, in my case it is System.Windows.Controls and the important output looks like this:

    Primary reference "System.Windows.Controls, Version=2.0.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35".
          Resolved file path is "C:\Projects\MC\BackOffice\UI\branches\2010Migration\Assets\lib\Silverlight\System.Windows.Controls.dll".
          Reference found at search path location "{HintPathFromItem}".

  5. You will note that it tells you specifically which path was used to resolve the reference!  And if you are so lazy that you don’t want to read the entire path used, you see that it says the reference was found at the search path location “{HintPathFromItem}”.  That means it used the path you specified.

I hope this helps!  Good luck and let’s hope they fix this bug soon.

Sunday, July 25, 2010 2:19:34 PM (Eastern Standard Time, UTC-05:00)  #    Disclaimer  |  Comments [5]  |  Trackback
 Thursday, February 19, 2009

If you are looking to learn about Silverlight development, here is your chance.  Our local Microsoft Developer Evangelists are running a free full day event this Saturday featuring a good variety of information. 

To learn more or register, click here.

If you are a beginner or haven't gotten started yet, this is a great opportunity.  I'm not a beginner and my weekends are pretty busy these days.  So initially, I was going to skip this event.  But from my conversation with Dani Diaz last night, it sounds like there will be a decent range of information here, so I think I will attend too. 

I don't know the full agenda but some of the speakers include Dani, Lindsay Rutter, Bill Wolff and Pete Brown.  That's a good line up but to be perfectly honest, Pete Brown is the big draw for me.  I've been reading his blog since I started doing Silverlight development, this guy really knows his stuff.  One thing I've learned over time is that if a good speaker if giving a talk, even on a topic that I think I know fairly well, it is worth attending.  You never know what kind of tidbit you may pick up from them!

Hope to see you there.

Thursday, February 19, 2009 9:42:51 AM (Eastern Standard Time, UTC-05:00)  #    Disclaimer  |  Comments [2]  |  Trackback
 Friday, February 13, 2009

One thing I really hate about doing Silverlight development is trying to search for good information on the Internet.  When I look for a solution to a problem I am having, I always run into a lot of "noise" in the form of outdated posts that aren't relevant anymore.  There are a ton of questions, answers, and sample solutions on the web from developers working with the Silverlight 2 Beta release.  I know this was all helpful information to share at the time, but a lot of it is useless now.  The problem is, sometimes you have to read the post a bit in order to figure out that the developer was on the Beta.  I've gotten to the point where the first thing I do is look at the date on the post before I read on.  What makes this even more complicated, is sometimes the information in these posts is still relevant and very helpful! 

Oh well, at least we are lucky to be developers in an age where so much information is shared among members of the community.  Can you imaging having to read manuals for all your information ;) ?  I don't mean to discourage anyone from posting.  Don't take me too seriously, I'm just ranting.

Friday, February 13, 2009 8:45:17 AM (Eastern Standard Time, UTC-05:00)  #    Disclaimer  |  Comments [4]  |  Trackback
 Tuesday, February 10, 2009

The other day I was working on a Silverlight app when I got this error:  Layout Cycle Detected.  The good news is that Silverlight actually gave me an error message that meant something.  That is unusual for Silverlight.  Of course the message didn't tell me what caused it, or how to fix it!  Luckily, there is this thing called the Internet ;-).  I found some information on David Yack's blog (I don't know him) that helped.

It turns out that Silverlight doesn't like it if you put too many TextBoxes in a ListBox (or possibly any other "repeater" kind of list control).  I'm not sure why it only applies to TextBoxes and not other controls, but here is my understanding of the problem...  Each time you add a TextBox to a ListBox it needs to figure out how much space to give the control, as well as all the other controls around it.  It figures that out, and then sizes all of the controls that don't have specific sizes set, and then lays everything out for you.  But I guess in a list, it needs to do this over and over and over again and Silverlight thinks it has gone into an endless loop, so at a certain point it cuts it off and says "Layout Cycle Detected".  Each time a control gets resized, the controls around it get resized, and that goes on and on until you get to the top level control.  I guess I can understand that it could be a problem, but I think the developers at Microsoft have got to come up with a better way to resolve this.  If I want to put a lot of TextBoxes in a list, I should be allowed to do so!  Also, the limit is supposedly 250 TextBoxes, but I am pretty sure I had less than that.

There are a few ways to get around the problem, as far as I know.  In my case there are a bunch of controls that made up the DataTemplate for my ListBox.  Since they are in a StackPanel, I put a fixed size on the StackPanel.  That prevents the "bubble up" of resizing going all the way to the page level.  That seemed to fix my problem most of the time, but not all of the time.  I could probably have kept playing with the layout and putting fixed sizes on more panels.  Instead, I gave in. 

I didn't want to fight with Silverlight any more so I changed all of my TextBoxes to TextBlocks.  Then I set the the ListBox items up so that you can switch them into "Edit Mode".  The problem here is that the ListBox doesn't have built in support for that.  So here is how I did it.  By the way, this is not dependent upon the "SelectedItem" in the ListBox, so you can have multiple items in EditMode at the same time.

The purpose of my list is to display a list of Services to the user.  My ListBox is bound to a collection: ObservableCollection<ServiceListItem>.  ServiceListItem is just a class that represents my data.  Among it's other properties, the ServiceListItem has a property for IsInEditMode.  It is nothing fancy:

            public bool IsInEditMode
            {
                get { return _isInEditMode; }
                set
                {
                    if (_isInEditMode == value)
                        return;
                    _isInEditMode = value;
                    NotifyPropertyChanged("IsInEditMode");
                }
            }
            private bool _isInEditMode;

In my DataTemplate for the ListBox I have two StackPanels, one for ReadOnly mode and one for Edit Mode.  The ReadOnly template has a button to switch to EditMode.  The EditMode template has two buttons.  The Cancel button reverts the data to it's original state and switched to ReadOnly mode.  The Save button saves the data and switched to ReadOnly Mode.  Here is the one that puts the template into Edit Mode (nothing fancy here):

<Button x:Name="EditService" Click="EditService_Click">
    <Button.Template>
        <ControlTemplate>
            <Image Source="../images/pencil.png" 
                   Height="10" 
                   Width="10" 
                   Cursor="Hand" 
                   VerticalAlignment="Center" 
                   HorizontalAlignment="Center"/>
        </ControlTemplate>
    </Button.Template>
</Button>

The code for the button click is pretty simple too:

        private void EditService_Click(object sender, RoutedEventArgs e)
        {
            ServiceListItem item = (ServiceListItem)((Button)sender).DataContext;
            item.IsInEditMode = true;
        }

Actually, the only cool part of this is how the control figures out which StackPanel to display.  Each one has it's Visibility Property bound to the IsInEditMode property!

                           <StackPanel x:Name="EditPanel"
                                       Visibility="{Binding IsInEditMode, Converter={StaticResource BoolVisibilityConverter}}" 
                                       Orientation="Horizontal" Height="20" >

The trick is the Converter.  We're using a Converter that converts a boolean value into a value from the Visibility Enumeration:

 

    public class BoolVisibilityConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value == null || string.IsNullOrEmpty(value.ToString()) || !(bool)value)
                return Visibility.Collapsed;

            return Visibility.Visible;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            // we don't need it to convert back but we could implement that later.
            return value;
        }
    }
Don't forget to add the Converter to your user control's resources:
    <UserControl.Resources>
        <ClientUtilties:BoolVisibilityConverter x:Key="BoolVisibilityConverter" />
        <ClientUtilties:BoolInverseVisibilityConverter x:Key="BoolInverseVisibilityConverter" />
    </UserControl.Resources>
And it all just works!
From this, you should be able to figure out the other end of this, switching back to Read Only Mode. 
I hope this helps.  
Tuesday, February 10, 2009 10:01:36 PM (Eastern Standard Time, UTC-05:00)  #    Disclaimer  |  Comments [1]  |  Trackback
 Tuesday, January 27, 2009

If you are working with LINQ to SQL, you may be familiar with this exception message:

"Cannot add an entity with a key that is already in use."

This typically comes up when you are working with LINQ to SQL, as I am, in a "disconnected " situation.  In my case, I am working with a Silverlight Application, so I get some data with one DataContext, then pass it out to my Silverlight application (this is the same with any other web application), make changes to it, pass it back to the server where it gets updated using a different instance of my DataContext.

The interesting thing in my case is that I thought I fixed the problem but I still got the exception.  I'll explain why.  But first, there are several ways you can resolve this issue.  How you choose to fix this will have to do with how your database is set up initially.  I am working with an existing database and there are limits to how I can change the db.  So I have my all of the properties in my LINQ to SQL Entities set as "UpdateCheck = UpdateCheck.Never".  Next I'll "Attach" my entity to my DataContext  but before I do that, I'll "Detach" it  My Detach() method "resets" all of the EntitySets and EntityRefs connected to my entity so that LINQ to SQL doesn't think I am trying to insert them into the database.  Sorry, I'm not going into details on this process in this blog post but you can easily find details on the web.  Now I can attach my disconnected entity to my DataContext like this: 

            using (ABCDataContext db = new ABCDataContext())
            {
                foo.Detach();
                db.Foos.Attach(foo, true);
                db.SubmitChanges();
            }

This should work fine.  But it wasn't working in my case.  Why?  It is a typical case of how various steps I took to resolve the a different problem ended up causing new problems.  I was debugging and trying a bunch of stuff because my calls to Attach were throwing exceptions.  There is an overload to the Attach() method that would look like this -- db.Attach(newEntity, originalEntity)  -- so that LINQ to SQL can compare the two items.  I had been playing around with it but when I commented out my code, I forgot to comment out one line, so it looked like this:

            using (ABCDataContext db = new ABCDataContext())
            {
                foo.Detach();
                Foo oldFoo = db.Foos.SingleOrDefault(f => f.FooId == foo.FooId);  // NOT REMOVING THIS LINE CAUSED THE EXCEPTION!
                //db.Foos.Attach(foo, oldFoo);
                db.Foos.Attach(foo, true);
                db.SubmitChanges();
            }

When I run this, I get the exception "Cannot add an entity with a key that is already in use".  For some reason, even though I wasn't working with "oldFoo", LINQ to SQL didn't like the fact that I requested it from the database.  So I commented out that line (Foo oldFoo = db.Foos.SingleOrDefault...) and everything just started working fine. 

It was a pain but it is over now.  Now it is time to solve more problems...

Tuesday, January 27, 2009 10:10:34 AM (Eastern Standard Time, UTC-05:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Sunday, January 18, 2009

As an ASP.Net developer, one of my favorite tools is Firebug.  Generally, my default browser is IE, but when I develop web sites I always debug and test with Firefox with the Firebug Add-on to make designing the pages easier. If you are a web developer and you aren't familiar with Firebug you must check it out.  It basically allows you to inspect your page in the browser at runtime.  With Firebug you can see how your ASP.Net Code gets rendered into HTML, and how the CSS is applied.  Often it was not as I expected!  You can even modify the html, CSS and JavaScript at runtime.  This is a great help because you can tweak the page in the browser to look the way you want and then go back and apply the changes to your source code.

Now I am developing a Silverlight Application.  The learning curve is steep, working with XAML I am starting from scratch.  It isn't like HTML at all and it is not so easy to make controls look like you want the to.  And it was even harder because I didn't have Firebug to help.  Searching the Internet, I found Silverlight Spy.  This is a cool, free tool that helps in many ways with Silverlight Development.

With Silverlight Spy you can inspect your XAP package, monitor events, network activity and performance and more.  But the best part is that I can inspect the elements within my XAML at runtime and even make changes.  This is pretty important because I find that the XAML design experience in Visual Studio is less than perfect.  I've already used Silverlight Spy to help me solve a bunch of problems.  The tool isn't perfect, but it is BETA software and it is free, so I am not complaining.  Many, many thanks to the developers.

 

Sunday, January 18, 2009 9:20:44 PM (Eastern Standard Time, UTC-05:00)  #    Disclaimer  |  Comments [2]  |  Trackback
 Tuesday, January 13, 2009

Sometimes strange things happen.  It happened to me, I figured it was a fluke.  But last week it happened to my co-worker too.  Weird right?  Everything was working great with my VS Solution including a Silverlight App.  It isn't new and I've debugged it many times.  But for some reason, no matter what I did, the debugger seems to be ignoring my breakpoints.  At first I thought that maybe the code wasn't getting called, but it sure seems like it was getting called.  If you find yourself in this predicament, here's all you need to do.   Go to the Property Pages of your Web App (the application that hosts the Silverlight).  You get there by right clicking on the Web Application in the Solution Explorer and select Properties.  Then choose the "Web" tab and you'll see the one below.  If debugging doesn't work, the "Silverlight" checkbox is probably not checked!  I'm not sure how this setting gets reset, but at least it is easy enough to fix.

Enable Silverlight Debug

 

Technorati Tags: ,
Tuesday, January 13, 2009 8:35:02 PM (Eastern Standard Time, UTC-05:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Thursday, December 18, 2008

So I'm working with Silverlight these days.  It's an excellent technology but it's got a fairly steep learning curve.  For the past several years I've been working predominantly with ASP.Net.  As a matter of fact, I've really gotten pretty good at it!  In addition to all of the in's and out's of ASP.Net, including the page lifecycle, custom controls, etc, I had gotten really comfortable with CSS and I've even stopped saying "I hate JavaScript" and started liking it.  Of course, with JQuery, it is really pretty good to work with.  But I digress.

Anyway, all of that stuff I have learned is out the window now.  Silverlight is completely different.  The easy part is that all of my C# code goes right to the client, as well as running on the server.  So much for JavaScript.  But there is no HTML, no ASP.Net controls.  None of it (at least in the apps I am writing).  This is not an ASP.Net application with a little Silverlight mixed in.  The entire UI for this business application is Silverlight.  The only html/asp.net is the page that hosts it.  So all of the UI is written in XAML.  XAML is cool and very powerful but takes getting used to and when you start with it, you are starting from scratch.  It's not like writing a web app or a windows forms app at all.  But don't get me wrong, I like it.

Anyway, the purpose for this first Silverlight post...

So I'm working along and things are going good.  My app is coming along and working as well as it should in the very rough state it is in.  After making a bunch of changes I fire up the debugger and run my Silverlight application in Internet Explorer.  "Hmmm, that's weird, it shouldn't do that" I think to myself.  I checked the code, and sure enough, it should not do "that".  So I run it again. Same result.  My code is running without the recent changes I made.  Ok, I try a bunch of stuff, not necessarily in this order: Build my Solution, "Rebuild" my solution, "Clean" my solution, put obvious changes in my UI and re run it, restart Internet Explorer, Ctl-F5 to clear IE, try Firefox, close/reopen my solution, close/reopen VS2008, reboot my machine.  I probably tried a few more things but no matter what I did, the application continued to show the UI before my changes.  At some point in all of this, it became clear that my XAP file was not getting updated in my web project.  I tried deleting it, figuring that would signal Visual Studio to replace it when it builds again.  No luck.  I manually placed a current XAP file (from the Silverlight app) into my web project.  Now when I run my application is perfectly up to date!  So I am positive on the problem but unsure how to fix it. I figured that in my Property Pages of my Silverlight Application I'd find something telling me where/when/what to do with the XAP file.  But I couldn't find it.  Next I searched the Property Pages of my Web Application.  Presto, there it is!  From a web application, select the "Silverlight Application" tab.  When I did the list of projects was empty!  I have no idea how it got to be that way.  But I clicked "Add" and the rest was self explanatory.  I picked my Silverlight project and selected where I wanted the XAP file to go. 

 

image

Technorati Tags: , ,
Thursday, December 18, 2008 9:04:51 PM (Eastern Standard Time, UTC-05:00)  #    Disclaimer  |  Comments [0]  |  Trackback