WPF is awesome, but it requires the developer to make a pretty big shift in their thinking of UI.  I’ve had a hard time explaining this to people, but last week, I had an opportunity to work through an example with Steve Gentile.  That’s the basis of this walkthrough.

 

The Scenerio

Steve has an ASP.Net website he maintains called ForgottenSkies.com.  One of the pages displays a map from the game with events that were captured from the server.  You can see the ASP.Net version here.  Steve was looking to create a Silverlight version of this page.

The Wrong Mindset

The initial response from most developers would be to put an image on the “form” and then figure out a way to place some composite control or other image that would denote each event’s location.  If they had the inclination they might use the DataContext, but they likely would also iterate each Event in some collection and manually place these controls within some container.  I believe Steve was trying to place them into a really big grid with lots of Rows and Columns to represent the Latitude and Longitude of the map.

The WPF Mindset

Decomposing this scenario is vital to using WPF properly.  When it comes down to it, the map is really just a way to visualize a collection of Events. If we wanted we could easily make this a list, couldn’t we?  So lets start there:

For the purposes of this demo, the Window.DataContext is set to an instance of an AttackService, which looks like the following:

public class AttackService
{
    public ObservableCollection<Attack> Attacks { get; private set; }
    public int MapSize { get; set; }
    public AttackService()
    {
        this.MapSize = 160;
        this.Attacks = new ObservableCollection<Attack>();
        Random random = new Random();
        for(int index =0; index < 10;index++)
        {
            var attack = new Attack
            {
                Description = string.Format("Attack {0}", index),
                Latitude = random.Next(0, MapSize),
                Longitude = random.Next(0, MapSize),
                Type = (AttackType)random.Next(0, 2)
            };
            this.Attacks.Add(attack);
        }
    }
}

Our goal is to display the Attacks collection, so let’s do that:

<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Grid>        
        <ListView ItemsSource="{Binding Attacks}" />
    </Grid>
</Window>

imageWe have a ListView which has it’s ItemsSource bound to our Attacks collection.  Nothing special.  WPF doesn’t know how to display an Attack class so if we would just see a 10 instances of our class name listed.  We’ll get there though.

 

For starters, lets look at these as if they were listed in a table (or GridView). To do this, we’ll tell the ListView to use a style, attacksList.  We’ll place this style definition in our Window’s Resources collection for convenience of our demo.

<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Window.Resources>        
        <Style x:Key="attacksList" TargetType="ListView">
            <Setter Property="View">
                <Setter.Value>
                    <GridView>
                        <GridViewColumn DisplayMemberBinding="{Binding Description}" />
                        <GridViewColumn Header="Latitude" DisplayMemberBinding="{Binding Latitude}" />
                        <GridViewColumn Header="Longitude" DisplayMemberBinding="{Binding Longitude}" />
                    </GridView>
                </Setter.Value>
            </Setter>
        </Style>        
    </Window.Resources>
    
    <Grid>        
        <ListView x:Name="attacksList" ItemsSource="{Binding Attacks}" Style="{StaticResource attacksList}" />
    </Grid>
</Window>

What we’ve done is given ourselves a way to set values or properties on the ListView.  imageFor the sample you see here, we set the type of View for the ListView to be a GridView. 

The Map

The ultimate visualization of this information is to display it contextually in a map.  It’s important to remember that this is still a list, we just want to visualize the list differently.  To do this we need to change our attacksListStyle.

<Style x:Key="attacksList" TargetType="ListView">
    <Setter Property="ItemsPanel">
        <Setter.Value>
            <ItemsPanelTemplate>
                <Canvas>
                    <Canvas.Background>
                        <ImageBrush ImageSource="Images\Map.jpg" />
                    </Canvas.Background>
                </Canvas>
            </ItemsPanelTemplate>
        </Setter.Value>
    </Setter>
    
    <Setter Property="ItemContainerStyle" Value="{StaticResource attackContainerStyle}" />
</Style>

Instead of setting the View of our ListView, we are now setting the ItemsPanel to a Canvas.  This tells the ListView to place all of the items its charged with listing into the Canvas.  We have chosen canvas, because we will want to place each item via coordinates (X/Y, Left/Type) rather than stacking, row/column, etc.  The background of our Canvas is going to be a JPG version of our map.  Backgrounds and Foregrounds are always brushes, so we are using an ImageBrush to draw our map on the Canvas background.

The second property we are setting is the ItemContainerStyle to the attackContainerStyle.  The ListView places each item into a container rather than displaying it directly.  In order to place it correctly, we need to set the Top and Left properties of this ItemContainer.

<Style x:Key="attackContainerStyle">
    <Setter Property="Canvas.Top" Value="{Binding Latitude}" />
    <Setter Property="Canvas.Left" Value="{Binding Longitude}" />
</Style>

This binds the Canvas.Top and Canvas.Left DependencyProperties to the Attack.Latitude and Attack.Longitude properties respectively.  To bring this together, we have our ListView bound to a collection of Attacks and the ItemContainer contains each Attack and has its DataContext set to that Attack it is meant to contain.

At this point we have most of what we want.  imageEach little black image you see below represents an attack.  This is done by setting the DataTemplate for the Attack type.

<DataTemplate DataType="{x:Type local:Attack}">
    <Image Source="Images\AlliedTerritory.gif" />
</DataTemplate>

The problem you will find is that if you allow the Window to be scaled beyond the size of the map size as it existed when creating the Attack Latitude and Longitude, the points on the map will not scale or move with the map.  I dealt with this by implementing an IMultiValueConverter.  I won’t go into it here as it doesn’t pertain to our Mindset discussion, but I’ve included it in the attacked source code.

Summary

If you come into WPF trying to create cool graphics or visualizations from the outset, you will miss the power and productivity of the platform.  WPF and the oft-sited Designer/Developer scenario actually thrive when you begin to simplify your application into the basics and then apply visualizations.

Get the source for this project here:  Source Code.  The Xaml for this is literally only 67 lines with spaces.  There is 1 line of custom code in code behind, and you saw the AttackService above.  It’s dead simple.

with no comments
Filed under:

I just found the reason why I’m going to slap down almost $200 bucks for VMWare Workstation over Virtual PC: Unity.  I am using a coworkers VM to help on a project he’s been working on, but he uses VMWare and I use Virtual PC.  Instead of buy a license I’m using VMWare Player.  Well I found option under VMWare called Unity so of course I clicked it.   Well it’s possibly the coolest thing I’ve seen ever. 

Here is my desktop with VMWare running as normal:

VMWare Normal

 

and here it is with Unity:

image

All of the windows/applications that were active inside the VM are now native windows in my host.  Also, when you go down to the start button, a second Start Button with the name of the VM becomes visible that allows you to start other apps in this same mode.  I don’t care what you say, that’s just awesome.

So everyone is hating on the new Gates/Seinfeld commercial (you can see it on Windows.com).  Maybe I like Seinfeld humor too much, but I think it's hilarious.  It doesn't inundate me with Windows or Vista glare, it's not over the top, it's just funny.  I mean, Bill Gates just wiggled his rear end on national television!

I guess I'm just easy to please.

One of the things we are using here at SDS for our TFS installation and projects is the Scrum for Team System which provides a new Sharepoint Portal layout, Reporting Services reports and graphs, Work Item Templates, and an awesome Process Guidance reference

In this screencast, I try to point out some of these features and how to get to them.  It's short (just over 2 minutes) and I'll dive into each as we continue our storyline.

Shoutout to Camtasia which is sooo simple to use.

with no comments
Filed under:

One of the projects I'm working on for my company, Strategic Data Systems, is our internal Team Foundation Server 2008 solution.  I'm working with some of the guys who head up our Agile Development Center to make sure things fit well with what they are doing.  It's been difficult to find overlapping free time, so I have started putting together screencasts to highlight our procedures and what I consider best-practices.  We've published written documentation internally, but these are so much more palatable.

These are geared toward our organization in content, but should be generally relevant to anyone interested in TFS.  This particular screencast walks through creating a Team Project and specifying permissions for implementing Scrum roles.

 Direct Link

p.s This is hosted, for free (as in beer), by Silverlight Streaming Services.  It took all of 20 seconds to sign up and 5 minutes to upload the video made with Camtasia.

with 1 comment(s)
Filed under: ,

People give Microsoft Outlook a lot of crap, but if you're willing to think outside the box, you'll realize they did all the little things that make life easy.  For instance, I rarely use the calendar popup for creating new appointments.  No, if I have a meeting next Wednesday, I type "next wed" and hit tab.  It's at 1pm, well, type 1 and hit tab.

Done.

New Appt. Screenshot

with 2 comment(s)
Filed under:

Someone was looking to do quick-and-dirty validation of an Xml document inside a SQL Server procedure today.  I assumed, and regretted, that he meant 2005, which would have looked like this:

declare @xml1 xml 
declare @xml2 xml 
set @xml1 = '<Node1><Node2 attrib="This is it." /></Node1>'
set @xml2 = '<Node1><Node2 /></Node1>'
select Col.value('count(./@attrib)', 'int') as count
from @xml1.nodes('Node1/Node2') as Tbl(Col)

select Col.value('count(./@attrib)', 'int') as count
from @xml2.nodes('Node1/Node2') as Tbl(Col)

After being told, "that blows up", I jogged the memory a bit and came up with this mess:

/* THE STUPID WAY */
DECLARE @hdoc int
DECLARE @doc1 varchar(MAX)
DECLARE @doc2 varchar(MAX)
set @doc1 = '<Node1><Node2 attrib="This is it." /></Node1>'
set @doc2 = '<Node1><Node2 /></Node1>'
/* DOC 1 */
EXEC sp_xml_preparedocument @hdoc OUTPUT, @doc1

IF EXISTS( SELECT    *
FROM       OPENXML (@hdoc, '/Node1/Node2/@attrib',1)
            WITH (attrib  varchar(20)))
BEGIN
PRINT 'Dumb ass'
END
exec sp_xml_removedocument @hdoc

/* DOC 2 */
EXEC sp_xml_preparedocument @hdoc OUTPUT, @doc2

IF EXISTS( SELECT    *
FROM       OPENXML (@hdoc, '/Node1/Node2/@attrib',1)
            WITH (attrib  varchar(20)))
BEGIN
PRINT 'Dumb ass'
END
exec sp_xml_removedocument @hdoc

 

Moral of the store?  UPGRADE!

with 1 comment(s)
Filed under:

This evening I completed my first split-server (or dual server as it's called in the guide) installation of Team Foundation Server 2008.  I've installed TFS a few times now in single-server mode which is pretty crazy easy when you consider what you get (way more than SVN or CVS by themselves).  Throughout the entire process I actually found myself RTFM step -by-step.  For all the grief that Microsoft receives, you have to give them a ton of credit for their manuals, guides, and walk-throughs.

Today I blew up a server.  Couldn't figure something out so I pushed every button I could find, flipped every switch and changed every setting.  Nothing.  So you know what I did, I deleted it, copied over a new Sysprepped Hard Drive and had a clean slate in about 5 minutes.

I figured out my problem, by the way.

with no comments
Filed under:

Ian Griffiths posted a great example of how powerful and cool LINQ is when used in everyday code (it's not all about databases people).

If you haven't started to learn how to incorporate this awesome toolset into your daily coding life, you're killing yourself.  No excuses.

with 2 comment(s)
Filed under:

I've been a faithful unit tester for a few years now.  I may not do everything by the book (I think end-to-end unit tests are helpful), but I do get good coverage most of the time.  That said, I've found myself unable to use any of the Mock frameworks out there, because I don't use your typical Dependency Injection pattern.  That is, I don't like "building up" very freaking instance with all the "Provider" or "Service" interfaces I'm might need in the possible life of a business object.  Yes, if your Customer class is only going to create or save an Order, it feels OK, but my objects are busy dude, so I'd need the longest constructor of all time.

I prefer Dependency Resolution.  I don't use any fancy framework, I just use a good old, DI.Resolve<IBusyBee>() and go about my business.  It works wonderfully, it's light-weight (cause I don't use configuration based DI frameworks), and it's my baby.

That said, it's also been the roadblock to my mocking foray.  That was, until I "got it" today.  Long story short, here's how I roll:

Create a Mock DI Container...

Mock<IDIContainer> mockContainer = new Mock<IDIContainer>();

Create the Injected Mock instances...

Mock<INotificationManager> mockNotifMgr = newMock<INotificationManager>();
Mock<IRepository> mockRepository = newMock<IRepository>();

Tell the mock IDIContainer to return the mock instances when asked...

mockContainer.Expect(c => c.Resolve<INotificationManager>(null)).Returns(mockNotifMgr.Object);
mockContainer.Expect(c => c.Resolve<IRepository>(null)).Returns(mockRepository.Object);

Mock your heart out...

mockNotifMgr.Expect(mgr => mgr.NotifyEmailConfirmation(It.IsAny<Member>())).AtMostOnce();
Member.Register("username", "firstname", "lastname", "ryan@myus.com");

mockContainer.VerifyAll();
mockNotifMgr.VerifyAll();

I'm very happy to have finally jumped on the Moq bandwagon as it will certainly make some unit tests much easier to write.  Maybe I'll even do the test first part more faithfully now. 

FYI, I use my own DI framework which is just a glorified HashTable.  It works for me and it is quick.  Moq has also become my Mock framework of choice for no good reason other than I downloaded it first.

with 14 comment(s)
Filed under:

My team uses ooVoo for video conferencing our Daily Scrum.  It's been great and very reliable.  My only complaint is a lack of whiteboard or desktop sharing, but we've overcome these obstacles with other tools (see SharedView).  Over the months, I've come to acquire an expectation of what the experience should be like and, from that, a Code of Conduct.  Here it is:

Don't Be a Slob - Just cause you're in your bedroom or PJ's doesn't mean I want to know about it.  Put a decent shirt on and brush your hair.  Same goes for yawning, coughing, and every other table manner.  Cover your mouth, mute the Mic, whatever.

Have a Headset - I'm sure some guy out there is ecstatic about the next step in the evolution of the speaker phone, but they still suck in comparison to a headset and Mic that are placed against their corresponding body part.  You're laptop's built in speaker and Mic are no better, so fork out the 10 bucks and get a cheap headset you cheap-***.

Go Full or Go Home - I'm glad your torrents are racing, but your video looks like the corner of your head just entered the Atari zone.  Stop downloading the latest SUSE iso for a few minutes and give me your full bandwidth attention.

I do a lot of demos and Virtual PC 2007 is a mainstay in my arsenal for those demos.  I've used VMWare Server (the free one) and it is very nice, but I run an x64 OS and VMWare had neglected to sign certain emulation drives which caused me enough headache that I ditched it for the easy of VPC. 

I mentioned using Syspreping for my VPC library prior which saves me a ton of time, but one of the things I've always started but never finished was setting up a Virtual Domain.  Well this weekend, I finished things up and I'm happy to say, it wasn't that bad. 

Here's what I did:

Create My Domain Controller Machine by copying a Syspreped Window 2008 Server harddrive image and creating a new Virtual PC using an existing hard drive.  About 120 seconds later I have a free standing vanilla server ready to roll.

imageConfigure Network Adapter(s) by specifying Local Only in the VPC's Network Settings. 

At this point you'll want to log into VPC if you haven't already.  We'll want to isolate our domain and let each of the workstation VPC's communicate with the domain controller by going into the Network Adapter's properties.  Our little domain network is going to be rather isolated.  To accomplish this, we will specify a specific Subnet and IP address range.  Here is what I've used for mine:

IP Range: 192.168.8.1 - 254 (where 192.168.8.1 is my domain controller IP)
Subnet Mask: 255.255.248.0
Gateway: 192.168.8.1 (DC/DNS server)
Primary DNS: 192.168.8.1 (DC/DNS server)

image Setting up Active Directory is a breeze if you do it the easy way.  Of course, I did it the easy way the last time.  (Note to self: when just learning, take the defaults).  Windows Server 2003 and 2008 have this concept of Roles.  A server can fill one or more roles which are the conglomeration of settings, services, etc to do something more abstract... like be a DC.  We are going to add the role Active Directory Domain Services.  

After the Add Role wizard does it's thing, you actually "promote" the machine to a DC by running dcpromo.exe (Start, dcpromo, Enter).  This is where you make your selections, which in this case, I've chosen:

Create a new domain in a new forest
FQDN: vpc.com

You'll want to let the machine also be a DNS server.  This is where I screwed up the first time.  Don't get scared here, with our networking settings this domain we're setting up won't touch your corporate domain or anything crazy like that.

Let the Wizard do it's thing and reboot when it is complete.

Your Active Directory Domain Controller is ready to roll.  Great job.

Adding Workstations is a matter of adding a Computer entry into the Active Directory Users and Computers console and then actually adding the computer to the domain.  You'll find the AD Users and Computers MMC console in Administrative Tools.  Once you've added a computer entry, log into another VPC instance which has the same Network Adapter settings as above (different IP of course .2, .3, etc) and add the machine to the domain (vpc.com) in my case. 

imageHere's a quick screen capture of my Network Adapter on the Workstation I added to the domain.

It's great being able to demo Enterprise software this way or test things like integrated authentication for intranet applications.

with no comments
Filed under: ,

If you are running a VPC instance and you'd like to take a screenshot of something on the VPC, did you know you can do that without any photo editing hassle?

Simply make sure you aren't "in" the VPC (hit the right Alt key if you are).  Now click and drag a square around the portion of the VM you want to capture.  CTRL+C or Edit -> Copy will capture the section to the clipboard and you can paste it wherever. 

Nice touch.

with no comments
Filed under:

http://dnrtv.com/default.aspx?showID=115

Just awesome!  I didn't see anything far fetched other than they must have a great designer on staff.  I wonder if the designer was doing the Blend work?

with no comments
Filed under: ,

I don't often have the need to implement the Visitor Pattern, but today I was that day.  I looked around really quick for an example of how to do this with Lambda Expressions and Anonymous Methods, which seemed like they were the way to go.  It may be that my search skills have deteriorated right along with my sense of style, but I didn't find much.

I played around for a few minutes and here is what I came up with:

public abstract class CarBase
{
    public void Visit(Action<CarBase> action)
    {
        if (action != null)
            action(this);
    }
}

public class BigCar : CarBase
{
    public void RunOverLittleCar()
    {
        Console.WriteLine("Me smash little car!");
    }
}

public class LittleCar : CarBase
{
    public virtual void RunAwayFromBigCar()
    {
        Console.WriteLine("Go Faster!");
    }
}

public class EcoCar : LittleCar
{
    public override void RunAwayFromBigCar()
    {
        Console.WriteLine("Ouch.");
    }
}
class Program
{
    static void Main(string[] args)
    {
        IList<CarBase> cars = new List<CarBase>(new CarBase[] {
                                                                new BigCar(), 
                                                                new LittleCar(), 
                                                                new EcoCar() 
                                                              });
        foreach (CarBase car in cars)
        {
            car.Visit(delegate(CarBase c)
            {
                if (c is BigCar)
                    ((BigCar)c).RunOverLittleCar();
                else if (c is LittleCar)
                    ((LittleCar)c).RunAwayFromBigCar();
                else if (c is EcoCar)
                    ((EcoCar)c).RunAwayFromBigCar();
            });
        }

        if (Debugger.IsAttached)
            Console.ReadLine();
    }
}

In many implementations of the visitor pattern there is an adapter or actual Visitor interface and implementation class which is passed into the Visit() method.  This is just smooth.

My visit method above is a little big to look good as a lambda expression, though maybe I just don't have the eye for it. 

with no comments
Filed under:

For those of you who use NHibernate you may find this convenient, if you don't already have your own.  Below is a C# code snippet for creating a public virtual property (code and file are both there).  Just put it in your <Visual Studio 2005/2008>\Code Snippets\Visual C#\My Code Snippets folder and you're off and running.  No restart required.

File

Code

<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets  xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
    <CodeSnippet Format="1.0.0">
        <Header>
            <Title>propv</Title>
            <Shortcut>propv</Shortcut>
            <Description>Code snippet for an automatically implemented virtual property</Description>
            <Author>Microsoft Corporation</Author>
            <SnippetTypes>
                <SnippetType>Expansion</SnippetType>
            </SnippetTypes>
        </Header>
        <Snippet>
            <Declarations>
                <Literal>
                    <ID>type</ID>
                    <ToolTip>Property type</ToolTip>
                    <Default>int</Default>
                </Literal>
                <Literal>
                    <ID>property</ID>
                    <ToolTip>Property name</ToolTip>
                    <Default>MyProperty</Default>
                </Literal>
            </Declarations>
            <Code Language="csharp"><![CDATA[public virtual $type$ $property$ { get; set; }$end$]]>
            </Code>
        </Snippet>
    </CodeSnippet>
</CodeSnippets>
 
 
with no comments
Filed under: ,

So last night I was restructuring my hosting infrastructure (read: moving folders around) and managed to delete the folder that hosts most of my sites.  I got that nasty sinking feeling in the pit of my stomach.  I was able to get things back up, but my hosting provider, which is normally pretty responsive and helpful, took FOREVER to respond to my restore request. 

Immediately after that I set up a scheduled job on my home machine to pull down a rar of the site each night.  It's hard to get good help these days.

http://jing.cromwellhaus.com/2008-07-01_1427.swf

with no comments
Filed under:

Get your head out of the gutter.

It's important to look at your mapping files closely when trying to diagnose unexpected results.  One of our developers had recently added two properties to our big honkin' CustomerOrder entity.  These both happened to be enumeration values, which are represented by Int values in the database.  Of course, NHibernate mapping files (hbm's) are from the POCO perspective, which means the <property type="..." />  value should be the Enumeration's themselves.  If you use Int32, though, things will appear to work, but you're actually causing NHibernate to do an incompatible type comparison during it's "Dirty" checks.  This will cause your lazily, loaded entities to be dirty as soon as you get them.

So, be careful in reviewing your mappings, because it doesn't take much to screw up something small that has a big impact.

with no comments
Filed under: ,

I create a lot of Virtual PC images, be they for demos, testing, or actual work.  If you haven't started using Virtual PC all the time, start.  When you do, start syspreping your machines and you'll save yourself a ton of time and find Virtual PC that much more useful.

Here is a step-by-step guide.  Run, do it now.

with 2 comment(s)
Filed under:

Tonight I presented for the Dayton .Net Developers Group on WPF.  Unlike my previous Lap Around WPF @ CONDG which was meant as a beginners guide to WPF, this time we were skipping the basics and plunging into a framework I've dubbed MiniMVC. 

MiniMVC is, primarily, a set of DependencyProperties and custom ICommand's which allow you to specify a Controller for any FrameworkElement and/or Action in the logical tree.  Unlike Dan Crevier's D-V-VM pattern or Josh Smith's MVC pattern implementations which rely on explicitly defining RoutedCommands for each action, binding them up manually, and other unpleasantries (in my humble opinion - these guys still know more than I) with this framework you can use any old class, with any old method, and start executing actions immediately.  Here's an example:

<Window x:Class="PostDemo.Window1"
      
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      
xmlns:mvc="http://cromwellhaus.com/wpf/minimvc"
      
xmlns:demo="clr-namespace:PostDemo">

    <
mvc:MiniMVC.Controller>
        <
demo:Window1Controller/>
    </
mvc:MiniMVC.Controller>
   
    <
StackPanel>
        <
TextBox x:Name="txtMessage"Text="" />
        <
Button>
            <
mvc:MiniMVC.Action>
                <
mvc:ControllerAction Trigger="Click"Action="Echo"
                      
Return="{BindingElementName=txtResult,Path=Text}">
                    <
mvc:ParameterParameterName="message"
                          
Value="{BindingElementName=txtMessage,Path=Text}" />
                </
mvc:ControllerAction>
            </
mvc:MiniMVC.Action>
          
Write Something
      
</Button>
        <
TextBlock x:Name="txtResult" />
    </
StackPanel>
</
Window>

Here's what's going on:

First, we have this class, Window1Controller, which we are attaching to the Window's MiniMVC.Controller property. 

Second, we are setting the MiniMVC.Action property on the Button to a ControllerAction triggered by the button's Click event.  When Click occurs the Action to be taken on the Controller is Echo.  We want to pass into Echo the value of the txtMessage TextBox Text value as parameter message.  Also, we're specifying that the Return value from Echo should be applied to the Text property of the txtResult TextBox controller.

Cool?  So what's really going on?  Well, MiniMVC is handling the most importantly the OnChange event handler for the Action DependencyProperty and using that to dynamically create an ICommand class called ActionCommand.  It's also looking up the Click RoutedEvent via Reflection and adding the ActionCommand's Execute method as the event handler for the located Click RoutedEvent.  There is ZERO code in my code-behind.  The Designer has free-reign to apply the Controller and action to any RoutedEvent he/she chooses and we can all sleep well knowing our concerns are separated.  A happy marriage in my book.

I must give a lot of credit to Rob Eisenberg's super-awesome Caliburn project on which much of the Action dependency property is based.  His framework is full featured to the tilt, but is a little over done to my liking with the extensive use of Dependency Injection.  If you find MiniMVC useful, though, I highly recommend you watch for progress on Caliburn.

You can download the full solution, including demo's, from the presentation, as well as the above example project here.

with 4 comment(s)
Filed under: , ,

When I'm trying to explain things to people or just want to try something out really quick I'll often create myself a temporary Visual Studio projects that I don't intend to keep around.  In fact, I have an entire Temp folder full of them.  imageI always loved that in the VB 6.0 IDE you could choose not to save your project at all and no remnant would exist if you chose not to save.  Apparently you can do this in Visual Studio 2005 and 2008.   Go into Tools -> Options and select the Projects and Solutions node.  Uncheck Save new projects when created. 

Bingo.

with no comments
Filed under:

I use Virtual PC a lot, especially for development.  I try to emulate a mini-infrastructure of how I'll be deploying my solutions, so no SQL Server on my box, no IIS on my box, etc.  To support this I use Virtual PC Guy's steps for enabling communication between my host and the VPC's.  If you are on an Active Directory environment this can have a pretty negative impact on name resolution, specifically when browsing through "My Network Places" (XP) or just "Network" (Vista).  imageIf you are running into this and it bugs you, go into your Microsoft Loopback Adapter properties and disable/uncheck "Client for Microsoft Networks".  I personally disable everything except Virtual Machine Network Services and IPv4 since this just a small private network running on my computer.

with no comments
Filed under: ,

I realize this isn't the MiniMVC post I promised, but that one is a monster and I wanted to feel like I accomplished something this evening.

imageLast week I was forced to replace a dying video card which was a piece-of-junk when I bought it, but, well, I'm cheap.  I picked up an NVIDIA GeForce 8600 GT and while not the best, it's more than I'll need. 

When I built this rig, I picked up about the best available at the time.  Looking at my latest Windows Experience Score, I'm sort of regretting not picking up the Intel 6800 Core 2 Duo, though it was significantly more expensive than the 6600 I  did choose.  I guess I can't fault the decision based on the facts at the time.  That said, my Dell M1530 has the 6800 and I swear it's a friggin' beast.

What's your score?

with no comments
Filed under: ,

I'm so behind on IIS 7 it makes me sad.  I love HttpModules and HttpHandlers in ASP.Net (Speedy Rewards transaction processing is based on one I wrote), but this just takes the cake.

Up Next: MiniMVC

with no comments
Filed under:

It has been quite a New Year so far.  As of today, Monday January 14th 2008, I have left Speedway and the Speedy Rewards™ team and found new employment with SDS Consulting and I have new eyes courtesy of Lasik Plus of Dayton.  I'd say that's a fairly ambitious first two weeks.

I'm still working on my side project, hoping to have it completed in the next few weeks or so.  I lost focus with all the holiday excitement, but I've picked back up again. 

I'll also be giving another WPF presentation for the Dayton .Net Developers Group.  This one will be more in-depth than my CONDG presentation which focused on some of the basics of templates, styles, and binding.  One of the big spots in this new version of the presentation will be implementing the MVC pattern within WPF.  Very cool.

with no comments
Filed under: , , ,

In my quest to get my wpfstyle.com site written in the new ASP.Net MVC framework (day 3) I've run across a little issue that I'm sure will come up again.

In my world, a checkbox always seemed to imply true/false or yes/no.  In reality, it can mean a lot of things in an Html Form.  It's an input, remember, and inputs have a value.  When your checkbox is checked, that value is posted back. 

Making it work as a boolean indicator in your MVC application, is possible though.  In keeping with the Membership/Authorization theme from yesterday, I have the following controller action:

public void Authenticate(string userName, string password, bool? rememberMe)
[Hint: Notice the '?' after bool for the third parameter.  That'll be important in a moment.]
Here is the corresponding Login.aspx View which contains a form posting to this action:
<%using (Html.Form("Authenticate", "Account"))
  { %>
    <div style="margin: auto auto 4px auto">Username 
        <%=Html.TextBox( "username") %> </div>
    <div style="margin: auto auto 4px auto">Password &nbsp;
        <%=Html.Password( "password") %></div>
            
    <div style=&qu