What is Interknowlogy Bloggers?

InterKnowlogy Bloggers was created to facilitate the connection of bloggers interested in InterKnowlogy and the technologies embedded within the cutting and bleeding edge projects we do. We believe this is a cool place to connect bloggers interested in what we are up to (within the hard limits of Non Disclosure Agreements) and our views on the changing face of the technology world.

But, you’ll find more than just Everett, Whidbey and Longhorn (and technology in general for that matter) within this site. Within these pages you’ll also find out how some of the most relevant players in the Microsoft Technology space bring balance to their lives.

Contact InterKnowlogy



Syndication

Blog Stats

Bloggers (posts, last update)

Powered by:

Copyright © InterKnowlogy, LLC

Latest Posts

My blog has moved

The new location is http://team.interknowlogy.com/blogs/bradcunningham/ 

 

Update your bookmarks and feed readers.

posted @ 10/22/2008 9:11 AM by Brad Cunningham

My Blog has Moved

The InterKnowlogy copy of Bill Sheldon's blog has moved. The past posts have been maintained for historical and linking purposes please join us at the new Team InterKnowlogy blog site.

My New Blog address is:   http://team.interknowlogy.com/blogs/BillSheldon

If you are not redirected automatically within a few seconds then please click on the link above.

posted @ 10/6/2008 10:58 PM by Bill Sheldon

New Blog Site

My blog has moved to team.interknowlogy.com/blogs/johnbowen/

Check it out for recent posts!

posted @ 10/1/2008 4:03 PM by John Bowen

My Blog has moved

http://team.interknowlogy.com/blogs/scottlarson/default.aspx

posted @ 8/13/2008 4:46 PM by Scott Larson

Blog Has Moved

My blog has moved to our new blog server http://team.interknowlogy.com/blogs/adamcalderon/default.aspx so please look there from now on for all of my blog posts.

posted @ 8/7/2008 9:10 PM by Adam Calderon

Book Chapter Excerpt

CoDe magazine has an excerpt from Chapter 11 Adding Client Capabilities to Server Controls Using the ASP.NET AJAX Control Toolkit of our book.

posted @ 7/28/2008 5:57 PM by Adam Calderon

Silverlight IE Pains on Windows 2008

So I got an environment up an running to do some work with Silverlight Beta 2 and also SP1 for VS 2008. I decided to do all of this on a VMWare image with Windows 2008. Man was this a headache. The extra super stringent security on Windows 2008 made this an absolute pain. Just so others don’t have to go through the same thing I documented what you have to do to get things to work.

1. Turn off IE Enhanced Security (ESC) for Administrators (this assumes your are developing as an admin). This will enable you to open websites without getting asked if it’s ok. To do this go to Administrative Tools and open Server Manager. Click the Configure IE ESC link as shown below in red. This opens the dialog that allows you to turn off ESC for administrators and for users. I just turned it off for administrators on my box since that is what I am developing as.

ServerManagerIEESCsetting

2. Now that you have that done run you application in debug mode (which won’t show the Silverlight control yet) and add “http://localhost” to your trusted sites. I did this so that all of the other websites I hit will still have the standard “bullet proof” security. To get to the security dialog shown double click the Internet icon. Then select the trusted sites icon and finally add “http://localhost” to the trusted sites.

IESettings2008Silverlight

Once I did this I was finally able to rock and roll with Silverlight. If I remember right you will get a little warning just below the toolbar that ESC is disabled. If you select it you can turn this warning off.

I hope this helps.

posted @ 7/12/2008 12:20 PM by Adam Calderon

Book Sales on Amazon

The book Joel Rumerman and I wrote

BookCoverImage Blog

Advanced ASP.NET AJAX Server Controls For .NET Framework 3.5

seems to be doing quite well wth only 4 days being on sale. Joel sent me an email earlier today with links to the latest statistics. I was quite suprised. Thanks to everyone!

Top AJAX Best Sellers

Top ASP.NET Best Sellers

posted @ 7/9/2008 3:18 PM by Adam Calderon

So Cal Code Camp Slides and Code

Thanks to everyone who attended my sessions at code camp last weekend. Once again Woody and company did a great job.

 

Overview of the Composite Application Guidance for WPF

Composite Application Guidance for WPF

 

Building Control Extenders using the Ajax Control Toolkit

posted @ 6/30/2008 5:39 PM by Adam Calderon

San Diego Code Camp 2008 Resources

Thanks to everyone who attended my sessions!

Application Layout in XAML:

Handout  | Code

Also look at this previous post for more on sharing sizing between Grids.

We didn't get to cover the FrameworkElement layout properties so check out the second application in the sample code to get a feel for how they work.

Building Controls for WPF:

Slides | Code

You can also download the full class library reference poster here.

WPF Data Binding:

Slides | Code

Also look at my other blog posts for more examples and explanations.

Creating Responsive Desktop Apps:

Code

 

posted @ 6/29/2008 2:45 PM by John Bowen

Speaking at San Diego Code Camp

I will be presenting on two very different topics this year at the SoCal Code Camp in San Diego that reflect much of what I have been doing over the last 6 months or so. My first session Building Control Extenders using the Ajax Control Toolkit stems from the work I have been doing on my book and will be a fairly comprehensive look at creating controls using the Ajax Control Toolkit. My second session Overview of the Composite Application Guidance for WPF covers the work I have been doing with the Patterns and Practices Group on building composite applications in WPF.

posted @ 6/23/2008 5:09 PM by Adam Calderon

ASP.NET AJAX Controls Book Done!

I thought this day would never come. Joel Rumerman and I have finally completed our book Advanced ASP.NET AJAX Server Controls For .NET Framework 3.5 that hits the book shelves the first part of next month. This has been a exciting experience for the both of us and we hope you enjoy reading it as much as we did writing it.

posted @ 6/23/2008 4:54 PM by Adam Calderon

Getting to Know Your Resource Tree

The XAML Resources in WPF and Silverlight can be a powerful tool but are often misunderstood and can cause lots of problems if not managed properly. The first point of confusion with Resources is that the term "resources" already has so many other meanings, including:

  • Project items compiled as Resource
  • Linked and embedded resources (resx files)
  • Hardware resources, and specifically graphics in WPF

So first to clarify what we're talking about here: XAML Resources are any .NET object that is declared in a ResourceDictionary. This is generally done in XAML but objects can also be added to a ResourceDictionary in code. ResourceDictionaries can be found on any FrameworkElement derived object (and also on Application) in the form of the Resources DependencyProperty.

Resources are typically accessed with the StaticResource or DynamicResource MarkupExtensions in XAML. I won't get too much into the details of these except for a few key points. DynamicResource will update if the referenced Resource changes which can be useful but generally just causes extra overhead that can create performance and memory problems. StaticResource requires that the referenced Resource exist in the resource tree at load time. More on that later. StaticResource can cause compile-time errors for missing Resources while Dynamic will just use a default value until the Resource becomes available. StaticResource should always be your default choice unless you have a specific need for the behavior of Dynamic (Blend always uses Dynamic so be prepared to make lots of switches in what it generates).

Next, what is the Resource tree? WPF UI is inherently hierarchical. Each UI is made of a logical tree that is then used to render a visual tree. This means that each element in your UI has a clear parent structure with a single path up the hierarchy to the root Window element (or NavigationWindow, Page…) and then an Application object at the very top. The Resources property of each parent element is made available to every child element so that elements can access any Resource that is declared anywhere in its parent hierarchy. This makes it possible to share Resources between elements in specific areas while not requiring the memory and performance penalty of declaring them application-wide.

To get the maximum reuse benefits while not overly impacting performance, resources need to be carefully managed and organized. In addition to resources from the parent hierarchy, the MergedDictionary feature allows you to extract any Resource to a separate ResourceDictionary file that can then be imported to specific elements that need it. This can allow you to share XAML between elements at a lower level but it can also cause situations where multiple instances of a ResourceDictionary are created by elements under a common parent, consuming more memory and initialization time than if the ResourceDictionary were merged once into the parent.

<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Resources/Brushes.xaml"/>
<ResourceDictionary Source="/MyCompany.MyApplication;component/Resources/Styles.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>

Once you've created and structured your Resources you can get to the important part: actually using them. The most compelling reason to use a Resource is reuse but even in cases where a resource is used once they can still provide value by simplifying your XAML's structure. Declaring things like templates and brushes as resources rather than inline can turn a deep hierarchy into a single line of XAML and can also introduce a descriptive name for a sub-section of XAML, making it more readable (it's no coincidence that this sounds like refactoring methods). There are also cases (ItemsControl ItemTemplates in particular) where declaring things in-line can actually break them but simply moving them to resources will fix the problem.

The primary method of accessing a Resource is by Key. Keys are specified by the x:Key attribute on the element that is declared as a Resource. Keys are a required attribute for most types of resources and will cause compiler errors if missing. Static and DynamicResource references rely on Keys to find resources.

The other method of accessing resources instead relies on a type that is associated with a Style (TargetType) or DataTemplate (DataType). When no x:Key is specified on one of these types they are assigned an implicit key that will cause them to be applied to any object of the specified type in whose Resource tree they exist. This can be very powerful but also cause problems that are very hard to locate. For example, if someone creates a Style with TargetType of Button that sets Width to 100 and puts it in App.xaml, suddenly all Buttons application-wide will be fixed at 100 unless they have some other explicit setting for Width. Now someone trying to figure out why their Button text is getting cropped needs to figure out where that fixed width is coming from but gets no clues from the settings on the Button itself. It's pretty easy to go check Window.Resources or App.xaml but now imagine the Style is located in one of 10 ResourceDictionary files that are merged into App.xaml. Implicit key resources should be used very carefully and be declared only in well known locations to avoid this sort of problem.

The first thing you should do when tracking down an issue with a named (explicit Key) Resource is to make sure the reference is using StaticResource rather than DynamicResource. This can often turn a mysterious run-time behavior into a compiler error, or in some cases a run-time exception, telling you immediately that the Resource doesn't exist in the current Resource tree. If this happens it can most often be fixed simply by merging in a ResourceDictionary or just moving the Resource declaration itself.

If you find yourself getting into problems with name collisions (i.e. 10 different people created "ButtonStyle1" in Blend and spread them all over the app) it can help to actually diagram out the resource tree for the element in question (on paper or in your head) to find out which one is really being used. It starts at the top with App.xaml, then the Window or Page, then local parent controls' resources, then the element itself. Inside each of these sections include any MergedDictionaries and anything in turn merged into those ResourceDictionaries. Once you can see the whole tree, whatever is declared last takes precedence: this goes for inside files as well as down the tree.
Resource Diagram
So if ButtonStyle1 is declared in Common.xaml (A) that is the first file merged into App.xaml but also as the last local Resource in App.xaml (B) and again in CustomStyles.xaml (C) merged into Window1.xaml then A and B are going to be ignored and C will be used. If you then rename C to ButtonStyle2, A will be ignored and B will be used. Using Visual Studio's Find in Files is usually the quickest way to find name collisions or just track down lost resources (use x:Key="MyResourceKey" to find declarations).

posted @ 5/30/2008 11:48 AM by John Bowen

What I am reading

Here is the current line up:

 

Born On A Blue Day: Inside the Extraordinary Mind of an Autistic SavantDesigning InteractionsUniversal Principles of DesignSoftware Creativity 2.0

 

 

Born on A Blue Day : Inside the Extraordinary Mind of an Autistic Savant -I am only a 1/4 of the way into to this book but I am fascinated by it. I actually find myself comparing some of the author's autistic traits to my own behaviors and trying to figure out why I think the way I do. It is a very interesting exploration in the way the mind works and how people think and react. Very Highly recommended.

 

Designing Interactions - This is a monster of a read. 700 plus pages. It has been a long but interesting read. I am just about finished with it and I have really enjoyed the read. It can be read in chunks which is nice due to it's size. Short interviews with influential designers. This gives a nice way to see what a designer thinks about when creating a new product or interaction. It has given me good ideas to consider when building user interfaces.

 

Universal Principles of Design - Short sweet and to the point. I really like this book as a reference guide. Some of the principles are obvious but others aren't quite so easy to see. The book takes a design principle and devotes 2 pages to it. A short summary of the principle, a reason why you would use the principle, and a real world example of where to apply it. Then on the other page a visual representation of the principle and an explanation of why the visual represents the principle. This is a highly recommend reference book. Anyone designing user interfaces or user interactions should read this IMO.

 

Software Creativity 2.0 - This has a been a slow read for me. I haven't read much of it so I don't have much to say on it yet. I have liked what I read but it obviously wasn't as engaging as the other books because it is the last one of the set I pickup to read. Once I catch up on it more I will update my review.

 

 

I had this idea for a book review "corner" the other day so this is my first stab at it. I will be adding a new post every once in a while when I have a new set of books to read. Tell me what you think.

posted @ 5/23/2008 10:54 AM by Brad Cunningham

Silverlight 2 and DHTML

The purpose of Silverlight 2 in demo applications has so far primarily been to provide enhanced graphics to self contained applications. While the graphics capabilities are attention-grabbing, some of the other powerful features that are available seem to get overlooked. For example, Silverlight has the ability to interact with the HTML DOM and Javascript which allows you to use it to enhance existing web applications. To try out some of these features, I took a basic data entry form (in this case just plain HTML that's not actually hooked up to anything on the server) and added a toolbar that gives the user some editing features to help fill out the form.

Toolbar

The toolbar provides

  • Unlimited Undo/Redo
  • Clearing of all form data
  • Saving multiple sets of the entire contents of the form locally on the client
  • Reloading of any set of data that is saved on the client

 

The only javascript that is required for this functionality is some boilerplate to connect to the Silverlight C# code.

For the toolbar I used the DHTML-Silverlight connections in both directions. The DataCache class in the application is decorated with the ScriptableType attribute and has methods decorated with the ScriptableMember attribute. This is the first step in making code available to javascript. The next is to call HtmlPage.RegisterScriptableObject("objectName", theScriptableObjectInstance) from the Silverlight UserControl's code-behind. A good place to do this is in a handler for the Loaded event. These methods are now available to call from javascript by getting a reference to the Silverlight application like this:

var agEControl = document.getElementById("SilverlightElementId");
var content = agEControl.content;
var scriptableObject = content.objectName;

Here objectName is the string used above to register the object and "SilverlightElementId" is the HTML id of your Silverlight control ("Xaml1" by default in a VS generated project). Once you have scriptableObject you can just call any method on it just as you would in C#.

In the scriptable methods I use the connection in the other direction to go back to the calling HTML and retrieve values from the page's controls. This basically takes one step to get the current value of an element:

HtmlElement element = HtmlPage.Document.GetElementById("controlId");
string value = element.GetAttribute("value");

It looks just like what you would do in javascript with the exception of the HtmlElement and HtmlPage classes that provide the access to the DOM. HtmlElement allows you to do all sorts of manipulation including attaching event handlers and playing with the structure of elements on the page.

Another interesting thing I ran into when I decided to blog this is the simplicity of deployment with the current structure of a Silverlight application. If you're working in Visual Studio your application is compiled into a single file with a .xap extension. You probably also have a web project of some type to host the application. When running your application the built-in web server is spun up to serve up the page to the browser.

If you happen to be using a plain HTML host and not using server-side code you can also open the .htm directly in your browser as a file. This gave me the idea to try xcopy deploying my app to my blog's downloads folder, which is just a basic file share. Starting out with a minimum set of files I copied the .htm and .js files that make up my page (no generated files) and the .xap file in ClientBin. This didn't work at first due I think to extension filtering that disallowed the browser from pulling down the xap file. Fortunately zip files are allowed to download and (big secret) xap files are actually just zip files containing your assemblies and a manifest. If you rename your xap to zip you can just open it up and see your dlls inside. Once I did this and adjusted the reference in the HTML accordingly the entire page with toolbar loaded in my browser over http from a simple file share! Compare this to what you need to stand up a simple AJAX application and you can see the advantage.

Download the sample code HERE. Try out the functional page HERE. You'll need the Silverlight 2 Beta 1 runtime (it should ask to install itself). Sets of data are saved by Last Name and ID so you may notice the Save button being enabled/disabled as you change fields. The Load and Delete buttons will become enabled after you save a form. The set selector is kind of clunky because there's no ComboBox control yet in Beta 1 so I just squeezed in a small ListBox instead.


**UPDATE** - Silverlight 2 Beta 2 was just released and I've updated the functional version and put it alongside the original HERE. **

posted @ 5/22/2008 10:15 PM by John Bowen

Photo Stackr (Silverlight goodness)

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 it 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" Foreground="#FF686868"  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 in 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.

posted @ 5/12/2008 8:34 PM by Brad Cunningham

Debugging Blend Errors

Blend has been getting more stable with frequent releases including SP1, Blend 2 etc but it still can't render everything, even from an application that runs flawlessly at runtime. There are lots of things that can break the Blend renderer but tracking down exactly what broke your window/page/control can be difficult and time consuming. In some cases the location can be found by taking advantage of how Blend hosts applications. When Blend renders XAML it's running the code just like at runtime and the code can be debugged in the same way. In cases where non-XAML Exceptions are breaking the renderer Visual Studio can attach to Blend itself and break to the exact location that's causing the problem.

The primary reason errors occur in Blend that don't show up at runtime is that Blend acts as a host for the application. This causes things that are evaluated relative to the running application like config files and certain types of relative resource references to look in the wrong place. The pack:application syntax in particular causes invalid references. The ResourceDictionary hierarchy is also different when running in Blend. In versions prior to Blend 2 Feb Beta App.xaml resources aren't automatically resolved using StaticResource the way they are at compile time. Even the newest versions run into problems resolving references inside things like UserControls when rendered as part of a Window. XAML errors generally show up in the Blend errors window and can be linked to a specific line (with varying accuracy depending on the version) while errors deeper in code need Visual Studio debugging.

Blend XAML Error

To debug an application inside Blend open the project in both Visual Studio and Blend at the same time. Before opening the broken component in Blend attach Visual Studio to the process with Debug->Attach To Process and select Blend.exe from the list. To make sure the Exception isn't just swallowed by Blend set Visual Studio to break on all CLR Exceptions by selecting Thrown in the Debug->Exceptions for Common Language Runtime Exceptions.

Exception Options

Once you've tracked down an Exception in code you have a few choices. You can fix the error if it's something that you determine shouldn't be happening. If it's due solely to the peculiarities of Blend and you want to leave the code as is, except when running in Blend, WPF provides a way to check whether Blend (or some other designer) is hosting the code. DesignerProperties.IsInDesignMode is set to True by Blend and can be accessed from anywhere in a WPF application with

(bool)DependencyPropertyDescriptor.FromProperty(DesignerProperties.IsInDesignModeProperty, typeof(DependencyObject)).Metadata.DefaultValue

Any code that breaks Blend can just be executed conditionally when this value is false.

One of the key advantages of using WPF is the promise of direct collaboration between designer and developer. Fixing Blend rendering errors will enable design and development of your application simultaneously without worrying about keeping application code and static designs from separate teams in sync.

posted @ 5/11/2008 5:13 PM by John Bowen

WPFPerf and software rendering

The WPFPerf tool that is included with the windows SDK can be a very useful tool in finding areas of your application that is being rendered using the WPF software pipeline.

Recently I was profiling an application looking for areas that could be improved, performance wise, at the WPF level. One thing I thought to do was use the WPFPerf tool and look for elements that were being software rendered and see if I could modify them to use the hardware pipeline and still get desired effect. See here for more information on the two pipelines.

To find the areas that are using software rendering the Perfortator plug-in gives a nice, albeit cheesy, visual cue. By enabling "Draw software rendering with purple tint"

 

Purple

 

Come on guys, really? Is that really what the option is called? I wonder what the property is called in code ShowSoftwareRenderingUsingPurpleShadeBecauseMyKidWasWatchingBarneyWhileIWasWritingThisFuction.

But I digress, The functionality works well.

 

 FullApp

So a discovery I made was that WPF is able to use the hardware rendering pipeline to render bitmap drop shadows (which is typically documented as being software rendered) but only if the drop shadow is rectangular. In my case I had a button template that was using a border element ad applying a drop shadow to the border element to give the drop shadow effect on the button

 

SoftwareRender

<Style x:Key="SoftwareRenderTemplate">
            <Setter Property="Control.Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Button}">
                        <Grid Height="22">
                            <Border Background="Gray" Height="22" Margin="0,0,0,0">
                                <Border.BitmapEffect>
                                    <DropShadowBitmapEffect Opacity="0.5" ShadowDepth="3" Softness="0.285"/>
                                </Border.BitmapEffect>
                                <ContentPresenter x:Name="ButtonContent" Width="Auto" Content="{TemplateBinding Content}" OpacityMask="{TemplateBinding Foreground}" HorizontalAlignment="Center" VerticalAlignment="Center" Height="Auto" Margin="10,0,10,0"/>
                            </Border>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

 

When I built the template this way and ran Perforator it showed me that the button was using software rendering. Which is what I would have expected. However, if I modify the template to use a rectangle shape instead of a border element. Then apply the drop shadow effect to the the rectangle I noticed that Perforator no longer indicated (which means to remove the lovely purple tint) that the button was using software rendering. This is not what I would have expected.

 

<Style x:Key="HardwareRenderTemplate">
            <Setter Property="Control.Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Button}">
                        <Grid Height="22">
                            <Rectangle Fill="Gray" Height="22" Margin="0,0,0,0" Stroke="{x:Null}">
                                <Rectangle.BitmapEffect>
                                    <DropShadowBitmapEffect Opacity="0.5" ShadowDepth="3" Softness="0.285"/>
                                </Rectangle.BitmapEffect>
                            </Rectangle>
                            <ContentPresenter x:Name="ButtonContent" Width="Auto" Content="{TemplateBinding Content}" OpacityMask="{TemplateBinding Foreground}" HorizontalAlignment="Center" VerticalAlignment="Center" Height="Auto" Margin="10,0,10,0"/>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

 

HardwareRender

 

I searched around a bit to try and determine what was going on here and the information is sparse (hence my blog entry) But I did find one source that hints to the fact that the underlying implementation of the drop shadow effect is optimized when sticking to rectangular shapes.

So there it is. If you really like drop shadows but don't want to get hammered by the performance this is one way to do it.

posted @ 5/9/2008 2:37 PM by Brad Cunningham

Generic or Specific

This is one of those musing posts and comes from one of the challenges I have when teaching a feature that Microsoft chose to call 'Generics'.  I think this name was picked by someone, who while reasonably familiar with English wasn't a native speaker of the English language.  Thus they found a definition and thought it applied - allow me to elaborate.

What is a .NET Generic - well in short - under the original implementation of .NET collection classes contained a set of other objects.  However, these classes didn't know specifically what kind of object they contained.  Instead a given collection might contain more then one different type of object, for example numbers stored in a collection with strings and image objects.  It wasn't possible to say thata given collection would contain only a specific type of class. 

With the introduction of 'Generics' it was possible to indicate that a given collection would only contain a specific type of object.  That's right the feature Generics describes a set of rules and syntax for ensuring a collection is of a specific type.  Now the challenge comes from how the definition of generic is phrased in some dictionaries: "Relating to or descriptive of an entire group or class"

Notice that the preceding definition basically associates the definition of a generic with a class.  Thus if you were searching the dictionary for a word that described a class - well there you have it.  Unfortunately this use of the word "class" doesn't relate to the use of the word "class" in object oriented programming.  In this use a class is more of a category of like items - not the definition of a single item. 

Webster's Revised Unabridged Dictionary - Cite This Source - Share This

(http://dictionary.reference.com/help/web1913.html)

Generic

Ge*ner"ic\, Generical \Ge*ner"ic*al\, a. [L. genus, generis, race, kind: cf. F. g['e]n['e]rique. See Gender.]

1. (Biol.) Pertaining to a genus or kind; relating to a genus, as distinct from a species, or from another genus; as, a generic description; a generic difference; a generic name.

2. Very comprehensive; pertaining or appropriate to large classes or their characteristics; -- opposed to specific.
Webster's Revised Unabridged Dictionary, © 1996, 1998 MICRA, Inc.

 

That's right the word I most frequently use to describe the feature Generic is the one which defines the opposite of the definition of the word generic....

I don't think Microsoft can really do much about this, it's just one of those things that make you wonder...

posted @ 5/2/2008 11:46 PM by Bill Sheldon

ROSARIO (cont'd) - Manual Test Runner

In last weeks post I talked about the new tool "Camano" to define your test cases and create test suites. After we have our tests loaded into team system , we can now start to actually execute the test. The first thing we will do is open the new tool called the Manual Test Run tool:

MTR

We now can start recording the actual test, in this case we will be testing the Beer House Web site. As we can see we have three recording settings

Action - Records an action log of each action performed on the application under test

Background - Records actions which can later be played back in the application under test

Video - Records video in the WMV format

Recording

We will now run the test. The last step will fail. From here we can capture the screen to show exactly what we see when we executed the test step.

We then create a new bug. We see all the data collected already being pre-populated and placed in the bug report and loaded into Team System.

 

NewBug1

 

NewBug2

Now after the bug is fixed we can re-play the recording to re-test the application. We go back in the Test case and select the steps then select play. The steps that we used to test the web page are now re-executed automatically which is fantastic. Now the last really cool thing is we can go to VS 2008, Create a New Test choose a Coded UI Test. Now we create a BrowserWindow object and use the recording as the source. Then we right click and select Generate code from Existing recording. Now the code is generated and placed right into the test procedure. We now have an automated test that will execute the recording that we have made earlier.

Microsoft has made some great strides in assisting us on being able to execute our manual tests being able to convert these test to automated test. These tools will help us being able to create and execute these test in a timely way. I look forward to using these tools when ROSARIO is released. The test tools will allow us to manage and execute our tests in a much more efficient and effective way to ensure quality on our projects. 

posted @ 4/24/2008 11:22 AM by Randy Bergeron

The Unofficial, still Plausably Deniable, Future Home of the "San Diego" Chargers

So officially it's not yet an option, after all the San Diego Chargers are still working with the city (suburb) of Chula Vista to keep the Chargers football team in San Diego County.  And of course the Chargers spokesman has officially denied it... http://www.sportsbusinessdaily.com/index.cfm?fuseaction=sbd.preview&articleID=120164 (account needed for full article - but the headline says it all)

However, if Chula Vista 'stumbles', one environmental suit or negative ruling in the next two years, and lets face it the Chargers are moving to Los Angeles and this brand new, very fancy stadium.  Construction should be ready to begin in 4Q of this year and my guess is if it does and if the inevitable challenges to the Chula Vista site arise - "Los Angeles 'super' Chargers" will be the new theme song...

http://www.losangelesfootballstadium.com/

I easily could be wrong but let's face it if there wasn't already a sequence of events (or perhaps more than one) that would result in a team moving here, this idea would be crazy.  Fact is, IMHO that's what you would have to be to think that this isn't the future home of the Chargers.  BTW, check out the background color scheme - which NFL team has uniforms in Baby Blue?  Heck another story even has Roski on the record as stating that the team moving could play in other LA venues for 2009, 2010 till this place opens in 2011.

posted @ 4/21/2008 2:05 PM by Bill Sheldon

The new phone books are here, the new phone books are here...

This is one of those 'hey look at me' posts that always make me feel like... well if you recognize the title of the movie that the quote which is the title of this movie comes from - that pretty much sums it up.

Anyway a few 'ads'. 

First off, I have a new article available over at SQL Magazine.  It's a very introductory article to LINQ for SQL so if you are looking for a good starting point for just getting started with LINQ, here's a short article that might be of assistance: http://www.sqlmag.com/Article/ArticleID/98205/sql_server_98205.html

The second item fits the post a bit better.  Back in the first Quarter I signed on to do another book - yes my wife is ready to kill me - which since she is pregnant get's the pregnancy multiplier (we're currently around 7 or 8 so the danger level is getting pretty high).  At any rate if you are interested it's still way out in the future - like October 2008 - if "we" (me) make "our" (my) final due date - here is the page: http://www.amazon.com/o/ASIN/0470377313/105-1544171-6096430

As you can note on that page this next book is an Office Business Applications book.  Of note, it will have both C# and VB samples (ok VB sample - but more on that later) and covers using WPF with Outlook Form Regions and Excel not to mention server side document generation.  That's the good news - the bad news - well I'm late on my chapters - of course that's pretty typical for me - the question is can I catch up in the next few weeks - especially given the increasing pregnancy multiplier...

Finally, I thought I should mention that my last book is finally getting read to be available.  At 1600 pages it pretty much is a phone book, and it should ship for the first week of May which apparently is fast approaching: http://www.amazon.com/Professional-Visual-Basic-2008-Evjen/dp/0470191368/ref=sr_1_1

 

posted @ 4/17/2008 5:27 PM by Bill Sheldon

"ROSARIO" TAP using "Camano" Tool

I have been participating in the Microsoft TAP program using the new Team Foundation Server codename "ROSARIO". I have been very impressed with this version of the TFS server. I will be making several posts on the features since the functionality in ROSARIO is more than one post can accommodate.

Let me add the disclaimer that these are potential features that will be part of the new version of TFS wether  these features will be part of the official release (I sure hope they are) has yet been determined. So today I'm going to concentrate on a new tool being introduced codename Camano.

Microsoft is creating tools to assist in manual testing. This is a great area that needs assitance and Camano is a great step in this direction. Currently here at InterKnowlogy all our test cases are written in word documents with only outbound references inside the document to link with the project requirements. Needless to say this creates issues when trying to run reports to confirm coverage of requirements.

Camano is a new tool that allows a tester to create and organize the test cases for a given project and link the cases back to to defined requirements that are stored in TFS.

Camano1

Above is a screen snapshot of creating a test case in Camano. As we can see each of the steps of the test case are stored inside TFS as Test Case work item. From here we will add the test case to a Test Suite, and the we will create the Test Plan which will track the actually testing of the features. As we can see Camano allows us to consolidate our test cases and test planning tasks into a single utility, they are not buried inside of a word document, which will give us the ability to easily generate coverage reports. Now from here we will be able to use the Microsoft Test Runner tool to actually run the test suite. Which will be the topic of the next post.

posted @ 4/17/2008 12:51 PM by Randy Bergeron

WPF Now? Why should you?

I'm in week 5 of teaching my Visual Basic I programming class at the University of California San Diego Extension.  The week 5 class is going to focus in on WPF and helping students get a better feel for working with this new user interface paradigm, and it's custom 'script' language XAML. :-)

WPF comes with several new concepts and I think that for developers who are just getting started and or coming from a solid web application background many of these concepts feel very natural.  On the other hand there are a host of developers out there who are coming from a Forms/Win32 based background.  For these developers, even though most people think of WPF as a Forms replacement the new declarative model and in particular the new buzzwords leave them overwhelmed.

After all most people that show of WPF applications are busy making sure they've included as many graphical elements as they possibly can, for example one famous paraphrase of Tim Huckaby is "It's just not a WPF application without some form of gratouitous animation."

However, from my standpoint, in the way I approach introducing developers is to explain some elements on XAML and then focus on the similarities between WPF and Windows Forms development.  For example in Chapter 17 of the soon to be released Professional Visual Basic 2008 which will ship this May, my approach is to literally have you start by designing what could easily be a Windows Forms application using WPF.  Over the course of the chapter the application is migrated with the title bar being hidden, buttons being customized, etc as you introduce more and more concepts that are native to WPF. 

In the beginning you start by working with the Visual Studio 2008 editor.  This editor is well known to be VERY limited in comparison to Blend.  However, if you are moving from Windows Forms to WPF then you'll feel much more comfortable in this environment.  Start here and work towards the same type of applications, then introduce Blend.  Blend not only provides several key examples that you can use to get a better feel for the WPF paradigm, but allows you to start to take that item which you feel comfortable with and migrate it to a WPF paradigm with routed events, complex styling and other elements that are much more in keeping with the declarative programming model.  Of course this book isn't about WPF so I don't go deep on things like styling and databinding and other topics, but it will help you start so that those topics combined with everything else in WPF aren't quite so overwhelming.

Keep in mind that while there are rumored to be several WPF related updates coming in the next update to Visual Studio 2008 (I think I covered when to expect that to appear) even with these updates you as a developer are still going to need to start to transition to this new UI paradigm.  Fortunately because WPF performs better on Vista then on XP, and has no backward compatability below XP there is still time for you to get up to speed... but that grace period won't last forever.  More importantly those performance issues are primarily for heavy duty graphics, if you are working in a more Windows Forms paradigm you won't see much of a difference at all.

Which brings me to "Why do it now?" - Well we already have an announcement that Windows Forms 2.0 was the last of the new development on that model.  By starting to work with WPF now, even though you might not create a gratouitous graphic, you are creating an application tier that as WPF takes over (and with it's relationship to Silverlight 2.0 the pace of adoption is imho going to accelerate) your code even though it still has the standard Windows Forms look will integrate and be able to be adapted much easier then people who are continuing to create new solutions using Windows Forms.  So now is the time to take those existing designs and just start by implementing them in WPF with little or no leverage of the high end graphics - and then as you get more comfortable with just how much power WPF provides you can update them to leverage that power.

posted @ 3/20/2008 12:39 AM by Bill Sheldon

Knowing Who Executed a Custom Workflow Action

As I noted in my last post I’ve been working with a State based custom MOSS workflow.  I’ve actually reached the point where I’m into resolving minor issues during my unit tests.  One of my tests involved having a user other then the assigned user take a pending task and resolve/address it.  So for example a document waiting to be approved is recognized by a manager who is covering for the assigned manager.  The covering manager has “permission” to complete the task but isn’t the assigned user.  This is where I had what I consider to be unexpected behavior.

What happens in SharePoint is that when I start in the debugger (or after deploying my workflow outside the debugger) the workflow is run in the context of the administrator.  Now before you read that as “administrator” let me clarify – it’s run under a fixed account.  The context of the thread executing the workflow isn’t assigned based on the current user.  So whether it’s the administrator account or the Guest account the point is that at runtime if a parameter containing the user who triggered a workflow event isn’t passed into the workflow there is no way to determine the actual identity of the person triggering that next step in the workflow.  This is important because if you are planning a workflow, then like most you are planning to capture a history of events which occurred.  The problem if you don’t explicitly pass the name of the current user triggering an event then the name available as part of your running context will not be correct.  Thus your history can at best reflect the name of the user who was supposed to resolve/address that action.  Lost is the identity of the user who actually accessed your site and did take action on that workflow item.

If someone actually has an answer for getting that user (aside from explicitly setting a parameter) that I'm not aware of please feel free to let me know?

I spent quite a while looking at the parameter and runtime environment data and created a new WindowsPrincipal.GetCurrent() instance to see if I could find the actual current user. I also checked for example the current user value in this.workflowproperties.web, and it also was the administrator.  Of course it might turn out to be a setting within SharePoint that I'm not aware of.  Not that I would have explicitly set it since I can only begin to guess at where the setting comes from when my workflow is deployed from Visual Studio 2008.  (btw, the account I deploy from isn't the administrator account.)

I actually consider this to be a pretty major workflow failing… in theory there is a reduction in security since the process executing the workflow has the permissions associated with (in this case the administrator) the most privileged account that will need to run any workflow.  Additionally it breaks down on tracking reliability since it is in theory possible to apply the wrong account name to some of the history data, or if you haven’t planned for it to not explicitly capture the actual user executing the workflow. 

Keep in mind if you are building and testing your workflow under the administrator account you might not ever notice this.  However, knowing about this issue you can set up an InfoPath form and at least capture the name of the user who actually acted on the associated workflow.

posted @ 3/11/2008 10:43 PM by Bill Sheldon

Thoughts on Microsoft Mix: The WideOpen Web

The majority of my blog posts are not exposed externally, but when a group of folks asked me to do an external post on my thoughts about the Microsoft Mix conference in Las Vegas this week, I gladly said, “Sure!”.  So here we go…Attending the conference was time well spent for me and consequently, I’m more confident than ever that not only is Microsoft building the platform, tools and plumbing for the next generation of applications, but that InterKnowlogy is perfectly aligned as experts in these technologies - specifically WPF and Silverlight.

I have been a strong advocate and evangelist for “the smart client revolution” for many years.  When .NET Windows Forms 2.0 shipped ~ 5 years ago, the deployment and maintenance nightmare of COM was nearing an end.   And finally people started seeing that in most cases building browser based applications inside the firewall was just silly – especially when you consider the developer productivity achieved.  Let’s face it. It simply is much easier to build windows apps than it is to build browser based apps.    I call this the Winform phase of the Smart Client Revolution.

In 2005, WPF shipped and took client apps to the next level.  WPF allows us to do things in design, usability, and UX that we never speculated would come so quickly.  In all honesty, WPF took me totally by surprise.  The paradigm was different, and difficult.  But the results were so compelling.  I call this Phase II.

In my opinion, we are in the 3rd phase of the smart client revolution: The Silverlight phase.  Silverlight gives us the ability to build rich client applications and manifest them in the browser…cross platform!  It’s basically WPF for the browser.  Sure it’s a light version of the .NET framework, but at a 4.3 mb download there are tough choices to be made on what goes in and stays out.

I am speculating here, but in phase 4 we are headed for a world where:

·         The rich clients of WPF are going to collide with applications delivered in the browser. 

·         There will be no delineation between web and windows.    The tool (Visual Studio) will not delineate between the two types.

·         Issues of cross platform will be overcome – at least for platforms and devices that have an SDK.

·         We’ll have a full blown framework / next generation version of Silverlight where the technical and security challenges of access to the entire .NET framework over the web delivered in a browser will be overcome.

 That’s a world I want to live in and it’s happening a lot quicker than I thought it would.  For now, the next 18 months of building WPF and Silverlight applications is going to be really fun.

posted @ 3/8/2008 8:21 AM by Tim Huckaby

SharePoint 2007 custom Workflow Debugging Quirk with Visual Studio 2008

So I noticed an issue the other day.  I have a custom SharePoint 2007 workflow as part of some work I'm doing on an Office Business Application (OBA).  Now if you were at the Office Developers Conference (ODC) in San Jose this year you saw Jay Schmelzer demonstrate how you could with Visual Studio 2008 start up the debugger on a SharePoint State Workflow project and have Visual Studio automatically update and deploy the files associated with your workflow. It's a great capability and very powerful when it comes to working with SharePoint workflow projects. 

However, I recently ran into a problem every time I went to debug my workflow the deployment step failed and the debugger failed to start.  It took a little while but I soon realized that the problem was related to two of the files the workflow.xml and the feature.xml files being marked read only in the deployment directory.  It was only a short time after that till I realized that the problem was related to the fact that I had finally bound my development environment to our Team Foundation Server (TFS).

It turns out that when Visual Studio deploys the files associated with the workflow it leaves the file attributes unchanged from your development directory.  This is an issue because in working with TFS and not having these files checked out they are marked as read only.  The first time you deploy no problem, the old version wasn't read only... but the second time the deploy fails.  Once you check the files out - even though you aren't planning to edit them, Visual Studio will deploy writable copies again.  However, you'll first have to access that directory on your system and manually reset the files to not be read only.

posted @ 3/7/2008 10:54 AM by Bill Sheldon

A dark day in Title Town

Brett Favre retired... sports pundits (who are of about the same value as political pundits) have spent tons of hot air on the subject and finally get what so many have asked for (a good football story after the Super Bowl and before March Madness)  I have to admit I was hoping for something more along the lines of the day Cal Ripken Jr. took himself out of the Orioles starting line-up (and finished out the season). My personal hope was that Brett would 'retire' to the role of backup early in a future season - help the team and Aaron R. along for that year and fill in if needed - since most first year QB's need some help along the way... 

 

So another streak ends, but as I listened to the clip I realized that Brett was in this voicemail also illustrating personal motivation and the role it plays for those at the top of their game.  Often  people who are put in charge of an organization forget that the best and only real motivator for your top performers are the expectations they set for themselves.  Listen to the clip, it isn't that Brett couldn't or wouldn't like to play but that his expecation that anything less then a Super Bowl victory would be a disappointment.  Brett recognized what his expectations for performance for the coming year were -which brought him to the conclusion that it was time to leave while he was (based on his performance last year) at the top of his game - plus a team that had a great year.

My remaining question - since Fox broke this story before literally anyone else including the Packers let it out - what is Brett's role when he comes to work for their network?  Lets face it they were so sure of the story - it was like well if he hadn't already signed - they were deep enough in negotiations that the deal was considered done.

posted @ 3/5/2008 2:34 PM by Bill Sheldon

How about those new Tech money makers...

This is a combination of humor and warning of lessons learned...

posted @ 2/26/2008 11:17 PM by Bill Sheldon

Visual Studio 2008 Launch and Updates

The Heroes Happen Here (http://HeroesHappenHere.com) launch event for Visual Studio 2008 happens this week.  As with the Visual Studio 2005 launch event this is a shared launch that includes Windows Server 2008 and SQL Server 2008.   Visual Studio 2008 actually released back in November of 2007 and since then we've all had a chance to start building applications.  The new features in Visual Studio 2008 are very powerful across the board, but those associated with Visual Basic and LINQ happen to be particularly powerful.  I'm sure the the launch will do a great job of showing off the new features, after all it seems like just last week at the Office Developers Conference that we were showing off several of the features related to created solution based on the Office 2007 products. (There was a truly awesome demonstration of the built in debugging capability of Visual Studio 2008 with custom MOSS workflows during the ODC that I happen to know a little about.)

I don't want to steal any of Microsoft's thunder related to Wednesday's launch event in LA, but instead to look beyond the current release.  Not way into the future (ie. Hawaii - a future version (next?) of Visual Studio) but something much closer - the coming updates to Visual Studio 2008.  That's right we haven't even gotten to the launch and of course the focus is already shifting to the next set of features.  This makes more sense when you consider that SQL Server 2008 - which is part of this week's launch event isn't actually releaseing until sometime in the 3rd quarter of 2008.  Thus I'm going to point out some things which it certainly appears will be releasing for Visual Studio 2008 at the same time as SQL Server 2008 releases.

Why do I say that - well the first example is a set of updates to ADO.NET to support the new features of SQL Server 2008 - http://blogs.msdn.com/adonet/archive/2008/02/21/coming-soon-to-linq-to-sql.aspx Yes as part of the release of SQL Server 2008 ADO.NET will be getting updates to support the new data types which are going to be available.  The nice thing about that post is that it helps clarify those new SQL Server features which are most likely to be used by application developers right out of the gate.

On the other hand a single blog post really doesn't firm up that those enhancements have to arrive with SQL Server 2008 -  they might not arrive until say October or November or even later, rather it is the fact that we also have word on several other new Client features which are going to be releasing "this summer."  Scott Guthrie outlines several new enhancements to Visual Studio 2008's client model http://weblogs.asp.net/scottgu/archive/2008/02/19/net-3-5-client-product-roadmap.aspx 

I personally am very interested in some of the new deployment enhancements, but lets get real there is no way Microsoft is making more then one release of enhancements this summer so the combination of the two blog posts gives us a pretty good idea of when to expect the next set of developer tool updates (http://www.sqlmag.com/Article/ArticleID/98161/sql_server_98161.html).

It's nice to see that new tools and enhancements to Visual Studio 2008 are on the way even if as some at Microsoft admit the new tools are coming at a breakneck pace: http://blogs.msdn.com/rbarker/archive/2008/02/04/test-post-from-windows-live-writer.aspx  (btw, I'm planning to download the Live Writer SDK as soon as I get caught up and have some free time...)

posted @ 2/24/2008 3:22 PM by Bill Sheldon

New InRoads to Internet Access

The biggest problem with wireless internet access (either WIFI or cellular) is finding a good connection. Sure your local coffee shop (woo hoo Starbucks) has a connection but what about other locations. This is where cellular comes into play. I have an awesome verizon card built into my laptop and for the most part no matter where I am I can access the Internet. So with these two solutions as long as I can find a hot spot or get cellular service I am good. But what about areas that don’t have a hot spot or cellular service? As I read more and more about how advances in technology and the internet are helping us I always think about areas in the world that don’t have all of this infrastructure in place and what they can do. I am glad to see that other people are thinking the same way. I was very excited to see that Japan launched a new satellite that has the capability to provide satellite based internet access anywhere in the world. The potential for this technology is enormous enabling anyone in the world to be connected. Take away the geek aspect of this and look at the potential for the medical industry for instance. A doctor in say the back country of Nairobi can consult with doctors anywhere in the world to assist him in diagnosing a patient or even better in an actual surgery. It is advances like this that make working in the technology business worthwhile.

posted @ 2/23/2008 7:41 AM by Adam Calderon

Using CodeRush and Resharper together

I love developer tools. I've been an avid user of of Developer Express's CodeRush and Refactor Pro for years and have gotten so used to having them that their shortcuts have become reflexes and I get uncomfortable when I have to use Visual Studio without them. I've also come across a lot of devoted Resharper users who feel the same way about their favorite tool. The ongoing debate about which is better I think is a matter of personal preference.  Both of these tools provide lots of extra capabilities to VS and I would recommend that anyone that spends a lot of time in Visual Studio try them both.

For a long time I wanted to try adding Resharper on top of the DevExpress tools but was always too worried about crippling CodeRush or eating all of my machine's resources. I had tried Resharper a few times in the past but had quickly given up when I saw how much memory overhead its background compiling added. A few months ago I started working with a team that all use Resharper and was impressed with some of the features it added, especially in the XAML editor. This finally gave me the extra nudge I needed to get the 2 products to work together and I'm happy to report that if you can afford to get them both and your hardware can handle it they do play well together.

I've now gotten quite comfortable with running the current versions of the DevExpress products (3.0) and Resharper (3.1) in both VS05 and now VS2008. A few tips if you're going to try them both:

  • I've used the pattern of installing CR and Refactor, then Resharper. I ran into a problem at one point with losing some DevExpress settings after the Resharper install so I now zip up and then restore my entire Settings folder when installing Resharper.
  • Both products have their own expansion template languages (like more powerful snippets). CodeRush includes many more templates out of the box and is my default choice but each template language has it's own strengths. My setup uses Space for CR expansion and Tab for Resharper expansion (I think those are both the defaults) so I can use either one or both for new templates, depending on which language fits the specific template I'm creating. CR's type substitution makes for more flexible templates in most cases. For templates that surround the current selection, Resharper's "Surround With" templates are quicker to add (but less flexible) than the corresponding CR feature.
  • A few features common to both products can conflict: things like auto-closing braces and on the fly formatting. I got around a bunch of minor problems by turning off everything in the "Editor" options for Resharper. A lot of other common features (like refactorings and navigation) can be left on because they're triggered in different ways. The more you use them the more comfortable you'll get with mixing features from both.
  • You will use more RAM. CodeRush and Resharper use somewhere in the neighborhood of 100-150 MB and Resharper uses about 75 MB plus more for background compiling depending on the size and complexity of the open solution. For large solutions Resharper can account for half of the total VS memory usage. A project I'm currently working on has a solution of ~20 projects that runs at about 850 MB with both tools running, 400 MB of which is used by Resharper. Both tools can be flipped on and off from the Add-in Manager if you want to temporarily do without their overhead and features.
  • I have not tried doing a complete removal of both tools so if you're thinking about just trying this out do it in a VPC or on a system you wouldn't mind rebuilding. I've read about people having VS problems after removing past versions but I'm not sure how much uninstall has been improved recently for either product.
  • Don't give up on either product if it feels like it's slowing you down at first! You will need some time to train yourself to do things in new ways but it will become much easier the longer you do it.

Here are some of my custom CodeRush templates for WPF in XAML and C#: CodeRush templates
These are some Resharper templates for XAML: Resharper templates

Get more info or download trials: Developer Express CodeRush and Refactor | Jetbrains Resharper

posted @ 2/2/2008 2:30 PM by John Bowen

Code Camp Presentations

Thanks to everyone that attended my presentations!

Sample code includes sln files for both VS 2005 and 2008. Slides are in pptx format (get converters to use in Office 2003).

WPF Data Binding: slides | code
Lots of stuff in the code that we didn't get to. Look at NavWindow.xaml to see just how much can go into a binding expression.

WPF Controls: slides | code

Also check out some of my other blogs posts for more sample code.

posted @ 1/27/2008 5:43 PM by John Bowen

Moving to Visual Studio 2008

After trying out the Orcas Betas I was very disappointed that the XAML editor had actually been made harder to use, especially after using the VS 2005 November 2006 CTP addin for so long. There were some great additions to the editor and it seemed to be more stable at least in the time that I spent in it but there were some usablity differences that I found infuriating and forced me to stop using the Betas for my WPF development. Now that I've been using the RTM version for a while I'm happy to report that the XAML editor is much more usable thanks to the new features that made it into the final product.

Now if you've gotten used to the old XAML editor (or the plain XML editor, which the CTP version was built on) closing your tags for you and adding quotes you won't need to stop every 5 keystrokes to go back and add all the stuff you expected to be generated when using Orcas. The new default view option is further icing on the cake. These issues were brought up by a lot of people during the Beta process and obviously were added into the product near the end of the development cycle as indicated by the separate Options dialog page for their settings as well as their absense from the Betas. This really shows that MS does heed the feedback they get during the CTP/Beta process.

A few additional WPF features that you get by moving from the 2005 CTP to 2008 RTM:

  • The designer actually works more than 10% of the time! It's still quite possible to "Whoops" it and it's still short of the rendering ability of Blend but it's a big step from the CTP. It supports double-clicking to create event handlers but unfortunately I haven't yet found a way to select anything other than the default event like you can in Blend and in the WinForms/ASP.NET designers.
  • Intellisense doesn't break when you reference a custom xmlns. It's also much more geared toward XAML now that it's not based on the XML schema Intellisense. It also works for adding xmlns definitions and lets you choose from a complete (more or less) set of .NET namespaces in assemblies referenced by your project.
  • Document Outline now works for XAML and even has an element level preview feature that renders an element as you mouseover it in the outline.
    Document Outline

    The preview does require that the design view be rendered but the outline itself is always there even if you're staying in the text view. The outline breadcrumb familiar from the ASP.NET designer also appears at the bottom of the editor in both modes and shares the same preview functionality.
    Breadcrumb
  • Expanded syntax highlighting provides separate font settings for XAML which consist of all the normal XML categories plus Markup Extension Class, Markup Extension Parameter Name, and Markup Extension Parameter Value. There's also opening/closing tag highlighting that works just like the bracket highlighting in C#.
  • Formatting options let you set a tag wrapping length so elements with many attributes will get wrapped to the next line or you can have every attribute placed on its own line.
  • The Property dialog works for XAML. Like the Document Outline preview it requires that the designer renders the XAML, but after that it can be used even in the text only editor where it magically adds new attributes for any settings that you change. This should be especially helpful for beginners who would otherwise have to waste time digging through Intellisense to find the name of the property they want to set.
    Property Grid
  • The integrated Zoom control lets you zoom in or out on the designer just like in Blend. It also has a fit to window button that toggles to 100% and the maximum viewable.
  • Solution Explorer knows that you're in a WPF project. Now if you right-click on your project and Add -> User Control it gives you a WPF rather than WinForms User Control!
  • There is real backward compatibility with 2005 CTP so you don't need to be held back by your poor coworkers that can't upgrade. When moving a project you will need to run through the upgrade wizard the first time and you will need to plan on using a separate 2008 solution as 8.0 and 9.0 slns are not compatible. The project upgrade process will make a few changes including adding some new project properties (which will be ignored by 2005), associating some new sub-elements (Generator and SubType) with included XAML files, and removing the explicit reference to the Microsoft.WinFX.targets MSBuild file. This last change is the only one that will mess with 2005 so once the upgrade is completed, open the project as XML and add  <Import Project="$(MSBuildBinPath)\Microsoft.WinFX.targets" /> near the end of the file right below the CSharp/VisualBasic Import statement. After that the project should work in both versions.

One additional tip: 2008 is much more stable on machines that have not had previous Beta installations. I know it's a standard recommendation but my personal experience has been that the WPF designer especially is much more prone to crashing on my machines that were running Beta 2 and had it uninstalled than my machines that were clean OS installs or only had 2005.

posted @ 1/22/2008 12:17 AM by John Bowen

My Day with Form Regions and Custom Message Classes in Outlook 2007

I was creating a form region in Outlook 2007 today for appointments and I wanted to limit the form from showing up with every appointment. I read that you could associate the form region with a custom message class and once you did this the form region would only show up for messages of that type. So with that information in hand I marched through the New Outlook Form Region Wizard (see Figures 1–4) in Visual Studio 2008. I was trying to create an adjoining form region that would show up on the bottom of the appointment screen so when I got to “Select the form region you want to create” step (see Figure 2) I selected Adjoining and continued to “Identify Message Class that will show this form” step (see Figure 4) where I added my custom message class “IPM.Appointment.MyAppointment” and finished. After adding some content to my form region I started to debug my add-in. This is when the trouble began. I could not find my custom form anywhere. Normally you would go to File>New>Choose Forms… the form would be there (see Figure 5) ready for you to choose and enter data in. Not in this case. After a long process I finally figured out that a custom message class will only work with replacement and replace-all form regions and not adjoining which I was using. The note in the SDK (see Figure 6) hints at this but it doesn’t come out and say “It will only work with these types”.

FormRegionWizardStep1

Figure 1 – Selecting how to create your form region

FormRegionWizardStep 2

Figure 2 – Choosing the form region type

FormRegionWizardStep 3

Figure 3 – Naming your form region

FormRegionWizardStep 4

Figure 4 – Determining Message class to use

Choosing form

Figure 5 – Selecting form in Outlook

Note in sdk

Figure 6 – Note in SDK

posted @ 1/16/2008 5:58 PM by Adam Calderon

Customer Profitability Tiers, PerformancePoint, and Analysis Services, Oh My

I recently read an article asserting, that perhaps, just possibly, the customer is not always right. In fact, the less profitable the customer is, the less right they are. OK, so it didn't say it quite that way, but the basic idea was companies should consider customer profitability when setting their customer service goals. Higher levels of customer services should be provided to the more profitable customers, and unprofitable customers (with little hope of future profitability) should be "fired". As with all good management articles, there was a clever little hook to make the technique memorable. This one happened to use a metallurgical metaphor (or is it an analogy?). Your most profitable customers are your Platinum customers. These are your tier 1 customers, interested in advanced service levels, extra support, or other highly profitable value-added services. Your Gold customers are also quite profitable, but not to the extent your Platinum customers are. Next is your Iron customers. They are profitable, but not overly so. If you spend TOO much time and money, they may become…..a lead customer. These are your unprofitable customers; those that demand unreasonable amounts of customer service, continually ask for freebees, bounce checks, and generally make your CFO sad. In addition, Lead customers don't have season tickets to the Padres, luxury boxes, or country club memberships.

I know what you're thinking…"this sounds fantastic, but how can I track customer-focused metrics by profitability segment, and present this information in an executive dashboard using PerformancePoint and the Microsoft BI stack?". I'm glad you asked.

Essentially, we need a customer-focused scorecard with different actual and target values for a given metric in each customer segment. For example, it will not suffice to provide a "Support Calls Per Month" metric in the customer scorecard. We need a Support Calls Per month for Platinum customer, a Support Calls Per Month for Gold Customers, and so on... because we are striving to provide different levels of support based on customer tier.

First of all, as all good armchair-economists do, let me preface this with some assumptions. Lets assume we have a data warehouse…Lets also assume that we do not have the time or resources to provide data feedback into a CRM. If this was the case, it would probably be preferable to calculate per customer profitability in the financial system, implement business logic to categorize profitability ranges into customer profitability tiers, and send this information back to the CRM. Not only would this information then be available in almost real time to support and sales staff, these tiers would be available as members of a Customer Tier dimension... A subject for another blog.

In this case I'm going to use SQL Server Analysis Services to create calculated members in the customer dimension in order to create customer profitability tiers. This calculated member will compute the average of any applicable measure (in this case I will use support calls per month as an example). In PerformancePoint, we then create a Key Performance Indicator using the desired measure (support calls per month) as the value for the metric, and filter the customer dimension for the appropriate customer tier. We drag and drop it into a dashboard, pretty it up, and deploy to our SharePoint 2007 site. The boss is impressed with how quickly this was done and raises his expectations for future projects.

In my toy problem here, I already have a SQL Server Analysis Service cube consisting of sales facts (FactInternetSales) and a customer dimension. Also, information from the support system has already been cleansed, transformed, and loaded into this data warehouse, where it lives quite happily in another fact table in the same cube (FactSupport_Custom).

clip_image001

In SQL Server Business Intelligence Development Studio, I open that cube, go to the calculations tab and create a calculated member for each customer tier:

image

Note that the parent hierarchy is Customer.Customer, with the parent member [All Customers]. This allows me to later filter the cube by this new "member" in the customer dimension.

The expression for the Platinum customer computes the average of ANY MEASURE included in the query for just those customers with [Internet Gross Profit Margin]>50%:

AVG(FILTER([Customer].[Customer].[All Customers].Children,[Measures].[Internet Gross Profit Margin]>.50))

This is then available as a member in your favorite multi-dimensional analysis tool. The below screenshot shows average profitability for each calculated "member" for 2003. (Note that I've already filtered out the non-calculated customer members)

clip_image003

If I drag my Support Calls Per Month measure in I get:

clip_image004

This tells us that in 2003 the average support calls per month for our Platinum customers is 5.638, 5.529 for our Gold customers, and so on.

 

Surfacing the information in PerformancePoint

At this point, if you are a back office kind of person, your job is done. Tell the Business Analysts that they can filter the customer dimension by customer tier to create Tier-specific KPIs and go to lunch.

OR….

From PerformancePoint Dashboard Designer, create a new KPI, click on the data mappings for the "Actual" Metric:

clip_image005

Click on Change Source, and select the data source for your cube

clip_image006

Select the desired measure (remember, in this case we will be getting the AVERAGE of any measure we select)

clip_image007

In the Select a Dimension part of the dialog, click on the filter and select the Customer.Customer hierarchy (this is the parent hierarchy that we selected when created our calculate member in a previous step).

clip_image008

In the default column, select the default link and filter by your desired profitability segment:

clip_image009

Repeat for each KPI, set your targets FOR EACH TIER then drag into a scorecard, add the scorecard to a dashboard, and deploy.

clip_image010

Of course, this may not be the ideal solution in many cases. Using Calculated Members in a large cube may have performance implications, and you may not get all the analytics you want out of it for reasons I won't go into here. The point, however, is that scorecards based on customer segments (in this case profitability segments), can be implemented relatively easily, provided your organization has some level of BI maturity.

Go Chargers.

posted @ 1/15/2008 7:38 PM by Scott Larson

Microsoft Mainstream Support - Early .NET reaching the end of lifecycle

A couple years ago there was a huge crisis since Microsoft was bringing an end to mainstream support for VB6.  At the time some people felt the sky was falling.  The reality of course is that applications still worked but the available support for unexpected behavior stopped.

Well it's that time again. The end of support for .NET 1.1 has been announced - October 14, 2008.  A little over 5 years after .NET 1.1 was released.  This isn't the end of support, just end of mainstream support.  Support will continue until 2013 - if you are like me your next question is what's the difference.  Microsoft provided the following table to explain:

What is the difference between Mainstream Support, Extended Support, and online self-help support?

Support provided

Mainstream Support phase

Extended Support phase

Paid support (per-incident, per hour, and others)

X

X

Security update support

X

X

Non-security hotfix support

X

Requires extended hotfix agreement, purchased within 90 days of mainstream support ending.

No-charge incident support

X

Warranty claims

X

Design changes and feature requests

X

Product-specific information that is available by using the online Microsoft Knowledge Base

X

X

Product-specific information that is available by using the Support site at Microsoft Help and Support to find answers to technical questions

X

X

Note A hotfix is a modification to the commercially available Microsoft product software code to address specific critical problems.

This might have other impacts, for example SharePoint 2.0 (2003) is built using .NET 1.1 for customization, so the impact of this on the SharePoint community and custom web parts could be significant.  Of course since SharePoint 2.0 mainstream support ends around 7/2008 (less then 6 months from now) that probably won't be a problem... at least on the .NET side - not sure about those actually using the product who haven't migrated to SharePoint 2007 (3.0) (Note: I was actually expecting the reverse (.NET 1.1 support ending first) when I started this post...)

At any rate I think it's safe to say that you shouldn't even consider starting a project on .NET 1.1 or SharePoint 2.0 (2003) at this point.  Of course in my opinion anyone not working on VIsual Studio 2008 is behind the power curve.

posted @ 1/9/2008 4:56 PM by Bill Sheldon

Code Length Guidelines in Visual Studio

If you have ever presented or written an article you probably have ran across a situation where the code you have written contains lines that are to long and you need to modify them to fit on the screen or page. This can be a real pain especially when you write code using a wide screen monitor with a high resolution. Well for the past few years I have just lived with this issue until I ran across this really cool blog entry Guidelines - A hidden feature for the Visual Studio Editor by Sara Ford that details how to modify your registry setting to get guidelines in the Visual Studio editor. Once I modified my registry setting, lines showed up in the editor giving me a visual clue of how long my code lines were. At last no more code hacking! For those of you who don’t know who Sara Ford is she is a prolific blogger of all things Visual Studio related and a great source for all kinds of little trinkets on the subject.

posted @ 1/7/2008 8:53 PM by Adam Calderon

ASP.NET Ajax Controls Book Coming Soon

Over the last year Joel Rumerman and I have been working on a book for Addison-Wesley that is part of the Microsoft’s .NET Development Series that Addison-Wesley publishes. It has been a long haul but the fruits of our labor are starting to take hold. The book is entitled Essential ASP.NET Ajax Controls and covers both the JavaScript and .NET side of creating controls in ASP.NET Ajax and the Ajax Control Toolkit. The book has been a blast to write and we hope you will enjoy it. The topic is something Joel and I have been involved with since the early Alpha as part of the ATLAS First Access program that began in early 2006.

 

0321514440_MED

 

posted @ 1/7/2008 12:07 PM by Adam Calderon

Let the Biking Begin

So it's a new year... and time to get working on getting back on my bike again.  I managed some riding this past year which was good - but not nearly as much as I'd hoped.  I've fallen about 2,400 miles off my target annual mileage... oh well, hopefully I'll hit or exceed my target this year - although in all honesty I think it'll be difficult to hit my target again this year.

On the plus side my light is working again, I was unable to ride to and from work for most of Dec. because when I pulled out my light it stopped working.  I have a very nice Flamethrower from NiteRider (www.niterider.com).  (The flamethrower was the 1st generation the current generation is the Flight: http://www.niterider.com/prod_flight.shtml) This light puts out more light then most car headlights - which is good because when I'm riding at night I want to be seen and this isn't a headlight that you can miss.  Unfortunately on my first ride home this winter; when I fired it up - the LEDs powered up but each time I tried to get my main light to start it failed.  I made it home, after all the 3 LED's do provide minimal light - but not an acceptable situation.

So I used the NiteRider website and gave them a call.  Their service was well coordinated and they gave me a Return Maintenance Authorization (RMA) number to track my repair.  So I sent them my light, at the height of the Christmas season...  A couple days after FedEx showed my package had been delivered I gave them a call to check on the status.  Note I didn't send them my battery because they charge $20 for each returned item (light, battery) and since my LED's worked, my taillight worked and my light was trying to fire up I felt the battery was solid.  When I spoke to the maintenance rep he mentioned he was preparing to call me... the problem was a bad ballast and the light had been given some free maintenance beyond the ballast.  So I paid for the light's bench test and parts.

I got it back a few days later and set up a test at home (no sense repeating my last ride).  Well I fired up the light - and same results.  Now I have no doubt that they tested my light before shipping it back to me so I called them back.  Of note I didn't start screaming or looking to kill the phone guy, I just said hey - got my light but it still doesn't work.  We talked a few minutes and we agreed I would send my light and battery back and they would waive the bench fee on the battery as long as it checked out (we all knew it would) and (still in the Christmas season) they put a rush on the work order.

A few days later I got my light and battery back - no charges, apparently something else related to the starter in the light or the light itself had failed (probably took a hit in shipping) and they had repaired my light and gotten it back to me in a matter of days.  Overall although it did take two trips (for the FedEx guy) they did a great job getting my light back online (although I was on vacation by then). 

Today I hooked up the light and rode into work - yes I had tested it previously. The goal is to get to ride in 3 days a week, and I'd ride tomorrow but it looks like the rain really will arrive tomorrow so I'll wait till next week to ride in again, but my thanks to the folks at NiteRider who did a great job with my light's repair and now I just need to get in a couple thousand miles...

posted @ 1/4/2008 12:14 AM by Bill Sheldon

Happy Holidays...

posted @ 12/23/2007 10:37 PM by Bill Sheldon

Don't Use the Original... Storing the Template in the 21st Century

Many years ago there was a common pattern for Office Workers.  Essentially before the true abundance of desktop systems and printers it was common to have a paper form.  Copies of this form would be used for any number of tasks (fax cover sheets are a common example most people can relate to) and then when there weren't any copies left you would make a new set of copies.  The cardinal sin for the admin staff was of course the person who took the original and used it instead of copying it.  Want to really get on the Admin staff's bad side wipe out 3 or 4 originals and they will hunt you down...

At any rate now that we have PC's and easy access to printers the separate set of file folders containing originals hidden from non-admin eyes is pretty much a thing of the past.  These documents are typically stored on a central Intranet server like SharePoint.  However, in many cases a limited version of the same problem still exists.  Now people will take the copy that is on the server and open it for customization.  Then without thinking they save that copy and it goes right back to the server.  In minor cases they've just poluted the baseline copy that's sitting on the server - but in extreme cases they could so modify the original that its almost useless as the original.  The solution of course is to make such original copies read only, except now instead of having them under lock and key in a big old file cabinet - they sit online marked read-only or checked out to the one trusted individual who won't overright them...  It's the same solution to the problem, just implemented with 21st century technology instead of physical copies.

------------------------------------------------------

Sorry for the long delay and somewhat sparse posts over the last few weeks (OK Months) but I've been a little busy with the latest version of the Professional Visual Basic book to go along with Visual Studio 2008 and VB 9.  However, I reached a milestone last night - OK theoretically it was early this morning.  I caught up with my publisher.  I've turned in all my draft chapters and returned all of the edited chapters that were returned to me to date.  I'm not yet done because there are more edits that need to be returned to me - of course the fact I turned in the draft late might be impacting that... but for tonight at least I don't have any authoring commitments... except I'm supposed to start that magazine article...

posted @ 12/20/2007 4:13 PM by Bill Sheldon

XML, XSL, XAML, XPS......XACTLY?

For some reason at every company I have worked for I have been dubbed the "Reporting dude." I don't know how this title was bestowed on me but so be it. Unfortunately reports aren't particularly sexy, you never hear people saying "Whoa check out that pivot table!"

 

All that aside, recently I came across a reporting challenge that I thought was particularly interesting. Currently in WPF there isn't much in the way of report designers (at least none that I have seen). We do have some very simple integration with the XPS framework, which makes printing XAML very easy. However, all the examples out there of generating an XPS document relies on the fact that your created the XAML objects in code. Ok, but that goes against a major tenet of WPF of separating the design and the implementation.

 

The challenge I was faced with was to create a reporting architecture in WPF that would support changes to report formats without invasive code changes, Support multiple output formats if desired (XPS, HTML, Excel, etc..) and the nice to have feature is to allow reports to be built using a visual designer if possible.

 

Well looking at the requirements and the toolset available first thought we were going to have to make a lot of compromises. I thought some more about it and took a lesson from my web developer toolset. Why not use XML to model the data and XSL to transform the data to the desired format?

 

I knew this would work for HTML and Excel outputs, what I didn't know was how it would work for XAML. So I gave it a go and here is how it went.

 

1. Model some test data in XML:

We need a sample chunk of data to work with in order to test our idea. So I started with this :

<?xml version="1.0" encoding="utf-8" ?>
<EmployeeInfo>
    <Employee>
        <FirstName>Bob</FirstName>
        <LastName>Smith</LastName>
        <City>San Diego</City>
        <State>CA</State>
    </Employee>
</EmployeeInfo>

2. Transform the data in to a XAML document:

Now that we have sample data to work with we need to write and XSLT document that will take the XML data above and turn it into a XAML document (I wasn't sure what I was going to get with this step. I didn't know how nicely XSL would play with XAML.)

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:template match="EmployeeInfo">
        <StackPanel xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" Orientation="Vertical">
            <TextBlock>
                <TextBlock.Text>
                    <xsl:value-of select="Employee/FirstName"/>
                </TextBlock.Text>
            </TextBlock>
            <TextBlock>
                <TextBlock.Text>
                    <xsl:value-of select="Employee/LastName"/>
                </TextBlock.Text>
            </TextBlock>
            <TextBlock>
                <TextBlock.Text>
                    <xsl:value-of select="Employee/City"/>
                </TextBlock.Text>
            </TextBlock>
            <TextBlock>
                <TextBlock.Text>
                    <xsl:value-of select="Employee/State"/>
                </TextBlock.Text>
            </TextBlock>
        </StackPanel>
    </xsl:template>
</xsl:stylesheet>

 

3.  From here the rest is fairly straight forward. You do the actual transformation in code (something like this)

XmlReader xreader = XmlReader.Create("SampleData.xml");

MemoryStream mem = new MemoryStream();
TextWriter twriter = new StreamWriter(mem, System.Text.Encoding.UTF8);

XslCompiledTransform trans = new XslCompiledTransform();
trans.Load("XAMLOutput.xslt");
trans.Transform(xreader, null, twriter);
 

4. From there all we have to do is to take the transformed output and turn it into an XPS document. What I did was take the transformed output and get it in string format and then created a function to create an XPS document

void XamlToXPS(string srcXaml,string destXpsFile)
        {
            
            StringReader stringReader = new StringReader(srcXaml);
            XmlReader xmlReader = XmlReader.Create(stringReader);

            object parsedDocObject = XamlReader.Load(xmlReader);
           
            XpsDocument document = new XpsDocument(destXpsFile, FileAccess.ReadWrite);
            XpsPackagingPolicy packagePolicy = new XpsPackagingPolicy(document);
            XpsSerializationManager serializationMgr = new XpsSerializationManager(packagePolicy, false);
            
            serializationMgr.SaveAsXaml(parsedDocObject);
            document.Close();
        }

That's it!

I tested this much more complex chunks of xaml and didn't find any issues. One thing to note is that you have to make sure the XAML namespace is specified for the root element of the document in order for the

XAML reader to understand the XAML elements (see the bolded area of my sample XSLT).

 

This solution separates the data from the implementation, it allows for format changes to the report without invasive code changes, and it adds the nice to have feature of allowing report design through a visual designer. Since XPS is simply loose xaml packaged up, you can design the report using Blend. Then take that xaml and paste it into the XSLT file and manipulate it to show the data from the XML where needed. 

posted @ 12/20/2007 11:41 AM by Brad Cunningham

My MSDN Web Cast on PowerPoint and Visio Solutions with VSTO in Visual Studio 2008

I am a huge Visual Studio Tools for Office Fan so when the VSTO team asked me to do a webcast for them, I said, “absolutely yes.”  What i didn't realize was how hard it would be to build the demos.  There just is not a lot out there for Visual Studio 2008 VSTO 2008 right now, so I am glad to provide the code for the demos i build so that you can “run“ with them. 

I can tell you that the genesis of the idea for this presentation goes to Paul Stubbs of the VSTO team.  He is a brilliant guy and a genuinely great guy and until i read his article in msdn magazine, i had pretty much given up on document-centric solutions for visio and powerpoint.  So, thank you paul for inspiring me to take your ideas to the next level.

The links to the demos and the ppt deck from the MSDN Webcast I did on 12/14/07 Called, “Office Development in Visual Studio - PowerPoint and Visio Solutions“:

Download the PowerPoint Deck from the msdn webcast here: Download

Download the first VSTO 2008 PowerPoint Addin demo here: Download

Download the second VSTO 2008 PowerPoint demo that creates a Powerpoint presentation here: Download

Dowload the VSTO 2008 Visio demo that creates a Visio Document here: Download

posted @ 12/14/2007 4:35 PM by Tim Huckaby

VS 2008 and Blend 1.0

So one of my biggest pet peeves with the release of VS2008 was the fact that if I created a WPF project in VS 2008 or even converted it to work in VS2008 - then I was stuck - no more taking that project into Blend to work on the graphics.  This to me was a significant issue.  Fortunately Soma announced that this issue has been resolved and Blend SP1 which supports the VS 2008 project files is now available. Here are the links:
Soma: http://blogs.msdn.com/somasegar/archive/2007/11/30/designers-and-developers-working-together.aspx

Blend SP1:  http://www.microsoft.com/downloads/details.aspx?FamilyID=a07196d1-971b-4710-99c8-d3d9603ccfcb&DisplayLang=en

posted @ 11/30/2007 12:32 PM by Bill Sheldon

My 11/27/2007 San Diego .NET User Group Presentation

Here are the slides and here is the code from my presentation yesterday.  A big thank you to everyone who attended, I thoroughly I enjoyed discussing DDD with you guys!

By the way, here is the link to my book on the Wiley web site:

http://www.wiley.com/WileyCDA/WileyTitle/productCd-0470147563.html

posted @ 11/27/2007 10:27 PM by Tim McCarthy

Team Explorer 2008 Install Error

Once I installed Visual Studio 2008 it was time to add the Team Explorer for Visual Studio 2008.  The Team Explorer aka Team Foundation Client is found on the Team Foundation Server installation DVD.

So I took the .ISO file which I downloaded from MSDN and copied the TFC folder which contains the Team Explorer installation onto an actual DVD.  This gave me a copy of just the Team Foundation Client 2008 which I could install onto my development machines.

I put the DVD into my Vista/Office 2007 machine and kicked off the install.  The install ran and after things were going I moved onto another machine.  When next I checked I found that the installation had failed.  So I reported the failure via the automated process that the install package provided and tried again.  The install failed again - which left me... concerned.

So I took the DVD out of my Vista machine and moved to my Windows XP / Office 2003 machine and ran the installation.  While that was running I started searching the web for any known installation errors with Team Explorer 2008.  I finally found a note in the Microsoft MSDN Forums that mentioned someone else was having an install problem and found that it went away when they used the install from a DVD which had all of the TFS products, as opposed to a CD with only the TFC folder.

Now what was interesting is I found this as my Team Explorer install on Windows XP with Office 2003 completed successfully.  In other words on an XP machine running Office 2003 you only need the TFC directory to install Team Explorer.

So I went to my .ISO file and burned a DVD of the entire image this time and put it into the Vista/Office 2007 machine.  I must admit I really like the updated install package for the TFS product, having the different product options available is a nice way of handling the different install packages.  At any rate I clicked on the Team Foundation Client and started the install.  The first and subsequent screens to start the installation looked just like the stand-alone DVD's and the install started with the same packages.  However, in this case the installation ran to completion.

Thus if you are using Windows XP with Office 2003 you can install a standalone installation package for Team Explorer however, if you are running Vista or Office 2007 and you get an installation error - then make sure you get a copy of the full Team Foundation Server (TFS) DVD and run the install from that media.

posted @ 11/23/2007 1:02 PM by Bill Sheldon

WPF "Master Page" like functionality

 

UPDATE: I found and issue with placing the default content elements in the Resources for the Page. When you place the elements directly in the resources, without wrapping them in a template, there is only one instance of the elements created. This means that after the MasterPage control is created the first time the elements will never get re-initialized. This causes problems when you have buttons or other interactions that bind to properties specific to current instance of the master page.

For example : If you had a ButtonContentArea defined and you placed a save button in that area with a Command "SaveCommand" that was bound to a command on the consumer of the MasterPage control, that command would be initialized the first time the MasterPage control is created. Then any subsequent consumers of the master page would use the Binding from the first instance of the master page. This means your save command would be routed to the wrong handler. If you make the Dependency Properties of Type DataTemplate and you wrap the elements in a DataTemplate then bind to the ContentTemplate property of the controls you can resolve this issue. The code below has been updated to reflect this change.

Now on with your regularly scheduled programming.

 

Coming from an ASP.NET background one of the things I really like are Master Pages. If you aren't familiar with master pages read this first.

In WPF there are several different ways to share styles and templates across pages. Recently I had a need to share a common layout across multiple pages while still allowing for different content and behaviors on each page. The first thing I thought was Master Page. However this feature doesn't come out of the box with WPF.

However it is easy enough to implement your own version. A quick search provided me with Karin Huber's code project article about this very subject. This approach uses a user control as the master page. After playing around with this example one problem I found is that you are unable to name elements that are inside of the master page user control (others have discovered this as well if you view the comments on the codeplex project or you view Rob Relyea's blog post) This isn't a deal breaker by any means but I wanted to give a go at implementing it myself. It was surprisingly easy when I got down to it.

 

First I created a simple custom control named Master Page and a few dependency properties for the different content zones I am going to expose. Here is what that looks like

    public class MasterPage : Control
    {
        public static DependencyProperty MainContentAreaProperty =
            DependencyProperty.Register("MainContentArea", typeof (DataTemplate), typeof (MasterPage));

        public static DependencyProperty HeaderContentAreaProperty =
            DependencyProperty.Register("HeaderContentArea", typeof(DataTemplate), typeof(MasterPage));

        public static DependencyProperty RightContentAreaProperty =
            DependencyProperty.Register("RightContentArea", typeof(DataTemplate), typeof(MasterPage));
       
        public static DependencyProperty FooterContentAreaProperty =
           DependencyProperty.Register("FooterContentArea", typeof(DataTemplate), typeof(MasterPage));
      
        static MasterPage()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(MasterPage), new FrameworkPropertyMetadata(typeof(MasterPage)));
        }

        public DataTemplate MainContentArea
        {
            get { return (DataTemplate)GetValue(MainContentAreaProperty); }
            set { SetValue(MainContentAreaProperty, value); }
        }

        public DataTemplate HeaderContentArea
        {
            get { return (DataTemplate)GetValue(HeaderContentAreaProperty); }
            set { SetValue(HeaderContentAreaProperty, value); }
        }

        public DataTemplate RightContentArea
        {
            get { return (DataTemplate)GetValue(RightContentAreaProperty); }
            set { SetValue(RightContentAreaProperty, value); }
        }

        public DataTemplate FooterContentArea
        {
            get { return (DataTemplate)GetValue(FooterContentAreaProperty); }
            set { SetValue(FooterContentAreaProperty, value); }
        }

    }

 

The generic.xaml is straightforward. I placed ContentControls where I wanted "content zones." I named them accordingly and I bound the ContentTemplate property to the appropriate dependency property

<Style TargetType="{x:Type local:MasterPage}">
        <Setter Property="HeaderContentArea" Value="{StaticResource HeaderContent}"/>
        <Setter Property="MainContentArea" Value="{StaticResource MainContent}"/>
        <Setter Property="RightContentArea" Value="{StaticResource RightContent}"/>
        <Setter Property="FooterContentArea" Value="{StaticResource FooterContent}"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:MasterPage}">
                    <Grid ShowGridLines="True">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*"></ColumnDefinition>
                            <ColumnDefinition Width="225"></ColumnDefinition>
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="50"></RowDefinition>
                            <RowDefinition Height="*"></RowDefinition>
                            <RowDefinition Height="25"></RowDefinition>
                            <RowDefinition Height="25"></RowDefinition>
                        </Grid.RowDefinitions>
                        <ContentControl Grid.Column="0" Grid.Row="0" x:Name="HeaderContentArea" ContentTemplate="{TemplateBinding HeaderContentArea}"/>
                        <ContentControl Grid.Column="0" Grid.Row="1" x:Name="MainContentArea" ContentTemplate="{TemplateBinding MainContentArea}"/>
                        <ContentControl Grid.Column="0" Grid.Row="2" x:Name="FooterContentArea" ContentTemplate="{TemplateBinding FooterContentArea}"/>
                        <ContentControl Grid.Column="1" Grid.RowSpan="3" x:Name="RightContentArea" ContentTemplate="{TemplateBinding RightContentArea}"/>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

This allows a consumer of this control to bind any piece of content they want to the dependency property of their choice and that content will be displayed in the "content zone" defined in the generic.xaml.

 

For example your Window1.xaml would look something like this 

    <Window.Resources>
        <DataTemplate x:Key="HeaderContent">
            <StackPanel>
                <TextBlock Text="Header Text"/>
                <Rectangle Fill="Black" Width="25" Height="25"/>
            </StackPanel>
        </DataTemplate>

        <DataTemplate x:Key="RightContent">
            <StackPanel Grid.RowSpan="3">
                <Rectangle Width="100" Height="50" Fill="DarkBlue"/>
            </StackPanel>
        </DataTemplate>
        
    </Window.Resources>
   
    <local:MasterPage  HeaderContentArea="{StaticResource HeaderContent}" RightContentArea="{StaticResource RightContent}" />

Pretty simple right?

 

Well what if we don't bind to all the available content zones like in the example above? With the current setup the layout elements (in this case grid rows / columns) will still be rendered but they will be empty. This may or may not be the desired behavior for your situation.

 

Furthermore you don't want to build this nice layout template and still force your consumers to bind content that will be static across multiple consumers. So we want to provide default content for the content zones from within the generic.xaml.

Easy enough we just need to bind the content property of our zone to a static resource defined in generic.xaml right?

Something like this :

<DataTemplate x:Key="FooterContent">
    <StackPanel>
        <TextBlock Text="Copyright 2007. All rights reserved"/>
    </StackPanel>
</DataTemplate>
  
<ContentControl Grid.Column="0" Grid.Row="2" x:Name="FooterContentArea" Content="{StaticResource FooterContent}"/>
 

 

This will work and will give you a distinct behavior. By doing this you are no longer binding to the dependency property defined in the control and therefore you are forcing the content zone to use the content defined in the generic.xaml. Your consumer will not be able override the content for this zone. This may or may not be the desired behavior.

 

For my situation I wanted to provide default content for the different zones but I also wanted to let the consumer override the content if they wanted to. I also wanted to provide specific defaults for zones that give the user a visual cue they have not bound to a "required" content zone.

 

First we defined default content for each of our zones in the generic.xaml file like this.

<DataTemplate x:Key="HeaderContent">
        <StackPanel>
            <TextBlock Text="Header" FontSize="15" FontWeight="Bold"/>           
        </StackPanel>
    </DataTemplate>

    <DataTemplate x:Key="MainContent">
        <StackPanel>
            <TextBlock Opacity="0.25" FontSize="18" Text="CONTENT ERROR! Bind content to the MainContentArea dependency property" TextWrapping="Wrap"/>
        </StackPanel>
    </DataTemplate>

    <DataTemplate x:Key="RightContent">
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="Right Text"/>
        <Rectangle Fill="AliceBlue" Width="25" Height="25">
            <Rectangle.BitmapEffect>
                <DropShadowBitmapEffect/>
            </Rectangle.BitmapEffect>
        </Rectangle>
        <Ellipse Fill="YellowGreen" Width="25" Height="25"/>
        </StackPanel>
    </DataTemplate>

    <DataTemplate x:Key="FooterContent">
        <StackPanel>
            <TextBlock Text="Copyright 2007. All rights reserved"/>
        </StackPanel>
    </DataTemplate>

 

Then we modified our control template to use Setters to set the dependency properties to the Static Resources in our generic.xaml.

<Style TargetType="{x:Type local:MasterPage}">
        <Setter Property="HeaderContentArea" Value="{StaticResource HeaderContent}"/>
        <Setter Property="MainContentArea" Value="{StaticResource MainContent}"/>
        <Setter Property="RightContentArea" Value="{StaticResource RightContent}"/>
        <Setter Property="FooterContentArea" Value="{StaticResource FooterContent}"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:MasterPage}">
                    <Grid ShowGridLines="True">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*"></ColumnDefinition>
                            <ColumnDefinition Width="225"></ColumnDefinition>
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="50"></RowDefinition>
                            <RowDefinition Height="*"></RowDefinition>
                            <RowDefinition Height="25"></RowDefinition>
                            <RowDefinition Height="25"></RowDefinition>
                        </Grid.RowDefinitions>
                        <ContentControl Grid.Column="0" Grid.Row="0" x:Name="HeaderContentArea" ContentTemplate="{TemplateBinding HeaderContentArea}"/>
                        <ContentControl Grid.Column="0" Grid.Row="1" x:Name="MainContentArea" ContentTemplate="{TemplateBinding MainContentArea}"/>
                        <ContentControl Grid.Column="0" Grid.Row="2" x:Name="FooterContentArea" ContentTemplate="{TemplateBinding FooterContentArea}"/>
                        <ContentControl Grid.Column="1" Grid.RowSpan="3" x:Name="RightContentArea" ContentTemplate="{TemplateBinding RightContentArea}"/>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
 

 

Notice that we can now keep the content properties for each of our zones bound to the dependency properties we defined in our class. We have also set these properties with default values so if the consumer doesn't set them they will get the content we defined. This is nice because it allows us to move static content in to the custom control's generic.xaml and leaves less for the consumer to worry about.

Another nice feature is we are able to give the user a visual error if they do not bind to a zone that we feel they should bind to. In this case I have defined a main content area and defaulted the content to a textblock that shows an error:

<DataTemplate x:Key="MainContent">
        <StackPanel>
            <TextBlock Opacity="0.25" FontSize="18" Text="CONTENT ERROR! Bind content to the MainContentArea dependency property" TextWrapping="Wrap"/>
        </StackPanel>
    </DataTemplate>

 

Right away the consumer will see the message that they forgot to bind to the content area and can quickly fix the error.

 

Overall this is a pretty simple solution that gives you a nice way to share a layout across multiple pages while still allowing the individual pages to control the content. This also makes it easy to change the layout of your pages in one place. You just modify the layout of the "content zones" in the master page and all your consumer using the control will see the change.

 

UPDATE: You can find the sample code here

posted @ 11/21/2007 2:46 PM by Brad Cunningham

VS2008 installing Release version over Beta2

So for those who weren't aware Visual Studio 2008 released on Monday November 19th.  I got my download started early while the downstream transmission speeds were still above 300KB and it finished late yesterday afternoon, early evening when the transmission speeds were down under 70KB.

So like many who have been using Visual Studio 2008 Beta 2, I made the decision to install Beta 2 on my main desktop (physical machine).  This was a good decision as I've been using Beta 2 for projects for the past 4 months.  However, now it was time to face the music - would I need to rebuild my box to get the release version installed?

As part of working on the next Version of Professional Visual Basic for Wrox, I have a virtual environment which was configured for my authoring and screen shots.  So it became my test platform.  I started the uninstall of VIsual Studio 2008 Beta 2, I uninstalled MSDN, and as I looked at the list of other products some of which hadn't uninstalled I found several that were from 7/27 the day I installed VS 2008 B2 and I could tell they were related, so I uninstalled them as well.  I then took a couple minutes to rename my old projects directory to "B2" since I plan to rebuild the projects from scratch and I made sure other directories that VS would target were also clean. 

So I took a fairly conservative approach to minimize the risk that it would fail.  I rebooted and connected my VPC to the ISO which I downloaded and kicked off the install with crossed fingers.  The installed started no problem.  Nearing the end of .NET Framework version 3.5 was install my Vista machine asked me to reboot and restart my installation, which I did.  The installation then ran to completion and asked for another reboot.

I then installed MSDN locally and again everything went fine.  So for those wondering installing the release version of VS 2008 on a machine which previously ran VS 2008 Beta 2 seems to a non-issue.  So get out there and get the latest bits and start working there are a ton of new features to explore.

 

posted @ 11/20/2007 11:03 AM by Bill Sheldon

Anonymous Delegates, how do I love thee? Let me count the ways...

This isn't anything new but I came across a situation recently where I was able to re-factor a seemingly trivial piece code to use an anonymous delegate and it reminded me how cool they are.

One great thing about generics is you can create a collection of strongly typed custom objects and iterate that collection to perform any number of operations. Often times you want to locate an item in the collection given a certain criteria.

I put together a simple little example to show the situation pre-generics,post generics without anonymous delegates, and post generics with anonymous delegates.

 

To set the scene let's assume we have a person class defined as follows

public class Person   

{
        private int id;

        private string firstName = string.Empty;
        private string lastName = string.Empty;


        public int ID
        {
            get { return id; }
            set { id = value; }
        }

        public string FirstName
        {
            get { return firstName; }
            set { firstName = value; }
        }

        public string LastName
        {
            get { return lastName; }
            set { lastName = value; }
        }
    }

 

Prior to generics you might load an ArrayList of person objects like so:

        static ArrayList LoadPersonList()
        {
            ArrayList list = new ArrayList();

            Person Bob = new Person();
            Bob.ID = 1;
            Bob.FirstName = "Bob";
            Bob.LastName = "Smith";

            Person Sally = new Person();
            Sally.ID = 2;
            Sally.FirstName = "Sally";
            Sally.LastName = "Jones";

            list.Add(Bob);
            list.Add(Sally);

            return list;
        }

So working from this example if we wanted to find the Person record with the first name Bob we could do something like this.

 

First write a find method that searches the ArrayList for the given first name. Something like this :

        static Person FindPersonByFirstName(string firstName, ArrayList personList)
        {
            foreach (Person p in personList)
            {
                if (p.FirstName == firstName)
                {
                    return p;
                }
            }
            return null;
        }

Then we call the find method and pass the FirstName "Bob":

       static void Main(string[] args)
        {
            ArrayList personList = LoadPersonList();
            Person bob = FindPersonByFirstName("Bob", personList);
        }

Not so bad.

 

With generics we get a little better

 

First our load method now looks like this

      static List<Person> LoadPersonList()
        {
            List<Person> list = new List<Person>();

            Person Bob = new Person();
            Bob.ID = 1;
            Bob.FirstName = "Bob";
            Bob.LastName = "Smith";

            Person Sally = new Person();
            Sally.ID = 2;
            Sally.FirstName = "Sally";
            Sally.LastName = "Jones";

            list.Add(Bob);
            list.Add(Sally);

            return list;
        }

 

And our find method has been simplified to look like this

        private static bool FindPersonByFirstName(Person p)
        {
            if (p.FirstName == "Bob")
                return true;
            else
                return false;
        }

 

And now we use the List<T> Find method like this to locate the item in the list that we want:

        static void Main(string[] args)
        {
            List<Person> personList = LoadPersonList();
            Person found = personList.Find(FindPersonByFirstName);
        }

 

You notice that we are now hard-coding "Bob" in the implementation of the Find method. That obviously isn't ideal. We need a better solution for passing arguments to the find method while still leveraging the generic List's built in find features (namely iterating the collection for you)

 

This is where anonymous delegates come in to play. Using the same person list we loaded above, we can eliminate our find method all together and do this instead:

       static void Main(string[] args)
        {
            List<Person> personList = LoadPersonList();
            Person found = personList.Find( delegate (Person p) { return p.FirstName == "Bob";});
        }


 

Neat huh?

 

To take it a little further if you want to be able to call a generic method passing the List and the value to search for (instead of writing the above for each time you need to find an item). You could do something like this :

        static Person FindPersonByFirstName(string firstName, List<Person> list)
        {
            return list.Find(delegate(Person p) { return p.FirstName == firstName; });
        }

 

With this implementation of the Find method the Main method from above would like this:

        static void Main(string[] args)
        {
            List<Person> personList = LoadPersonList();
            Person found = FindPersonByFirstName("Bob", personList);
        }

 

This works for all of the methods attached List<T> and will simplify the mundane task implementing the guts of the various methods (FindAll,FindLast,Exists,etc..)

 

 

posted @ 11/19/2007 6:53 PM by Brad Cunningham