Blog?

I'm sure you have something better to do
geekSpeak recording on Channel 9

Recently I recorded a geekSpeak interview on Touch Based computing and the general NUI paradigm shift.

I just noticed that the interview has been uploaded to Channel 9 now so if you missed it you can check it out here

http://channel9.msdn.com/shows/geekSpeak/geekSpeak-Recording-Touch-based-Computing-with-Brad-Cunningham/

It is a talk show based podcast so there isn’t much video to pay attention too but you can listen to it while you work (if you are that geeky :) )

If you listen to it and think it is awesome let me know (if you think it really sucks you can let me know too :( )

Note: Cross posted from Permalink

TextTrimming in Silverlight 2

In a previous post I found myself hacking around in the Silverlight 2 trying to emulate drop shadows on text blocks (something that is natively supported in WPF but missing in Silverlight 2)

Once again, I find myself trying to emulate functionality that is natively supported in WPF and again it is related to TextBlocks.

In WPF when you have a TextBlock whose text could extend beyond the available space you have the option to trim the text using a specified TextTrimming setting. To do this in WPF you would set the TextTrimming property of the TextBlock element and be done. Something like this:

<TextBlock Text="A really really long string that should be trimmed"
TextTrimming="CharacterEllipsis" />


In Silverlight there is no such property on a TextBlock. So I created a quick and dirty implementation that works (for the most part)


I created a new UserControl called TrimmingTextBlock. The XAML for this control looks like this:


<UserControl x:Class="TextTrimming.TrimmingTextBlock"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" >
<TextBlock x:Name="TrimmedTextBlock" />
</UserControl>


All the “magic” (a.k.a hacking) happens in the code behind. I wanted the consumer of the control to be able to bind to a Text property, just like a normal TextBlock so I created a custom dependency property called Text


private static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text",
typeof(String),
typeof(TrimmingTextBlock),
new PropertyMetadata(String.Empty,OnTextChanged));


I need to display trimmed text but I still wanted the “Text” property of my control to maintain the original string. Trimming is only a display issue and shouldn’t impact the underlying data. So I created a second private dependency property called TrimmedText where I will store the display version of the string.


private static readonly DependencyProperty TrimmedTextProperty = DependencyProperty.Register(
"TrimmedText",
typeof(String),
typeof(TrimmingTextBlock),
new PropertyMetadata(String.Empty, OnTrimmingTextChanged));


So the first step is to make sure the TrimmedText property gets the value that is bound to the Text property. I do this in the OnTextChanged method (this is fired whenever the Text dependency property is changed). In the changed method I am getting an instance of my control and finding the TextBlock element and setting it’s text property to the new value.


private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var tb = d as TrimmingTextBlock;
if (tb != null)
{
tb.TrimmedTextBlock.Text = e.NewValue.ToString();
}
}


Now that the data is wired up correctly I have to do the actual trimming. In the ArrangeOverride method of my control I call my TrimText method


protected override Size ArrangeOverride(Size finalSize)
{
TrimText(this);
return base.ArrangeOverride(finalSize);
}


In TrimText I get the ActualWidth of the TextBlock. Since I have set the Text property already the ActualWidth will be the width in pixels that is needed to display the specified string of text.


I compare this ActualWidth to the DesiredWidth, that is the width that is available to the TextBlock. If the text is larger then the available space, that is if the ActualWidth is greater than the DesiredWidth, I need to trim.


My trimming implementation is simplistic but seems to work. I chop off one character at a time from the end of the string and then update the TextBlock with the new value. This causes a measure and arrange pass to fire which will call my trim method again and we can re-check the width.


I continue cutting off one character at time until the text will fit. Here is what the Trim method looks like:


private static void TrimText(TrimmingTextBlock block)
{
//Check the desired size of the text block and the actual size and trim accordingly
var actualWidth = block.TrimmedTextBlock.ActualWidth;
var desiredWidth = Double.MinValue;

if (desiredWidth == Double.MinValue)
{
desiredWidth = block.TrimmedTextBlock.DesiredSize.Width;
}

if (desiredWidth < actualWidth)
{
//Trim
String trimmedText = block.TrimmedTextBlock.Text;

if (!trimmedText.Contains("…"))
trimmedText += "…";

trimmedText = String.Concat(trimmedText.Substring(0, trimmedText.IndexOf("…") - 1), "…");
block.SetValue(TrimmedTextProperty, trimmedText);
}

}


This approach seems to work in most cases. For my purposes it does the job. This isn’t the most optimized code as it can cause a ton of Measure and Arrange operations. In fact in Silverlight 2 there is a known bug (which is fixed in SL3 beta1) that you cannot have more than 250 layout operations on one page. See this thread


Because of this bug this solution doesn’t really scale that nicely if you have the need for a bunch of TrimmingTextBlocks on one page. Or if you have a really long string that could cause more than 250 layout recursions.


This code could be optimized so that large strings cause fewer layout passes by intelligently removing more than one character at a time. But for me this works for now.


You can get the code with a few examples of usage from here

Note: Cross posted from Permalink

Two sessions for Code Camp this weekend

I have two sessions scheduled for the Code Camp event in San Diego this weekend

Touch 101

http://www.socalcodecamp.com/session.aspx?sid=e927884d-6bb6-4e13-9554-ee426e573f0f

XAML Panel discussion

http://www.socalcodecamp.com/session.aspx?sid=4046c382-190d-40f6-b86b-af0dd307b9ae

If your interested come and check it out. It’s free.

Note: Cross posted from Permalink

Binding to custom attached properties

Another quick post. In an effort to blog more I am trying to blog quick snippets I come across instead of full blown manifestos.

Colleagues of mine at InterKnowlogy came across an interesting binding edge case the other day and I thought it would make a decent post. In the past I have needed to bind to attached properties (although it has been rare). Typically I was doing something like this :

<DockPanel Height="100" Width="100">
<TextBlock DockPanel.Dock="Left"
Text="{Binding RelativeSource={RelativeSource Self}, Path=(DockPanel.Dock)}" />
<TextBlock DockPanel.Dock="Right"
Text="{Binding RelativeSource={RelativeSource Self}, Path=(DockPanel.Dock)}" />
<TextBlock DockPanel.Dock="Top"
Text="{Binding RelativeSource={RelativeSource Self}, Path=(DockPanel.Dock)}" />
<TextBlock DockPanel.Dock="Bottom"
Text="{Binding RelativeSource={RelativeSource Self}, Path=(DockPanel.Dock)}" />
</DockPanel>


Where I am binding to the attached property “DockPanel.Dock.” The basic trick here is to add the parentheses around the path to indicate you are binding to an attached property.



The edge case we came across this past week was binding to a custom attached property. Something like this



<TextBlock Custom:MyAttachedProperty.CustomString="Some String" 
Text="{Binding RelativeSource={RelativeSource Self}, Path=(MyAttachedProperty.CustomString)}" />


Where I am binding to “MyAttachedProperty.CustomString.” This however doesn’t work as posted. It will throw and error stating it cannot find type MyAttachedProperty. The solution may be obvious to most but we were stuck on it for a few minutes.



You have to add the namespace prefix to the property in the binding in order for the Binding markup extension to be able to resolve the custom type and find the attached property.



So the example above is corrected like this:



<TextBlock Custom:MyAttachedProperty.CustomString="Some String" 
Text="{Binding RelativeSource={RelativeSource Self}, Path=(Custom:MyAttachedProperty.CustomString)}" />


Like I said, might be obvious to most but it isn’t something I had done before so it took a few minutes to discover the correct way to do it.

Note: Cross posted from Permalink
Controlling Audio playback in XAML

Just a quick post (mainly for my own reference). I had the need to do some simple audio playback in a WPF application recently and wanted to trigger the playback declaratively.

In the  past any media playback I have done through code behind of some sort. In this scenario the audio files were going to be more dynamic and all I needed to perform was a simple play operation. I didn’t have the need to support pausing, fast forward, rewind, etc. Just play the clip.

A little poking around on the tubes didn’t turn up much useful. Hence why I am posting this entry.

I found that if you use the MediaElement control you can trigger it using a MediaTimline element in a BeginStoryboard action.

First declare your MediaElement and simply give it an x:Name (don’t specify the source, LoadedBehavior, UnloadeBehavior etc..)

<MediaElement x:Name="mediaElement" />  


Then wherever you want to trigger the animation (on a button click in my case) put the following even trigger



<Button.Triggers>
<EventTrigger RoutedEvent="ButtonBase.Click">
<BeginStoryboard>
<Storyboard>
<MediaTimeline Source="Resources\AudioFiles\easy.wma" Storyboard.TargetName="mediaElement" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Button.Triggers>
Note: Cross posted from Permalink
geekSpeak interview

I am going to be giving a live MSDN webcast as part of the geekSpeak series. The discussion will be focused around Touch based development in general. More specifically we will be covering touch based hardware implementations and gestural interface design.

If you are interested in joining in on the discussion you can register here

http://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032416182&Culture=en-US

best of all it’s FREE!

 

The discussion will be hosted by Lynn Langit and Mithun Dhar. Many thanks to Lynn for inviting me to do this event.

Note: Cross posted from Permalink

Touch 101 Talk – San Diego .NET user group

Thanks to everyone that came out to my talk last night. We had a good time discussing touch based development and gestural interfaces.

You can download the slide deck here if you are interested.

Here are a handful of links that I showed during the talk.

http://www.microsoft.com/surface/ http://code.msdn.microsoft.com/WindowsTouch

http://interknowlogy.com/ http://silverlight.interknowlogy.com/Videos/Surface/default.html

http://www.perceptivepixel.com/

http://vimeo.com/4206140 http://idlemode.com/2009/04/10/design-considerations-for-touch-ui/

http://www.designinggesturalinterfaces.com/

Note: Cross posted from Blog?.

Think outside the TextBox

I recently presented WPF and Silverlight material at Xamlfest - Denver. While I was there one of the students had an interesting idea. He was trying to do a simple drop shadow TextBlock in Silverlight.

Since Silverlight doesn't support Bitmap effects it wasn't as easy as adding a new BitmapDropShadow effect, like you would in WPF.

My first reaction was to have him try to re-template a TextBlock and fake the drop shadow. However, as we quickly found out, you can't re-template a TextBlock. This is because TextBlock inherits directly from FrameworkElement and handles it's own rendering. The Control class is where the Control Template is implemented. A good way to see this is by checking out the WPF poster created by our own John Bowen. This shows the hierarchy of the classes and you can see that TextBlock is a direct descendant of FrameworkElement, which means no control template.

So what to do? Well I thought about it for a little while and then decided that you could re-template a TextBox to act like a TextBlock (read only, no entry box, bind directly to a text property) TextBox supports re-templating (because it inherits from Control). Then we can fake a drop shadow effect inside the new template.

So first things first. Open blend and create a new Silverlight Application 

NewBlendProject

Then right click on the TextBlock icon on the left hand tool strip and select TextBox

SelectTextBox

This will change the tool strip icon to a TextBox control (instead of a TextBlock). Double click on the TextBox icon in the toolstrip to add a default size TextBox to your canvas.

Now we need to re-template the TextBox to act like TextBlock. That is, we want a read only piece of text. We want to be able to set the "Text" property to anything we want, and we don't want to Input box border and chrome to show up.

To do this in Blend you can right click on the TextBox that you added to your canvas and select "Edit Control Parts (Template)" and select "Edit a copy"

EditTemplate

Give your new style a name (I named mine DropShadowTextBlock) and click ok

This will take you in to Template editing mode you will notice that the Objects and Timeline window now shows the visual elements that make up the TextBox control Template

TextBoxTemplate

What we want to do is replace this template with a TextBlock and Bind the Text property of the TextBlock to the Text Property of the TextBox. This will allow the people who use our control to set the Text property and get the expected behavior.

So first highlight (ctrl+click) all the elements under the RootElement and hit delete.

ElementsToDelete

Now go over to your tool strip and select the TextBlock element and double click to add it to the RootElement.

TextBlockTemplate

Now we need to Bind the Text property of the TextBlock element to the Text property of the TextBox. To do this we will use a TemplateBinding.

Make sure your TextBlock is selected and go the properties panel and select the advanced property options for the text property

AdvancedPropertyOptions

From the Advanced property options context menu select TemplateBinding | Text

TemplateBindingText

Now let's test our TextBox as a TextBlock functionality. Exit template editing mode by click on the breadcrumb above the design canvas

Breadcrumb

Now we are back to our main design canvas and you can see our TextBox control looks like a TextBlock now (no border, read only). Let's test our template binding by setting the Text property

Select the TextBox from the Object and Timeline window. Go to the properties panel and set the Text property to something (I chose "Some Text"). You should see the text you enter reflected in your control on the design canvas (click on the design surface to make the control update)

Great! Now we have a control that we can re-template that acts like a TextBlock. Problem one solved. Now we need to fake a drop shadow.

Since we have a template-able "TextBlock" this part is fairly trivial.

We are going to add another TextBlock to our template, and TemplateBind it's Text property just like we did on the first one, and we are going to offset it to give a poor mans drop shadow effect.

So go back in to the TextBox template by selecting it from the Breadcrumb

TemplateBreadCrumb

Now add one more TextBlock to the RootElement grid (when you add multiple children to a grid it will stack them on top of each other)

When you do this you will see a jumbled up mess of text on your canvas. This is because we have not TemplateBound the Text property of the new TextBlock to the Text Property of the TextBox.

Mine look like this

JumbledText

So let's fix the TemplateBinding for the new TextBlock. Select the text block and then go to the Property panel and go to the Advanced Property Options for the Text property (just like we did for the first TextBlock) and then set the TemplateBinding to the Text property (just like before)

Once you set the Binding we just need to offset the TextBlock .5px below the TextBlock before it.

To set the Top Margin in Blend select the TextBlock you want to set the Margin on and go to the Property Panel. Find the Margin section and find the one with the arrow pointing upward. Then set the value you want.

TopMargin

Finally you probably want to give the new text block an opacity setting of 50% so that it is a lighter than the first one. This gives that shadow effect. When you are done you get something like this 

Finished

Like I said it is a poor man's drop shadow but it works and is pretty easy to implement.

This little exercise shows that you can use the power of control templating to do many different things. Sometimes you just have to think a little outside of the ... TextBox?

Mock Data in Blend - Using custom markup extensions

In an earlier post I talked about using mock data classes to share data between Blend and Unit Tests. The approach was pretty straight forward but it isn't an ideal long term solution.

It requires that your ViewModel class has the logic to construct Mock versions of it's dependencies. This means you will be writing some extra plumbing for each of your ViewModel classes that need this level of support.

So what can we do? Well I have been playing for Custom Markup extensions lately in WPF and the solution I have thus far is pretty handy. It isn't complete yet and I am sure there is room for improvement but I thought I would show what I have.

My thought was, I want some sort of object provider layer that will handle giving me an instance of the object I need, wether that be a mock instance or a real instance. I wanted the solution to be generic so that implementing it would be simple and straightforward.

So the first thing I did was to go into my XAML file where I wanted to use this feature and I took a couple of passes at writing the XAML the way I think I would want it.

As a side note, this process of writing your usage scenarios first then building code to support the usage scenario is really the only way to develop a good framework. From Framework Design Guidelines book

"DO design APIs by first writing code samples for the main scenarios and then defining the object model to support the code samples."

So here is what I tried. First I had this:

<Window.DataContext>
     <
IoCSample:ViewModel />
</
Window.DataContext>

I am setting the Windows DataContext in markup to an instance of my ViewModel object. That is ok and works with the technique described in my earlier post.

Then I thought doing this

<Window.DataContext>
    <
IoCSample:ObjectProvider DataType="IoCSample:ViewModel"/>
</
Window.DataContext>

 

So now I am setting the window's DataContext to an instance of a more generic object called, ObjectProvider and I am setting a property on the ObjectProvider clas called "DataType". This tells the object provider what type of object I need (in this case a ViewModel). The thinking was that the ObjectProvider class would determine if I was in design mode or not and give me an instance of the ViewModel class with either concrete or mock implementations of my dependencies.

But something about that approach just didn't feel right. So then I wrote this.

<Window x:Class="IoCSample.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:IoCSample="clr-namespace:IoCSample"
xmlns:CustomMarkupExtensions="clr-namespace:IoCSample.MarkupExtensions"
Title="Window1"Height="300"Width="300"
DataContext="{CustomMarkupExtensions:ObjectProvider IoCSample:ViewModel}">

 

This to me seemed more natural and I can see how this will be more flexible. So what I am doing here? I am setting the Windows' DataContext in attribute syntax (instead of element syntax as we were above). I am using a custom markup extension called ObjectProvider and I am setting the default property of the custom markup extension to my ViewModel type.

So think of the Binding markup extension. It's default property is Path so you can write a Binding like this

{Binding PersonFirstName}

This is saying use the Binding markup extension and set the default property (Path) to PersonFirstName.

Now look at my custom extension again.

{CustomMarkupExtensions:ObjectProvider IoCSample:ViewModel}

Use the ObjectProvider markup extension. Set it's default property (which is of type Type) to IoCSample:ViewModel, that is the ViewModel Type.

I won't go into how to build a custom markup extension in detail here as a colleague of mine, John Bowen, has written a nice post about it already. His post is what I used to get started with custom markup extensions so go read it.

So what does my markup extension do? Well the markup extension has one method called ProvideValue. This method get's called when the XAML parser is evaluating the markup extension. So when the XAML parser is constructing my Window and it hits the DataContext attribute it is going to call the ProvideValue method on my markup extension. Since I have set the ObjectType property to IoCSample:ViewModel in the markup when I get to the ProvideValue method I have the information I need to construct an instance of the object requested.

So now I have centralized the place where I will check for the IsInDesignMode property. This means my ViewModels don't have to know anything about DesignMode or not. Which is ideal since the ViewModel really shouldn't be responsible for making that decision and shouldn't be forked to support the two different scenarios.

So now if I encapsulate the construction of the object being requested then the ObjectProvider just has to call the appropriate factory to get back an instance of the object for the given environment (runtime or design time)

In my next post I will discuss a way to encapsulate the construction of this object to increase the flexibility of this approach.

Slide Deck and Sample App from Architecture SIG talk

Thanks to everyone who came out to our talk last night. We had some really good discussion and I even got to pimp out or Skunkworks surface video :)

 

You can get a copy of our demo app and our Slide Deck here

Posted: 11-13-2008 5:21 PM by Brad Cunningham | with no comments
Filed under:
TechDays material

Thanks to all who came out to the TechDays event today. You can get my slide deck and demo code here (The slide deck is a solution item in the visual studio solution)

If you want to see our surface video again or any of our other XAML based projects (Silverlight, WPF, and Surface) you can check them out here

 

Lynn has posted presentation material from the other sessions today on her blog

Posted: 11-12-2008 2:14 AM by Brad Cunningham | with no comments
Filed under:
Code Camp Slide Deck and Sample Code

Thanks to everyone who came out to our Code Camp presentation (and sweated through the lack of A/C with us)

You can get a copy of our slide deck and our sample application here (The slide deck is added as a solution item)

(It requires VS 2008)

 

If you didn't get a chance to see the presentation we have, at least, one more date scheduled. November 12th at the San Diego .NET User Group Architecture SIG.

Photo Stackr (Silverlight goodness)

 

 

Update: I updated the code to work with Silverlight 2 RTW.

 

So with the release of the Silverlight 2 beta bits I finally decided to see what all the talk was about. I suppose I would consider myself an ASP.NET guy by trade. Although I have been building WPF applications for the past year or so and generally I am enjoying NOT building web applications. However, I can't hide the fact that I spent the last seven odd years building mostly ASP.NET applications.

So when I first heard of Silverlight and heard it was in the same vain as Flash I was skeptical to say the least. I would say I was somewhere closer to outright disgust. I spend so much time focusing on a lightweight client that offloads it's work to a controlled and decidedly beefier web server. There is no way I want to push a plug-in to a client and THEN pay the price of shoving all the assest's down the pipe and hoping their machine can handle it. but alas, I will give it a fair shake. I do like WPF after all.

So with that said I wanted to see what the development experience is like and what kind of things I could do with the WPF skills I had amassed.

 

Cue PhotoStackr (note the gratuitous web 2.0 spelling)

 

One of the things I really like with WPF, and the main thing that makes WPF so compelling to me, is that it gives you the ability to focus on user interaction and user experience and less on implementation details. This allows you to build incredible applications with minimal effort (compared to building the equivalent in WinForms). So before I show the gory details of my Silverlight application I will say that I was trying to build an application that models a known collection of data (in this case a set of photos from the flickr website) in a new / interesting way.

To that end Silverlight, really XAML in general, gives you the tools to visual your data quickly. For the photo stackr application I wanted to give a interesting way to view and organize multiple search results on a single page.

What I like about Silverlight is it changes the development paradigm on the web. With the plug-in architecture you have a stateful environment to develop to. You can write fully managed code to do things previously done on the client in JavaScript (like drag and drop)

The basic design idea of PhotoStackr is to have a "Photo Table", which is the main canvas of the application. On the table you will have multiple "Photo Stacks." These stacks are the result of searching the Flickr web service for a specified tag. The application will give you the ability to "un-stack" your search results so you can view all results at once. You can then zoom in on any one of the results to view the photo in more detail.

There is a link at the bottom of this post where you can get the entire project to view the code in more detail so I will just focus on the main points.

The main canvas is pretty simple I put a text block to show the title in the top left and then two custom controls, one for the search box and one for the about window. I am toggling the visibility of these controls on the button click event of the respective buttons. This brings me to my first annoyance with Silverlight. The current build doesn't support triggers. Triggers are fundamental (IMHO) to WPF. Since I am approaching Silverlight with a WPF background the lack of triggers is painfully obvious. However, Sivlerlight is still in beta so some features just aren't there. I don't know if there is a plan to support triggers in Silverlight. Personally, I think they have to be supported if they want Silverlight to follow the "Do it in markup, not in code" mantra.

 

<Canvas Background="Black" x:Name="Table" Loaded="Table_Loaded" SizeChanged="Table_SizeChanged" >

<TextBlock x:Name="Title"Text="Photo Stackr"FontSize="16"    Canvas.Left="100" Canvas.Top="50" Opacity=".4"/>

<Button x:Name="AddButton"Click="AddButton_Click" Template="{StaticResource AddStackButtonTemplate}" Canvas.Left="100"Canvas.Top="650"/>

<Button x:Name="AboutButton"Click="AboutButton_Click" Template="{StaticResource AboutButtonTemplate}" Canvas.Left="125"  Canvas.Top="650"/>

<local:MessageControl x:Name="About"Canvas.Left="250"Visibility="Collapsed"/> <local:SearchPopup x:Name="SearchPopup"Canvas.Left="100"Visibility="Collapsed" />

</Canvas>

 

I like the control architecture that Silverlight drives you towards. I have built the SearchPopup and the MessageControl as separate UserControls in it's own XAML file. This is nothing revolutionary, you could do this in ASP.NET with custom controls, but with the stateful environment it makes managing multiple controls much easier. The controls are more aware of the application domain data and don't need state management code to work with the rest of the application. This gives you a development experience much closer to desktop development. This is a big plus to me.

When the user enters a search tag and clicks the search button I create a PolaroidStack control. This control is a canvas that has the logic to manage multiple Polaroid controls and perform the stack and un-stack behaviors. This brings me to the first programming feature that I really like about Silverlight. On the PolaroidStack control I added a static dependency property called SelectedTag

 

public static readonly DependencyProperty SelectedTagProperty =

DependencyProperty.Register("SelectedTag", typeof(string),

typeof(UserControl),OnSelectedTagChanged);

 

Dependency properties come from WPF and are a key component to control development. Since I have a dependency property on the PolaroidStack all I have to do in code is set the property and the change handler code in the stack control will take care of the rest. 

 

PolaroidStack s = new PolaroidStack();

s.SetValue(PolaroidStack.SelectedTagProperty, SearchPhrase.Text);

 

Change handler for the PolaroidStack.SelectedTag property:

 

private static void OnSelectedTagChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)

{

    //Reload the Polaroid Stack

    ((PolaroidStack)d).LoadStack(e.NewValue.ToString());

}

 

The nice thing about the DependencyProperty is that it can also be set in markup. If I created the PolaroidStack in markup I could set the SelectedTag property in the markup as well which would cause the stack load itself when the control is loaded (and this is exactly what I did to test the LoadStack functionality)

In the LoadStack method I make a call the the Flickr Rest based Webservice passing the tag that the user passed in as the search term. The only thing to note here is that I am processing the result of the web service using LinqToXml which makes processing the XML document leaps and bounds easier then before.

 

XDocument doc = XDocument.Parse(e.Result);

var photos = from results in doc.Descendants("photo")

select new

{

    id = results.Attribute("id").Value.ToString(),

    farm = results.Attribute("farm").Value.ToString(),

    server = results.Attribute("server").Value.ToString(),

    secret = results.Attribute("secret").Value.ToString()

};

 

This snippet of code basically creates a dynamic collection and I am defining the members of the objects in the collection by selecting the attributes from the XML document. So I have a collection of Photos, the items in the collection are of type Photo. The Photo type (which is a dynamic type created by LINQ when I call select new) has string members id,farm,server, and secret. And this ends my LINQToXML lesson :), LinqToXML is really cool, for more info check here

After processing the web service response into a collection of Photo objects, I iterate the collection and build a new Polaroid control. The Polaroid control is a custom user control composed of an Image control, a button to control the zoom, and a border to give the look and feel of a Polaroid.

 

<Canvas Height="110" Width="91" Background="#FFFFFFFF" x:Name="PolariodCanvas">

    <Button x:Name="Zoomer" Canvas.Left="70" Canvas.Top="95.666" Click="Button_Click" />
    <
Image x:Name="imageControl"  Height="75" Width="75" Stretch="Fill" Canvas.Top="8" Canvas.Left="8"/>

<Border Height="75.75" Width="76.006" Canvas.Left="8" Canvas.Top="8" BorderBrush="#FF000000" BorderThickness="1,1,1,1"/>


</
Canvas>
 

I am also creating a rotate transform in code to randomly set the angle of the Polaroid control to give it the messy look when stacked on top of each other. Again, the control development approach works nicely here because I can keep the logic to zoom the Polaroid in the Polaroid control.

The last thing to point out here is how I implemented drag and drop logic. I wanted to give the ability to drag and drop the PolaroidStack control so I hooked into the mouse button events of the Polaroid control. The actual drag and drop code is nothing new but the ability to do it all in managed code is the big difference. Previously this type of thing would have to be done in javascript. With Silverlight you can do it all in managed C# code

 

private void PolariodStack_MouseMove(object sender, MouseEventArgs e)
{
    // only execute this code when the user has started dragging
   
if (startDrag)
    {
            Point movePos = e.GetPosition(null);
           double currentX = double.Parse(this.GetValue (Canvas.LeftProperty).ToString()) + (movePos.X - beginPos.X);
           double currentY = double.Parse(this.GetValue(Canvas.TopProperty).ToString()) + (movePos.Y - beginPos.Y)
        ...

         this.SetValue(Canvas.LeftProperty, currentX);
         this.SetValue(Canvas.TopProperty, currentY);
         beginPos = movePos;
    }
}

 

<Borat> Very Nice </Borat>

 

You can get the code for this project here. NOTE: you will have to sign up for a Flickr account and get your own API key to get this to work. I purposely forced a compile error to show you were to enter your API key.

So in the end, I like what Silverlight offers so far but it isn't all the way there yet. The lack of support for DataTemplates and Triggers  are glaring issues. I am also still not sold on the plug-in approach. Solving the satefulness issue is huge and I think that is the overriding win with the plug-in approach but I am still concerned with pushing that much on to the client machine. The temptation to abuse the technology is high and pushing really intensive applications down the wire to the client can lead to bloated applications and serious support issues.

 

To see the application in action visit our Silverlight page silverlight.interknowlogy.com

 

Tell me what you think

 

As I wrote this I thought of clever way to use this same data visualization for another purpose....... So stay tuned for an update.

Sharing Mock Data for Unit Tests and Blend

I have been diving in to Inversion of Control and specifically the Dependency Injection / Inversion (DI) pattern recently and I have been trying to find legitimate ways to fit the pattern into my workflow. First off I will say I really like the DI pattern and it has plenty benefits which I will try to discuss in a series of blog posts in the future (or if you want to hear about it in person come to my presentation at Code Camp)

 

What I have been to trying to work out this week is how can I provide a seamless way for developers and designers to share mock data between unit tests and Blend. The prerequisite for this approach to make sense is that you are doing unit tests during your development process. Assuming that is the case then I think the following solution could work out nicely.

 

If you are following the DI pattern then you will know that it is easy to swap out different concrete types for a given interface. The DI patterns focuses on the idea of programming against interfaces. That way, your code is decoupled from the details of the implementing type. This allows you to easily swap out the real version of your data classes for Mock versions. This gives you a nice way to cleanly unit test your code without being dependent on any sort of external environment (SQL DB, Web Services, etc..)

 

So if you are following this pattern and creating mock versions of your data classes why not share those with Blend designers? One of the complaints I hear often from Blend designers is that they struggle to create data visualizations when they don't have any data (duh). Using mock data classes is a great way to provide sample data for designers to use in Blend so they can see what the screen will look like when it is connected to data. If you are already creating the mocks for unit test purposes then sharing with Blend isn't any much more work on your part.

 

If you separate your Interface definitions and your Mock Data classes in to separate .NET projects like this

 

ProjectSeperation

 

Then you have a way for your Unit Tests and your Main application to leverage the Mock Data. A unit test that uses the the MockPerson type might look something like this

var person = new MockPerson();

Assert.IsNotNull(person);
Assert.AreEqual(person.GetFirstName(), "MockFirstName");
Assert.AreEqual(person.GetLastName(), "MockLastName");
Assert.AreEqual(person.GetFullName(), "MockFirstName MockLastName");

 

Where the implementation of the MockPerson class looks like this

public class MockPerson : IPerson
{
public string GetFirstName()
{
return "MockFirstName";
}

public string GetLastName()
{
return "MockLastName";
}

public string GetFullName()
{
return string.Format("{0} {1}", GetFirstName(),
GetLastName());
}
}
 
Notice how MockPerson implements the IPerson interface. This is key to allowing the use 
of Mock data classes. I will dive deeper
into programming against interfaces and the DI
pattern in future posts.
Now if we want to use this MockPerson class to provide sample data to a designer in Blend 
we need first understand what Blend does when constructing your XAML file. My first
thought was that Blend would call my constructor in the XAML.cs file for the XAML file
I was opening in Blend.
However I was wrong. Blend will not call your constructor but it will construct any objects 
that are specified in the XAML markup itself. This means that if you set the DataContext
attribute of your XAML file in XAML like this
 <Window x:Class="IoCSample.Window1"
xmlns
="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:IoCSample
="clr-namespace:IoCSample"
Title="Window1" Height="300" Width="300">

<Window.DataContext>
<
IoCSample:ViewModel
/>
</
Window.DataContext
>
Then you will have a piece of code that you can hook into to check and see if you are 
in DesignMode. To check and see if you are in DesignMode you can use the following
code:
DependencyPropertyDescriptor descriptor = 
DependencyPropertyDescriptor.FromProperty(DesignerProperties.
IsInDesignModeProperty, typeof(System.Windows.DependencyObject));
var isInDesignMode = (bool)descriptor.Metadata.DefaultValue;

if (isInDesignMode)
{
}

Now to actually provide MockData to Blend we want to check this IsInDesignMode property and provide Mock implementations of the data classes we need. Sticking with the example above of IPerson and MockPerson, let's say that our ViewModel class (which is specified as the data context for the XAML file we are opening in Blend) has a property of type IPerson. Defined like this

public class ViewModel
{

public IPerson Person { get; set; }
public string PersonFirstName {get{return Person.GetFirstName();}}
public ViewModel()
{
   DependencyPropertyDescriptor descriptor = 
DependencyPropertyDescriptor.
FromProperty(DesignerProperties.IsInDesignModeProperty,
typeof(System.Windows.DependencyObject));
var isInDesignMode = (bool)descriptor.Metadata.DefaultValue;
if (isInDesignMode)
{
   }
}
}

And say we are binding to that property in our XAML like this (Remember our DataContext is set to the ViewModel class shown above so  {Binding PersonFirstName} refers to the PersonFirstName property on the ViewModel class)

<TextBlock Text="{Binding PersonFirstName}" />

 

Notice the check in the ViewModel constructor above to see if we are in design mode. Now we have a place to check if we are in design mode and create a MockPerson object if we are. To do that we will modify the ViewModel constructor to look like this:

public ViewModel()
{

    DependencyPropertyDescriptor descriptor = DependencyPropertyDescriptor.
FromProperty(DesignerProperties.IsInDesignModeProperty,
typeof(System.Windows.DependencyObject));

var isInDesignMode = (bool)descriptor.Metadata.DefaultValue;    

if (isInDesignMode)

{

    Person = new MockPerson();

 }
}

Remember from above that the MockPerson class has some "Mock" data (hence the name) in the property getters. So a call to Person.GetFirstName(); (which is called from the Binding in the XAML file {Binding PersonFirstName})  returns "MockFirstName" .

 

Now when we open this file in Blend it will fire the ViewModel constructor and make the check to see if we are in DesignMode, if we are it will construct a new MockPerson object and set the ViewModel IPerson property to the MockPerson instance. This will provide MockData to the Blend designer. This is a very basic approach to this solution. In a future blog post I will describe a more detailed approach that involves a custom markup extension and ties in to an Inversion of Control container to provide a generic way of registering Mock object dependencies with your IoC container for DesignTime and UnitTest development. But for now this solution should get you started and help you provide a richer design time experience for Blend designers.

Visual Studio XAML designer annoyances

 

UPDATE: MSFT has released a patch for the XAML designer in Visual Studio 2008 SP1. This patch appears to fix some edge cases with the designer that cause it to crash VS. You can get the patch here: http://code.msdn.microsoft.com/KB958017

I pretty much abandoned the integrated XAML designer in VS long ago. It is painfully slow to load and even after waiting several minutes for it load it usually just shows the brilliant "We're sorry... our designer blows" screen. Recently a co-worker was having some problems with XAML files crashing Visual Studio. He had just installed VS 2008 SP1 and .NET 3.5 SP1. No idea what the issue was but I suggested that he try switching his XAML editor to open XAML pages in full XAML view. I realized that maybe other people don't know how to do this since the option is buried pretty deep.

 

So a quick to post to show how to do this.

In the VS IDE click Tool | Options

ToolsOptions

 

Then expand the tree for Text Editor

TextEditor

 

Scroll down and you should see a XAML section. Expand the XAML tree

 

XamlTree

 

Then click on the Miscellaneous item. Now you will see a check box that says "Always open documents in full XAML view"

 

FullXamlView

Click OK and you are all set. Now when you open XAML files in VS they will open in full markup view. This prevents the designer from loading. This should speed up the time it takes to open XAML files. And in some cases it looks like it prevents the IDE from crashing. Interesting to note, after making this change my coworker was able to switch to design view and reload the designer and this time it did not crash Visual Studio. hmmm? Race condition maybe?

Posted: 10-20-2008 5:00 PM by Brad Cunningham | with 3 comment(s)
Filed under:
More Posts Next page »