I recently wanted to put together a portfolio page of the various code and samples that I've worked on over the last few years.  To do so, I created a very simple xml file, which you can see here.  Then, I decided to create two different UI experiences to display the UI, one in ASP.NET and one as a WPF .XBAP.  I added a page that uses javascript to detect if a user has .NET 3.0 and, if they do, I send them to the .XBAP.  If they don't, I send them to the ASP.NET page.

Each implementation turned out to be pretty simple to create and have quite a few similarities.

I like how both data models have something in place to handle nested hierarchies.  In ASP.NET, it is done by using a Repeater inside a Repeater, setting the DataSource with an XPathSelect.  In WPF, it is done by nesting an ItemsControl inside the DataTemplate, setting the ItemsSource to the right XPath.

I also had to handle the case where I didn't have a string value. For example, not all samples have videos, which in the XML looks like this: <VideoUri/>.  In ASP.NET, if I had an empty string,  the syntax I used to not display the URL was to put an expression in the Visible field:

Visible='<%#XPath("VideoUri") != string.Empty %>'

In WPF, I first thought that the built-in BooleanToVisibilityConverter would do the trick, but because you can't do expressions in WPF databinding, I had to whip up a quick converter:

    public class EmptyStringToVisibilityConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            string strValue = string.Empty;
            if (string.IsNullOrEmpty((string)value))
                return Visibility.Collapsed;
            else
                return Visibility.Visible;

        }
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return null;
        }
    }

And then in the XAML, I used the converter as such:

Visibility="{Binding Mode=Default, XPath=VideoUri, Converter={StaticResource StringToVis}}"

Here's some little lessons learned and gotchas:

  • ASP.NET: When using the asp:HyperLink tag in conjunction with the #XPath syntax, I had to use single quotes (') instead of double quotes (") to make the parser happy.
  • WPF: Remember to wrap your ItemsControl in a ScrollViewer, since scrolling doesn't come for free with ItemsControl.
  • WPF: I used the LinkLabel control by Lubo Blagoev which was quite nifty. 
  • WPF: To download the XML from the server to the XBAP, I used the pack://siteoforigin:,,,/ syntax.

So, recursively, I've added the code for my portfolio to my portfolio, which is where you can get the code. The next thing I want to do is add a tag cloud to the application, probably using LINQ. I also want to make the WPF page more interesting to show what you can do above and beyond just displaying the information.

Posted on May 21, 2008 10:42
Actions: E-mail | Comments (3)

Comments


RobertT

RobertT

May 20, 2008 03:13

"..., but because you can't do expressions in WPF databinding,..."

It is not quite true. You CAN write expressions in data binding, but you'll have to write expression converter. Or you could use Kent Boogaart's set of various handy converters, that includes expression converter.

I can't find a link to article as for some reason it was deleted from codeproject.

Best regards, Robert.
          


Rodrigo Ratan

Rodrigo Ratan

May 20, 2008 20:57

I've Windows Vista with .NET 3.5 installed but I'm being redirected to the ASPX version.
          


Karsten Januszewski

Karsten Januszewski

May 26, 2008 05:44

RobertT -- True, true.  No expressions out of the box. There is Blendables by IdentityMine also which supports expressions.  

Rodrigo -- Ah, good point.  I think I need to spend some time tweaking that javascript.  I also realized it isn't handling Mozilla gracefully. Expect a new blog post on that shortly...
          


Add comment

Enter your name, handle, alias, or email.

We'll incarnate your avatar from the services below.