# Friday, April 24, 2009

If you’ll be in the northwest Arkansas area tomorrow (April 25), be sure to come out for the NWA Code Camp. There will be presentations on everything ranging from LINQ and Silverlight to iPhone development. I’ll be presenting my PowerShell talk one more time as well. If I can count at all, it looks like there will be 15 different speakers total.

I’m looking forward to it!

image 

Technorati Tags:
posted on Friday, April 24, 2009 7:28:37 AM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Monday, March 30, 2009

This is just a quick post to share a very simple PowerShell script I wrote to extract files from a compressed file (zip, 7z, whatever). When downloading utilities that don’t have installers, like Sysinternals tools, I typically extract them to a Utils directory that is in my PATH. Previously, I would always do this by right-clicking, choosing the 7-Zip context menu option and then extracting to to c:\Utils. Another common option would be to extract to a folder of the same name.

image

I had tried in the past to use the 7-Zip command line tool, but the arguments were not very intuitive or consistent with other command line tools (Windows, Unix, PowerShell or otherwise). So, I got fed up and wrote a script to do it for me. It just shells out to the 7-Zip command line app, but it saves me some time.

The script assumes that you’ve aliased ‘zip’ to the 7z.exe command line executable.

[1] » ls alias:zip

CommandType     Name                                                  Definition
-----------     ----                                                  ----------
Alias           zip                                                   7z

[2] » get-command 7z

CommandType     Name                                                  Definition
-----------     ----                                                  ----------
Application     7z.exe                                                C:\Utils\7z.exe

Here’s the script:

param (
    [string]$file,
    [string]$outputDir = ''
)

if (-not (Test-Path $file)) {
    $file = Resolve-Path $file
}

if ($outputDir -eq '') {
    $outputDir = [System.IO.Path]::GetFileNameWithoutExtension($file)
}

zip e "-o$outputDir" $file

Like I said, pretty basic. If you don’t specify an output directory, it uses the name of the file.

Other people have written scripts that do this, too, but I needed an excuse to publish something on my blog for March :-)

posted on Monday, March 30, 2009 9:55:29 PM (Central Daylight Time, UTC-05:00)  #    Comments [0]
# Wednesday, February 25, 2009

I couldn’t resist borrowing my title from Christopher Bennage’s post entitled “An Essential Tip for Working with XAML.” My “essential tip” is identical to what he has already shown for WPF (and Fabrice originally) – it just applies to Windows Forms instead of WPF :-)

I’ll mix it up some and show with pictures instead of text, though.

Step 1. Right click on a Form, UserControl, or Component and select “Open With…”

image

Step 2. Select “CSharp Editor” and click “Set as Default” - (note that this setting only applies to C# code, though you can perform the identical setup for VB.NET as well)

image

Step 3. Enjoy your delicious, hot meal of faster Visual Studio!

In case you missed it, the real benefit that you get from this setting is that double clicking a file in the Solution Explorer will now go directly to the code instead of defaulting to the designer view. If you want to get to the designer view, just right click and select “View Designer.”

Thanks again to Christopher and Fabrice who did the real work here!

posted on Wednesday, February 25, 2009 10:32:12 AM (Central Standard Time, UTC-06:00)  #    Comments [0]
# Monday, February 23, 2009

WiX Setup

I’ve been doing some work with MSIs lately, specifically using the WiX toolkit, so I thought I’d share a short primer on using WiX to build your own MSIs, and also to share some links and some tricks to avoid some pitfalls that I ran into.

First off, WiX stands for Windows Installer XML and, from what I understand, is the first Microsoft-supported open source project. Not only that, but it is the way that Microsoft builds their MSIs, too, so it is pretty significant.

To get started, I wouldn’t even bother with the release version of 2.0. The real fun is in version 3.0, which, even though it is in beta, is plenty stable (IMHO) and supports Visual Studio with a project template and intellisense support via schema files. It also makes the building step a lot easier.

image

My First WiX Project

Once you start your project, you’re presented with a WXS file pre-filled with a few initial options that looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
    <Product Id="de9157d6-2fbf-4c16-9d28-77f790788b28" Name="WixProject1" Language="1033" Version="1.0.0.0" Manufacturer="WixProject1" UpgradeCode="f5614cd8-aa70-4bc4-948b-208b34e16a6d">
        <Package InstallerVersion="200" Compressed="yes" />

        <Media Id="1" Cabinet="media1.cab" EmbedCab="yes" />

        <Directory Id="TARGETDIR" Name="SourceDir">
            <Directory Id="ProgramFilesFolder">
                <Directory Id="INSTALLLOCATION" Name="WixProject1">
                    <!-- TODO: Remove the comments around this Component element and the ComponentRef below in order to add resources to this installer. -->
                    <!-- <Component Id="ProductComponent" Guid="95758d74-281c-4eee-84ce-4fda6ad60557"> -->
                        <!-- TODO: Insert files, registry keys, and other resources here. -->
                    <!-- </Component> -->
                </Directory>
            </Directory>
        </Directory>

        <Feature Id="ProductFeature" Title="WixProject1" Level="1">
            <!-- TODO: Remove the comments around this ComponentRef element and the Component above in order to add resources to this installer. -->
            <!-- <ComponentRef Id="ProductComponent" /> -->
        </Feature>
    </Product>
</Wix>

It has most of the things that you’ll be interested in.

The Product element is likely the most important element as it defines the application that your MSI will install. You’ll notice that WiX is built around a lot of Guids. MSIs, or Windows Installer actually, is built around tables. Using the orca tool that ships with the Windows SDK, you can actually see these tables for any MSI. (FYI, you’ll find your Product Id Guid if you look under \\HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\ after installation.)

image

You Can Refactor WiX, Too

Before going further with your WiX file, I would strongly recommend refactoring some of the Guids and common strings out into variables like so:

<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
  <?define ProductName = "WixProject1"?>
  <?define ProductCode = "de9157d6-2fbf-4c16-9d28-77f790788b28"?>
  <?define UpgradeCode = "f5614cd8-aa70-4bc4-948b-208b34e16a6d"?>
  <?define ProductVersion = "1.0.0.0"?>
  
  <Product Id="$(var.ProductCode)"
           Name="$(var.ProductName)"
           Language="1033"
           Version="$(var.ProductVersion)"
           Manufacturer="WixProject1"
           UpgradeCode="$(var.UpgradeCode)">

Doing this can help you greatly later when you’re trying to figure out which Guid goes where or what the Guid is actually for. The rest of the process of building your WiX file involves mapping out your dependencies. The project template by default already creates Directory elements pointing to the ProgramFilesFolder constant (see http://msdn.microsoft.com/en-us/library/aa370905(VS.85).aspx#system_folder_properties for the other system folder constants). The Component tag resolves to what I think of as a separate installable component. Components go together to form a Feature (think Complete versus Custom installs) so you’ll refer to your Component (by Id) in the Feature element using a ComponentRef element. The template has this commented out, but it shows how this would work. I’ll defer to the WiX Tutorial for specific examples here.

To build your MSI, you just have to do a Visual Studio build because you followed my instructions and installed beta 3.0, which comes with Visual Studio integration! Behind the scenes, though, all the build does is call out to candle.exe passing in your WXS file which results in a wixobj file. Then it calls out to light.exe passing in the wixobj file which results in an MSI. (WiX is pronounced like “wicks” – that should help you get the candle and light jokes… WiX also includes tools like dark, torch, votive, smoke, melt… :-))

Upgrading!

Up to this point, I didn’t really run into any problems with building my MSI. The online resources were fairly good at getting me started. What I wanted was for my MSI to be able to remove existing versions of my software before installing its version. MSIs support three types of upgrades: small update, minor upgrade, and major upgrades. I’d recommend skipping directly to major upgrade. From what I’ve seen so far, the other two options require additional command line arguments to msiexec to actually perform the removal of a prior install of your product.

To get a major upgrade to work, the most important thing you’ll need is your UpgradeCode. This is an attribute off of your Product element tag. Always store that off, regardless of whether or not you plan on allowing upgrades. As soon as you decide you don’t need to upgrade, you’ll want to upgrade. If you don’t have an UpgradeCode, you can’t upgrade.

You’ll use your UpgradeCode in an Upgrade tag like so:

<Upgrade Id='$(var.UpgradeCode)'>
  <UpgradeVersion Minimum='$(var.ProductVersion)'
                  IncludeMinimum='no'
                  OnlyDetect='yes'
                  Property='NEWPRODUCTFOUND' />
  <UpgradeVersion Minimum='$(var.RTMProductVersion)'
                  IncludeMinimum='yes'
                  Maximum='$(var.ProductVersion)'
                  IncludeMaximum='no'
                  Property='UPGRADEFOUND' />
</Upgrade>

Notice how I’m using my predefined variables. Makes it easier, eh? I’ve also added an additional variable defined as RTMProductVersion. This is the version of my installed application that I am upgrading from. UpgradeVersion tags work like ranges. So, for the UPGRADEFOUND to match, the installed application has to match inclusive RTMProductVersion (inclusive because of IncludeMinimum=’yes’) up to exclusive ProductVersion, which is the new version we’re about to install.

Now, changing the version isn’t enough for a major upgrade to work. You also need to change your ProductCode. This is what I continued to miss and why I was getting so frustrated with WiX. Now that I know what it should do (and what to search for), I’m finding plenty of WiX articles on how to do major upgrades! The reasoning for this is because major upgrades only work between two completely different products (think of Visual Studio 2005 and Visual Studio 2008 as having two different ProductCodes). These two products can run side-by-side, hence the different Guids for their product code. These applications allow side-by-side execution so they’re not specifying the removal of the old software, but they certainly could. MSDN has a good article on everything that you’ll need to check before getting an MSI ready for a major upgrade.

Once you have a new version and a new product code, you’ll need to actually tell the MSI to remove the existing version. To do this, you’ll add a RemoveExistingProducts element to an InstallExecuteSequence. Like this:

<InstallExecuteSequence>
  <Custom Action='PreventDowngrading'
          After='FindRelatedProducts'>NEWPRODUCTFOUND</Custom>
  <RemoveExistingProducts After='InstallFinalize' />
</InstallExecuteSequence>

<InstallUISequence>
  <Custom Action='PreventDowngrading'
          After='FindRelatedProducts'>NEWPRODUCTFOUND</Custom>
</InstallUISequence>

<CustomAction Id='PreventDowngrading'
              Error='Newer version already installed' />

In my example, I’ve told RemoveExistingProducts to run after the ‘InstallFinalize’ action, but this is customizable and can have an impact on the efficiency of your installer.

Once I set my WiX project up like this, it worked like a charm.

There are two resources that are essential for getting up to speed with WiX that I’d like to share. One is the WiX Tutorial. I’m probably using about a 10th of the content posted there. Second is Alex Shevchuk’s “From MSI to WiX” articles, particularly his post on major upgrades, which was invaluable to me.

posted on Monday, February 23, 2009 1:38:15 PM (Central Standard Time, UTC-06:00)  #    Comments [1]
# Monday, January 26, 2009

If you’ve been writing .NET applications for a while, you’re likely aware that you’re not supposed to just throw Exception. Instead, if you’re dealing with a null argument, you should be throwing an ArgumentNullException instead. FxCop warns against cases like this.

My problem isn’t knowing to not throw Exception. My problem is finding the appropriate exception to throw.

Just about every time I need to throw an exception in code, I type something like throw new… then wait for intellisense, and then inevitably try to type something like *Exception. Which fails of course. Then I do a google search for common exception types and will come across a post like Brad Abram’s Common Exception Types. Which is somewhat useful, except that his list only contains Exception names including Exceptions like the InvalidProgramException, which has a description of “the exception that is thrown when a program contains invalid MSIL.” Most likely not what I need :-) Jeff Atwood has an older post about a console application he wrote to write out Exception types from assemblies, but once again, it doesn’t provide the description I needed to help make my decision, too.

So, I decided to solve this problem myself.

I liked Jeff’s approach because it was lightweight and could be piped to programs like findstr so that I could look for certain types of exceptions. I essentially wanted what he had, but I wanted summary information as well. I ended up solving the problem with PowerShell. First, check out the output:

[3] » Get-Exception Null | Format-List

Name    : System.ArgumentNullException
Summary : The exception that is thrown when a null reference (Nothing in Visual Basic) is passed to a method that does not
          accept it as a valid argument.

Name    : System.NullReferenceException
Summary : The exception that is thrown when there is an attempt to dereference a null object reference.

Name    : System.Management.Automation.PSArgumentNullException
Summary : No summary found.

Name    : System.Data.NoNullAllowedException
Summary : No summary found.

Name    : System.Data.SqlTypes.SqlNullValueException
Summary : No summary found.

As you can see, my script is called Get-Exception and it can handle searches. The results can be passed to the various formatting cmdlets like Format-List. You can also pipe the results to Select-String for further searching if you wish or just pipe it to a Where statement.

The script itself is fairly simple. The pulling of exception types is based entirely off of the following statement:

$exceptions = [System.AppDomain]::CurrentDomain.GetAssemblies() | foreach {   
    $_.GetTypes() | where { $_.FullName -match "System$filter.*Exception$" }  
}

To pull the summary documentation, I’m using the returned type’s Assembly.Location property and checking for an XML file with the same name at the same location. This usually equates to an XML file in C:\windows\microsoft.net\framework\v2.0.50727. Then I use an XPath expression against it.

I’ve posted the script out on the PowerShell Code Repository at http://poshcode.org/827 if you’re interested in downloading it and trying it out. There are a lot of other great scripts there as well.

posted on Monday, January 26, 2009 7:47:21 AM (Central Standard Time, UTC-06:00)  #    Comments [3]
# Monday, January 12, 2009

Tonight, the FSDNUG group participated in their first launch event ever – for SQL Server 2008! Woo!

The gist of it was that 4 of us took about 15 to 20 minutes to talk about different portions of SQL Server. It turned out to be more intro than deep dives, but I think the group got more out of the presentation this way.

My portion of the presentation was on SQL CLR.

I think my talk went alright, but my demo definitely didn’t work. I blamed the Windows 7 beta but it probably had more to do with my lack of knowledge. *shrug* If you’re interested in trying the example out for yourself, Bashar Kokash has a good post on it. The example worked fine on my machine without any problems the first time, but during the talk, the Visual Studio deployment apparently didn’t work. Oh well.

The other code examples that I had all are linked off of the MSDN overview of SQL CLR link from above, so knock yourself out. Keith Elder’s post on creating custom SQL CLR user-defined types is also a good start.

The final two links I used were this one from SQL Skills and this one… that provided most of my information :-) Thanks Google!

I enjoyed the chance to present again! If you have any feedback, feel free to let me know.

posted on Monday, January 12, 2009 10:09:06 PM (Central Standard Time, UTC-06:00)  #    Comments [0]
# Thursday, January 01, 2009

So, a year ago to the day, I posted my review of 2007 with a look towards 2008. To continue that age old tradition, I will now review 2008.

Learning

I started off the month by stating that I wanted to learn some new languages, primarily Python and Ruby. I’m sad to say that I haven’t made it past the 5th python challenge yet. I pretty much got distracted, which is a lame excuse. On the other hand, instead of learning languages, I’ve learned a ton about editing in VIM and even a little about Emacs (though I have to use viper or vimpulse to be at all productive in Emacs). I’m even using ViEmu in Visual Studio. The Vim key-bindings have become muscle memory now and I consider that a positive thing. I’m still going to try to learn other languages this year, but I’m going to need a project to work on before I can become proficient.

FSDNUG

This year, a very exciting thing for me was the formation of FSDNUG. Michael Paladino pretty much did all of the work, but he lets me call myself a co-leader. Raymond Lewallen opened up the FSDNUG meetings by speaking about Behavior Driven Development. I didn’t really grok BDD at that point, but I’m learning. I most definitely prefer the context/specification style of naming specs over traditional TDD test names.

Conferences

I was fortunate enough to attend both Tech Ed and DevLink this year. I even told people at DevLink that I’d be attending CodeMash, but I sadly won’t be able to make it after all. I have no doubts that it will be an amazing conference, though, and wish I could be there.

Presentations

I presented on PowerShell three times in 2008. Once to FSDNUG, once to MNUG and then once to Harding University CS students. My presentations pretty much took up all of September. It was a great experience and I’m looking forward to speaking to the Shreveport .NET User Group in March!

Posts

My post on “real world debugging witn WinDbg” post was featured on the Tech Ed bloggers site, which led to me being selected as a “featured Tech Ed blogger” for a day. I was also excited to have my PowerShell thumbnail script mentioned on the PowerScripting Podcast.

In closing…

All in all, a really great year. I noted in 2007, that it had been the year of the most growth for me as a developer. That was true… at least until 2008. My opinion right now is that there is no such thing as a good developer, only a better developer. This saying comes from a discussion I had with a coworker a few months back where we came to the conclusion that there isn’t such a thing as a good design or architecture, only a better design or architecture – all because we’ll inevitably have learned a better way to do things in the future.

I hope everyone has a great 2009!

posted on Thursday, January 01, 2009 2:13:41 PM (Central Standard Time, UTC-06:00)  #    Comments [1]
# Wednesday, December 31, 2008

Last week, the PowerShell team released PowerShell v2 CTP3. And, of course, there was much rejoicing. I’ve got quite a bit I’d like to blog about regarding PowerShell, but I couldn’t wait to share one feature I love.

PowerShell ISE Themes.

Okay, so, it doesn’t actually ship with themes. But you can create them. Let me provide some background. The “ISE” in PowerShell ISE stands for Integrated Scripting Environment and is based on the upcoming WPF editor that will ship with Visual Studio 2010. Here is a screenshot of it.

image

As you can see, there are three panes included: one that allows you to edit PS1 scripts (with syntax highlighting and tab completion included), one that displays the output of your commands (whether from the script editor or the command pane), and one that allows you to type in commands (the equivalent of the prompt you get in the console host).

I’ll admit, when I heard about the graphical host, I thought it was nice but I really didn’t think I’d use it much. I use gVim to edit my scripts and have the console up all day. Why did I need another editor? I didn’t get really excited until I saw all of the customizations that you can do with it.

The $psISE variable offers up a wealth of options. I’m particularly fond of the Options property off of $psISE. I’ll let the screenshot describe why:

image

Looks different, eh? Below is the code to get it to work:

# PowerShell ISE version of the VIM blackboard theme at 
# http://www.vim.org/scripts/script.php?script_id=2280

# fonts
$psISE.Options.FontName = 'DejaVu Sans Mono'
$psISE.Options.FontSize = 16

# output pane
$psISE.Options.OutputPaneBackground = '#FF000000'
$psISE.Options.OutputPaneTextBackground = '#FF000000'
$psISE.Options.OutputPaneForeground = '#FFFFFFFF'

# command pane
$psISE.Options.CommandPaneBackground = '#FF000000'

# script pane
$psISE.Options.ScriptPaneBackground = '#FF000000'

# tokens
$psISE.Options.TokenColors['Command'] = '#FFFFFF60'
$psISE.Options.TokenColors['Unknown'] = '#FFFFFFFF'
$psISE.Options.TokenColors['Member'] = '#FFFFFFFF'
$psISE.Options.TokenColors['Position'] = '#FFFFFFFF'
$psISE.Options.TokenColors['GroupEnd'] = '#FFFFFFFF'
$psISE.Options.TokenColors['GroupStart'] = '#FFFFFFFF'
$psISE.Options.TokenColors['LineContinuation'] = '#FFFFFFFF'
$psISE.Options.TokenColors['NewLine'] = '#FFFFFFFF'
$psISE.Options.TokenColors['StatementSeparator'] = '#FFFFFFFF'
$psISE.Options.TokenColors['Comment'] = '#FFAEAEAE'
$psISE.Options.TokenColors['String'] = '#FF00D42D'
$psISE.Options.TokenColors['Keyword'] = '#FFFFDE00'
$psISE.Options.TokenColors['Attribute'] = '#FF84A7C1'
$psISE.Options.TokenColors['Type'] = '#FF84A7C1'
$psISE.Options.TokenColors['Variable'] = '#FF00D42D'
$psISE.Options.TokenColors['CommandParameter'] = '#FFFFDE00'
$psISE.Options.TokenColors['CommandArgument'] = '#FFFFFFFF'
$psISE.Options.TokenColors['Number'] = '#FF98FE1E'

To use it, I just dot the script into my PowerShell ISE profile (see the $profile variable while in PowerShell ISE) like so (where ./Themes/blackboard.ps1 is the path to the blackboard theme):

. ./Themes/blackboard.ps1

The script is a conversion I did of the vim blackboard theme which itself is a clone of the blackboard theme from TextMate. I’m sure it could use some tweaking, but it works for me for now.

One thing I’m missing so far is how to change the color of the text caret. Because I have a black background, I can’t see where I’ve got focus in the editor! Hopefully the PowerShell team will add an additional property to the Options to change the caret color or, even better, hopefully I’ve just missed the setting :-)

Let me know what you think! I’ve got even more PowerShell profile posts I’m working on so stay tuned.

UPDATE: Based on Joel’s comment, I’ve posted a bug on the Microsoft Connect site for PowerShell. Go vote for it at https://connect.microsoft.com/feedback/ViewFeedback.aspx?FeedbackID=390304&SiteID=99. Note that you can only access the site if you’ve signed up on Microsoft Connect and added PowerShell as a project.

posted on Wednesday, December 31, 2008 9:17:11 AM (Central Standard Time, UTC-06:00)  #    Comments [5]
# Friday, December 05, 2008

This post presents a problem that has been approached by others before, but I thought I’d offer yet another possible solution. But first, let’s introduce the problem!

In my experience, real world applications (aka NOT demos) don’t display data that was hard-coded in an application. For my part, the data is usually coming from some remote service or endpoint, so I’m either working with some proxy to a WCF, ASMX, or remoting endpoint. It seems that most WPF demos that showcase data-binding imagine a scenario where the data is readily available to the designer which allows them, at design-time, to see what the application might look like with real data loaded.

Check out the below screenshot of an amazing application that I created this morning.

image

As you can tell, I’m displaying a list of accounts by name and balance. The UI on this thing is unbelievable, too, because it also makes the balance red when their balance is below zero. Go WPF!

Seriously, though, I’ve tried to structure this like I might a real application. I’m a huge fan of the CompositeWPF library (*cough* Prism *cough*), so I’m using a Model-View-Presenter approach here, where the View is binding to a PresentationModel. You can see some examples of this in the StockTrader reference application that ships with CompositeWPF. The presenter’s only job is to hook up the data binding to the view and then load the PresentationModel up with data from the service. (Note that it would be very easy to add threading support here so that, while pulling data from IService, we don’t lock up the UI)

public class Presenter  
{  
    private readonly IView _view;  
    private readonly IService _service;  
    private readonly PresentationModel _presentationModel;  
  
    public Presenter(IView view, IService service, PresentationModel presentationModel)  
    {  
        _view = view;  
        _service = service;  
        _presentationModel = presentationModel;  
    }  
  
    public void Run()  
    {  
        _view.Model = _presentationModel;  
        LoadAccounts();  
    }  
  
    private void LoadAccounts()  
    {  
        foreach (var acct in _service.GetAccounts())  
            _presentationModel.Accounts.Add(acct);  
    }  
}

The PresentationModel only exposes an ObservableCollection of Accounts.

public class PresentationModel  
{  
    private readonly ObservableCollection<Account> _accounts = new ObservableCollection<Account>();  
    public ObservableCollection<Account> Accounts  
    {  
        get  
        {  
            return _accounts;  
        }  
    }  
}

The code for Window1.xaml is below.

<Window  
  x:Class="WpfApplication1.Window1"  
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
  xmlns:local="clr-namespace:WpfApplication1"  
  Title="Window1"  
  Height="300"  
  Width="300">  
    
  <local:AccountDisplay  
    DataContext="{Binding}" />  
</Window>

I’m just tying the DataContext for my AccountDisplay UserControl to whatever Binding is set to the Window. This allows the data binding to just flow through the rest of the application. This is very flexible. But what about the code behind? It is pretty basic, too.

public partial class Window1 : Window, IView  
{  
    public Window1()  
    {  
        InitializeComponent();  
  
        var presenter = new Presenter(this, new RealService(), new PresentationModel());  
        presenter.Run();  
    }  
 
    #region IView Members  
  
    public object Model  
    {  
        get { return DataContext; }  
        set { DataContext = value; }  
    }  
 
    #endregion  
}

The sample isn’t using CompositeWPF, but if you’re familiar with it, you should realize that it would be very easy to plug it in. In fact, my example is screaming Inversion of Control because of the Dependency Injection that I’m already using with the Presenter. A conversion to using the CompositeWPF would start with replacing the local declaration of the AccountDisplay user control with a region and associated module and you’ll be well on your way.

The real display is in AccountDisplay. Here is its source:

<UserControl  
  x:Class="WpfApplication1.AccountDisplay"  
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
  xmlns:local="clr-namespace:WpfApplication1"  
  Height="300"  
  Width="300">  
    
  <UserControl.Resources>  
    <local:BalanceToBrushConverter  
      x:Key="BalanceToBrushConverter" />  
  </UserControl.Resources>  
  
  <ItemsControl  
    ItemsSource="{Binding Path=Accounts}">  
  
    <ItemsControl.ItemTemplate>  
      <DataTemplate>  
  
        <StackPanel  
          Orientation="Horizontal">  
          <Border  
            CornerRadius="5"  
            Padding="5"  
            BorderBrush="Black"  
            BorderThickness="2">  
            <TextBlock  
              Text="{Binding Path=Name}" />  
          </Border>  
          <Border  
            CornerRadius="5"  
            Padding="5"  
            BorderBrush="Black"  
            BorderThickness="2">  
            <TextBlock  
              Foreground="{Binding Path=Balance, Converter={StaticResource BalanceToBrushConverter}}"  
              Text="{Binding Path=Balance}" />  
          </Border>  
        </StackPanel>  
      </DataTemplate>  
    </ItemsControl.ItemTemplate>  
  
  </ItemsControl>  
</UserControl>

Here, I’m just using relative binding (Binding Path=Property) here. This means I’ll pick up data binding from the DataContext, which was set back in Window1.xaml (once again, a result of that flowing data binding).

So, where’s the problem? Let’s look at this from the designer perspective by opening AccountDisplay.xaml in Blend.

image

It… it looks really great. So… white and everything. Anyone know what the problem is? My Presenter is the guy who does the work to return accounts to bind to, but Blend is just showing us the XAML. This is good – we don’t want the fact that we’re designing this to actually run our code and hit our services. But… we still want some test data to design with, right? We could add some data to our XAML file… but then that affects us when we actually run the application. Besides, I personally want test data to match the structure of the model I’m binding to.

Here’s what I’m doing to fix this right now. I added the following 3 lines of code to AccountDisplay.xaml.

<local:Designer.DataContext>  
  <local:BlendPresentationModel />  
</local:Designer.DataContext>

That doesn’t tell you much, so I’ll show you the Designer class that is being referenced now.

/// <summary>  
/// Allows the use of design-time only data binding... seems to only work  
/// in Blend and not the VS designer...  
/// </summary>  
public static class Designer  
{  
    public static readonly DependencyProperty DataContextProperty =  
        DependencyProperty.RegisterAttached("DataContext", typeof (object), typeof (Designer),  
                                            new PropertyMetadata(OnDataContextChanged));  
  
    private static void OnDataContextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)  
    {  
        SetDataContext(d, e.NewValue);  
    }  
  
    public static void SetDataContext(DependencyObject d, object value)  
    {  
        var element = d as FrameworkElement;  
        if (element == null) return;  
  
        if (DesignerProperties.GetIsInDesignMode(element))  
            element.DataContext = value;  
    }

    public static object GetDataContext(DependencyObject d)
    {
        var element = d as FrameworkElement;
        if (element == null) return null;

        if (!DesignerProperties.GetIsInDesignMode(element))
            return null;

        return element.DataContext;
    }  
}

A few of things to note. I have a Dependency Property called DataContext first. I’m using a Dependency Property so that WPF data binding works. It can take any object (hence the typeof(object) parameter. When it changes, I call off to SetDataContext with the new value. Next important thing to note – DesignerProperties.GetIsInDesignMode. I try to cast the owner of my Designer instance (which is typically going to be a UserControl or Window or other UI element) to a FrameworkElement. I’m using FrameworkElement because it is the highest object in the hierarchy that provides the DataContext property. Then, if we’re in Design mode, I override the DataContext with my Designer DataContext.

In the XAML, what ends up getting set is a BlendPresentationModel, which looks like this:

public class BlendPresentationModel : PresentationModel  
{  
    public BlendPresentationModel()  
    {  
        var accounts = new List<Account>  
                           {  
                               new Account  
                                   {  
                                       Name = "Bob's Stuff",  
                                       Balance = 1000000  
                                   },  
                               new Account  
                                   {  
                                       Name = "Cheap Skate",  
                                       Balance = -100  
                                   }  
                           };  
        foreach (var acct in accounts)  
            Accounts.Add(acct);  
    }  
}

With my approach, I’ve created an object that inherits from my PresentationModel, so the object I’m binding my UI to is the same type that I’m using when running, but I’m providing test data instead. This is what it looks like in Blend now:

image

In one of my projects, I’ve been dropping these guys around in various UserControls and even one at the top level Window so that I can see what it all looks like together. So far, it is working well.

The biggest problem I’ve got with this solution so far is that the Visual Studio designer doesn’t render the test data. I would guess that this would be fixed at some point – honestly, the rendering of XAML should be the same between Blend and Visual Studio and, if it isn’t, it should be fixed.

Karl Shifflett posts a solution to this as well – my solution is basically just my own take on what he’s already done, so thanks to him for the initial idea. I wasn’t using Resources for binding, which is the primary reason I started with my own solution.

Also, Laurent Bugnion has a great article on various methods to accomplish this as well. I particularly like the feature he shares where Blend can create sample data. I’m very hopeful that this functionality is improved and expanded in future versions of Blend.

I hope this post helps out! Also, if I’m doing something that doesn’t make sense or if there is a better way to do something, please let me know.

UPDATE:
Thanks to Brian Genisio for the suggestion to add the GetDataContext method to my Designer class.

posted on Friday, December 05, 2008 1:13:38 PM (Central Standard Time, UTC-06:00)  #    Comments [4]
# Thursday, December 04, 2008

Thought I’d share the below LINQ statement I wrote recently:

var filesToBeMoved =  
    from networkFile in network  
    join localFile in local  
        on networkFile.Name equals localFile.Name into localToNetwork  
    from localMatchesNetwork in localToNetwork.DefaultIfEmpty()  
    // Handle files that are on the network but don't exist locally  
    where localMatchesNetwork == null  
          // Handle files that are newer on the network that they are locally  
          || (localMatchesNetwork.LastWriteTime < networkFile.LastWriteTime)  
    select networkFile;  
  
foreach (var file in filesToBeMoved)  
    file.MoveTo(_directoryProvider.LocalDirectory);

In this case, the files that are being returned are actually IFileProvider instances, which are basically wrappers around the System.IO.File instances for testability.

Oh, and this post is an excuse to see if I set SyntaxHighlighter up correctly :-)

posted on Thursday, December 04, 2008 7:55:44 AM (Central Standard Time, UTC-06:00)  #    Comments [0]