NHibernate Mapping to System.Drawing.Color

In my POCO (Plain Old CLR Object) class, I had a property for FontColor that is of type System.Drawing.Color. I wanted this to map to an HTML string value in the database. i.e. #ffffff

Basically, I wanted to do a type conversion from #ffffff to System.Drawing.Color. At fist I didn’t realize that this sort of type conversion was built-in to NHibernate via the interface IUserType. I thought you had to use you new custom type in the POCO, but I found that you can just use the IUserType implementation to map to the native .NET type.

Here is how I did it…

First, create the custom type that implements IUserType. This will be used to do the type conversion from string to Color.

public class ColorUserType : IUserType
{
    public object Assemble( object cached, object owner )
    {
        return cached;
    }

    public object DeepCopy( object value )
    {
        return value;
    }

    public object Disassemble( object value )
    {
        return value;
    }

    public new bool Equals( object x, object y )
    {
        if(ReferenceEquals(x, y ) )
        {
            return true;
        }
        if( x == null || y == null )
        {
            return false;
        }
        return x.Equals( y );
    }

    public int GetHashCode( object x )
    {
        return x == null ? typeof( Color ).GetHashCode() + 473 : x.GetHashCode();
    }

    public bool IsMutable
    {
        get
        {
            return true;
        }
    }

    public object NullSafeGet( IDataReader rs, string[] names, object owner )
    {
        var obj = NHibernateUtil.String.NullSafeGet( rs, names[0] );
        if( obj == null )
        {
            return null;
        }
        return ColorTranslator.FromHtml( (string)obj );
    }

    public void NullSafeSet( IDbCommand cmd, object value, int index )
    {
        if( value == null )
        {
            ( (IDataParameter)cmd.Parameters[index] ).Value = DBNull.Value;
        }
        else
        {
            ( (IDataParameter)cmd.Parameters[index] ).Value = ColorTranslator.ToHtml( (Color)value );
        }
    }

    public object Replace( object original, object target, object owner )
    {
        return original;
    }

    public Type ReturnedType
    {
        get
        {
            return typeof( Color );
        }
    }

    public SqlType[] SqlTypes
    {
        get
        {
            return new[] { new SqlType( DbType.StringFixedLength ) };
        }
    }
}

Next, create the POCO.

public class MyClass
{
    public int Id { get; protected set; }
    public Color FontColor { get; set; }
}

Next, create the mapping file. I’m using FluentNhibernate here.

public class MyClassMap : ClassMap<MyClass>
{
    public MyClassMap()
    {
        SetupMapping();
    }

    private void SetupMapping()
    {
        Id( m => m.Id );
        Map( m => m.FontColor ).CustomTypeIs<ColorUserType>();
    }
}

Now when you get an instance of MyClass from NHibernate, the string color stored in the database will be converted to a System.Drawing.Color.

Windows 7 and Realtek HD Audio

After installing Windows 7 my sound was very crackly and just sounded horrible. I searched around for a while trying to find a way to fix this, and found many posts with fixes for this… none that worked.

I finally found that Realtek’s drivers on their site are now updated to work with Windows 7. The site doesn’t say so, but updating to the newest drivers fixed all sound issues.

Just install the Vista driver located here and everything will be peachy.

The New World of NHibernate

NHibernate has always been a great tool for data access but there are a couple things that have always bugged me; the mapping files and the non-type-safe querying. There are now some great tools out there that solve these problems.

Mapping files has always been a pain for me. It’s not the most intuitive thing and it’s really easy to miss-type something in the xml hbm files. I have started using Fluent Nhibernate to do my mapping files, which has made my life with NH a lot better. Not only do I no longer have to edit xml files, but now the mappings are type-safe. Fluent Nhibernate is a tool that I don’t think I could live without now.

POCO:

public class MyClass
{
    public virtual int? Id { get; private set; }
    public virtual string Name { get; set; }
    public virtual MyReference MyReference { get; set; }
    public virtual IList<MyReference> MyReferenceCollection { get; private set; }
}

Mapping:

public class MyClassMap : ClassMap<MyClass>
{
    public MyClassMap()
    {
        Id( m => m.Id );
        Map( m => m.Name );
        References( m => m.MyReference );
        HasMany( m => m.MyReferenceCollection );
    }
}

The other annoying thing is creating queries that aren’t type-safe, which makes doing re-factors a pain. You would think when using the Criteria language instead of HQL that it would be type-safe, but you still are using strings for the column names. I recently found a tool called NHLambdaExtensions which makes doing Criteria queries type-safe. This makes me sleep a little better at night.

// This:
session.CreateCriteria( typeof( MyClass ) ).Add( Expression.Eq( "Name", name ) );

// Becomes this:
session.CreateCriteria( typeof( MyClass ) ).Add<MyClass>( m => m.Name == name ).List();

What about the Linq-To-Everything craze? I’m definitely a person that loves Linq and use it constantly, so naturally I’m wondering when a Linq-To-NHibernate provider will be coming out. Oren Eini had a simple implementation going but didn’t handle many of the complex scenarios (or so I’ve read, and I must say, he’s a coding machine). But don’t fear, Steve Strong has been employed to create a fully functional Linq-To-NHibernate provider. I’m excited to see it come to fruition and can’t wait to actually use it. You can keep up with the progress at Steve’s blog at http://blogs.imeta.co.uk/sstrong.

Making a Custom Window Resizable in WPF

This is a continuation of my Creating a Custom Window in WPF post. If we create a custom window, we want the window to behave like a normal window. One of those things are making the window resizable.

To make the window resizable, we need something to grab on to. We can’t use the border, because we can’t specify a side or corner of the border, so we will need to create our own border that we can grab.

Let’s start by making the top/right/bottom/left sides. Since our corner has a radius of 10, we’ll set margins on the sides so they don’t overlap the corner. We also want to put a negative margin so that the sides will overlap the border. There are some events here that we’ll use later.

<aero:SystemDropShadowChrome CornerRadius="10" Margin="10">
    <Border BorderThickness="1" BorderBrush="Black" Background="White"
        Margin="0" CornerRadius="10">
        <Grid>
            <Border Height="40" Background="#01000000" VerticalAlignment="Top"
                    CornerRadius="10,10,0,0" MouseLeftButtonDown="DragWindow" />
            <Rectangle x:Name="ResizeN" Fill="Yellow" VerticalAlignment="Top"
                       Height="4" Margin="9,-2,9,0" MouseEnter="DisplayResizeCursor"
                       MouseLeave="ResetCursor" PreviewMouseLeftButtonDown="Resize" />
            <Rectangle x:Name="ResizeE" Fill="Yellow" HorizontalAlignment="Right"
                       Width="4" Margin="0,9,-2,9" MouseEnter="DisplayResizeCursor"
                       MouseLeave="ResetCursor" PreviewMouseLeftButtonDown="Resize" />
            <Rectangle x:Name="ResizeS" Fill="Yellow" VerticalAlignment="Bottom"
                       Height="4" Margin="9,0,9,-2" MouseEnter="DisplayResizeCursor"
                       MouseLeave="ResetCursor" PreviewMouseLeftButtonDown="Resize" />
            <Rectangle x:Name="ResizeW" Fill="Yellow" HorizontalAlignment="Left"
                       Width="4" Margin="-2,9,0,9" MouseEnter="DisplayResizeCursor"
                       MouseLeave="ResetCursor" PreviewMouseLeftButtonDown="Resize" />
        </Grid>
    </Border>
</aero:SystemDropShadowChrome>

window1

Now we can create the corners with a radius of 10.

<Path x:Name="ResizeNW" VerticalAlignment="Top" HorizontalAlignment="Left"
      Stroke="Green" StrokeThickness="4" Margin="0" MouseEnter="DisplayResizeCursor"
           MouseLeave="ResetCursor" PreviewMouseLeftButtonDown="Resize">
    <Path.Data>
        <PathGeometry>
            <PathGeometry.Figures>
                <PathFigureCollection>
                    <PathFigure StartPoint="0,10">
                        <PathFigure.Segments>
                            <PathSegmentCollection>
                                <QuadraticBezierSegment Point1="0,0" Point2="10,0" />
                            </PathSegmentCollection>
                        </PathFigure.Segments>
                    </PathFigure>
                </PathFigureCollection>
            </PathGeometry.Figures>
        </PathGeometry>
    </Path.Data>
</Path>
<Path x:Name="ResizeNE" VerticalAlignment="Top" HorizontalAlignment="Right"
      Stroke="Green" StrokeThickness="4" Margin="0,0,-2,0" MouseEnter="DisplayResizeCursor"
           MouseLeave="ResetCursor" PreviewMouseLeftButtonDown="Resize">
    <Path.Data>
        <PathGeometry>
            <PathGeometry.Figures>
                <PathFigureCollection>
                    <PathFigure StartPoint="0,0">
                        <PathFigure.Segments>
                            <PathSegmentCollection>
                                <QuadraticBezierSegment Point1="10,0" Point2="10,10" />
                            </PathSegmentCollection>
                        </PathFigure.Segments>
                    </PathFigure>
                </PathFigureCollection>
            </PathGeometry.Figures>
        </PathGeometry>
    </Path.Data>
</Path>
<Path x:Name="ResizeSE" VerticalAlignment="Bottom" HorizontalAlignment="Right"
      Stroke="Green" StrokeThickness="4" Margin="0,0,-2,-2" MouseEnter="DisplayResizeCursor"
           MouseLeave="ResetCursor" PreviewMouseLeftButtonDown="Resize">
    <Path.Data>
        <PathGeometry>
            <PathGeometry.Figures>
                <PathFigureCollection>
                    <PathFigure StartPoint="10,0">
                        <PathFigure.Segments>
                            <PathSegmentCollection>
                                <QuadraticBezierSegment Point1="10,10" Point2="0,10" />
                            </PathSegmentCollection>
                        </PathFigure.Segments>
                    </PathFigure>
                </PathFigureCollection>
            </PathGeometry.Figures>
        </PathGeometry>
    </Path.Data>
</Path>
<Path x:Name="ResizeSW" VerticalAlignment="Bottom" HorizontalAlignment="Left"
      Stroke="Green" StrokeThickness="4" Margin="0,0,0,-2" MouseEnter="DisplayResizeCursor"
           MouseLeave="ResetCursor" PreviewMouseLeftButtonDown="Resize">
    <Path.Data>
        <PathGeometry>
            <PathGeometry.Figures>
                <PathFigureCollection>
                    <PathFigure StartPoint="0,0">
                        <PathFigure.Segments>
                            <PathSegmentCollection>
                                <QuadraticBezierSegment Point1="0,10" Point2="10,10" />
                            </PathSegmentCollection>
                        </PathFigure.Segments>
                    </PathFigure>
                </PathFigureCollection>
            </PathGeometry.Figures>
        </PathGeometry>
    </Path.Data>
</Path>

window2

Now we need to make the corners and edges resizable. We also need to make the cursor change when it hovers the corners and edges. To do this, we implement the events I mentioned earlier.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Interop;
using System.Runtime.InteropServices;

namespace ResizableWindow
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        private const int WM_SYSCOMMAND = 0x112;
        private HwndSource hwndSource;

        private enum ResizeDirection
        {
            Left = 61441,
            Right = 61442,
            Top = 61443,
            TopLeft = 61444,
            TopRight = 61445,
            Bottom = 61446,
            BottomLeft = 61447,
            BottomRight = 61448,
        }

        [DllImport( "user32.dll", CharSet = CharSet.Auto )]
        private static extern IntPtr SendMessage( IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam );

        public Window1()
        {
            SourceInitialized += Window1_SourceInitialized;

            InitializeComponent();
        }

        private void Window1_SourceInitialized( object sender, EventArgs e )
        {
            hwndSource = PresentationSource.FromVisual( (Visual)sender ) as HwndSource;
        }

        private void ResizeWindow( ResizeDirection direction )
        {
            SendMessage( hwndSource.Handle, WM_SYSCOMMAND, (IntPtr)direction, IntPtr.Zero );
        }

        protected void ResetCursor( object sender, MouseEventArgs e )
        {
            if( Mouse.LeftButton != MouseButtonState.Pressed )
            {
                this.Cursor = Cursors.Arrow;
            }
        }

        protected void Resize( object sender, MouseButtonEventArgs e )
        {
            var clickedShape = sender as Shape;

            switch( clickedShape.Name )
            {
                case "ResizeN":
                    this.Cursor = Cursors.SizeNS;
                    ResizeWindow( ResizeDirection.Top );
                    break;
                case "ResizeE":
                    this.Cursor = Cursors.SizeWE;
                    ResizeWindow( ResizeDirection.Right );
                    break;
                case "ResizeS":
                    this.Cursor = Cursors.SizeNS;
                    ResizeWindow( ResizeDirection.Bottom );
                    break;
                case "ResizeW":
                    this.Cursor = Cursors.SizeWE;
                    ResizeWindow( ResizeDirection.Left );
                    break;
                case "ResizeNW":
                    this.Cursor = Cursors.SizeNWSE;
                    ResizeWindow( ResizeDirection.TopLeft );
                    break;
                case "ResizeNE":
                    this.Cursor = Cursors.SizeNESW;
                    ResizeWindow( ResizeDirection.TopRight );
                    break;
                case "ResizeSE":
                    this.Cursor = Cursors.SizeNWSE;
                    ResizeWindow( ResizeDirection.BottomRight );
                    break;
                case "ResizeSW":
                    this.Cursor = Cursors.SizeNESW;
                    ResizeWindow( ResizeDirection.BottomLeft );
                    break;
                default:
                    break;
            }
        }

        protected void DisplayResizeCursor( object sender, MouseEventArgs e )
        {
            var clickedShape = sender as Shape;

            switch( clickedShape.Name )
            {
                case "ResizeN":
                case "ResizeS":
                    this.Cursor = Cursors.SizeNS;
                    break;
                case "ResizeE":
                case "ResizeW":
                    this.Cursor = Cursors.SizeWE;
                    break;
                case "ResizeNW":
                case "ResizeSE":
                    this.Cursor = Cursors.SizeNWSE;
                    break;
                case "ResizeNE":
                case "ResizeSW":
                    this.Cursor = Cursors.SizeNESW;
                    break;
                default:
                    break;
            }
        }

        protected void DragWindow( object sender, MouseButtonEventArgs e )
        {
            DragMove();
        }
    }
}

Now the edges are resizable. We don’t want to keep the green and yellow coloring, so we can change all the colors to almost transparent by setting the colors to #01000000.

window3

And now our window looks like normal again and is resizable.

You can download the example project here. Note: Be sure to change the extension from .doc to .zip.

Creating a Common Window in WPF

The is a continuation of my last post Creating a Custom Window in WPF. If you have a custom window that you’re using, you’re going to want all windows to look the same and you don’t want to have to copy the code into every window.

One way to do this is to create a ControlTemplate for the window. All you have to do is set Template="{DynamicResource WindowTemplate}" on the window.

<ControlTemplate TargetType="Window" x:Key="WindowTemplate">
    <aero:SystemDropShadowCrome CornerRadius="10" Margin="10">
        <Border BorderThickness="1" BorderBrush="Black" Background="White"
                CornerRadius="10">
            <Border Height="40" Background="#01000000" VerticalAlignment="Top"
                    CornerRadius="10,10,0,0" MouseLeftButtonDown="DragWindow">
                <ContentPresenter />
            </Border>
        </Border>
    </aero:SystemDropShadowCrome>
</ControlTemplate>

There is a problem with this though. If you want multiple windows to use the template, you’ll need to put the template in a resource file and include it in the each window that you want to have the template. If you want to use any events, such as MouseLeftButtonDown, like in this example, you can’t put it in an external resource file.

The way I found to fix this, is to create an abstract base class that creates the code. You can then wire the events up right in the base class. They key to doing this is to create a ContentPresenter control, and set the window’s content to the content of the presenter. This makes it so that any code that is put in the window will show up in the presenter.

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using Microsoft.Windows.Themes;

namespace CommonWindow
{
    public abstract class WindowBase : Window
    {
        public WindowBase()
        {
            Initialized += WindowBaseInitialized;
        }

        private void WindowBaseInitialized( object sender, System.EventArgs e )
        {
            SetResourceReference( Window.StyleProperty, "Window" );
            ResourceDictionary resource = new ResourceDictionary();
            resource.Source = new Uri( "pack://application:,,,/WindowResource.xaml" );
            this.Resources.MergedDictionaries.Add( resource );

            SystemDropShadowChrome dropShadow = new SystemDropShadowChrome();
            dropShadow.SetResourceReference( Control.StyleProperty, "WindowShadow" );

            Border windowBorder = new Border();
            windowBorder.SetResourceReference( Control.StyleProperty, "WindowBorder" );
            dropShadow.Child = windowBorder;

            Grid grid = new Grid();
            grid.RowDefinitions.Add( new RowDefinition() { Height = new GridLength( 40.0 ) } );
            grid.RowDefinitions.Add( new RowDefinition() );
            windowBorder.Child = grid;

            Border headerBorder = new Border();
            headerBorder.SetResourceReference( Control.StyleProperty, "HeaderBorder" );
            headerBorder.MouseLeftButtonDown += DragWindow;
            grid.Children.Add( headerBorder );
            Grid.SetRow( headerBorder, 0 );

            ContentPresenter contentPresenter = new ContentPresenter();
            contentPresenter.Content = this.Content;
            grid.Children.Add( contentPresenter );
            Grid.SetRow( contentPresenter, 1 );

            this.Content = dropShadow;
        }

        private void DragWindow( object sender, MouseButtonEventArgs e )
        {
            DragMove();
        }
    }
}

We should put all the styling in a resource, which is the first thing included when creating the base code.

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:aero="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero">

    <Style TargetType="Window" x:Key="Window">
        <Setter Property="AllowsTransparency" Value="True" />
        <Setter Property="WindowStyle" Value="None" />
        <Setter Property="Background" Value="Transparent" />
    </Style>

    <Style TargetType="aero:SystemDropShadowChrome" x:Key="WindowShadow">
        <Setter Property="CornerRadius" Value="10" />
        <Setter Property="Margin" Value="10" />
    </Style>

    <Style TargetType="Border" x:Key="WindowBorder">
        <Setter Property="BorderThickness" Value="1" />
        <Setter Property="BorderBrush" Value="Black" />
        <Setter Property="Background" Value="White" />
        <Setter Property="CornerRadius" Value="10" />
    </Style>

    <Style TargetType="Border" x:Key="HeaderBorder">
        <Setter Property="Grid.Row" Value="0" />
        <Setter Property="Background" Value="#01000000" />
        <Setter Property="VerticalAlignment" Value="Stretch" />
        <Setter Property="HorizontalAlignment" Value="Stretch" />
        <Setter Property="CornerRadius" Value="10,10,0,0" />
    </Style>

</ResourceDictionary>

All that we need to do now to get a window to have our common look is inherit from the base class. All the styling, resources and controls will automatically be there.

namespace CommonWindow
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : WindowBase
    {
        public Window1()
        {
            InitializeComponent();
        }
    }
}
<local:WindowBase x:Class="CommonWindow.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:CommonWindow"
    Title="Window1" Height="300" Width="300">

    <Label Content="blah" />
</local:WindowBase>

Now anything we put in our window will show up in our custom window, like our "blah" label.

window1

So all the base controls are coded but we can still abstract most of it out to xaml in resource files. Now we have a common window that we can use and all we have to do is inherit from a base class.

You can download the example project here. Note: Be sure to change the extension from .doc to .zip.

Creating a Custom Window in WPF

For an app I’m working on I wanted to create a custom window look. Here is how I did it.

The default window looks like this:

<Window x:Class="CustomWindow.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:aero="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero"
    Title="Window1" Height="300" Width="300">
    <Grid>

    </Grid>
</Window>

Default Window

To make a custom window, we need remove the default window, and make the window transparent. This will make it so there is no window that shows at all. We need to change the AllowsTransparency, WindowStyle and Background properties.

<Window x:Class="CustomWindow.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:aero="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero"
    Title="Window1" Height="300" Width="300"
    AllowsTransparency="True" WindowStyle="None" Background="Transparent">
    <Grid>

    </Grid>
</Window>

Now we need to start creating our own window. Lets add a border for the window.

<Window x:Class="CustomWindow.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:aero="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero"
    Title="Window1" Height="300" Width="300"
    AllowsTransparency="True" WindowStyle="None" Background="Transparent">

    <Border BorderThickness="1" BorderBrush="Black" Background="White"
        Margin="0" CornerRadius="10">
    </Border>

</Window>

window2

Now that we have our own window design, we should make a draggable area at the top. I made the background black so you could see the draggable area. We need the corner radius to be the same as the window for the top and left and top right so that it doesn’t go over the window. On the border’s MouseLeftButtonDown event, we want to allow the window to be draggable. To make the draggable area be invisible, set the color to #01000000. This will make the border almost completely transparent. It will look 100% transparent, but you will still be able to click on it.

<Window x:Class="CustomWindow.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:aero="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero"
    Title="Window1" Height="300" Width="300"
    AllowsTransparency="True" WindowStyle="None" Background="Transparent">

    <Border BorderThickness="1" BorderBrush="Black" Background="White"
        Margin="0" CornerRadius="10">
        <Border Height="40" Background="#01000000" VerticalAlignment="Top"
            CornerRadius="10,10,0,0" MouseLeftButtonDown="DragWindow"/>
    </Border>

</Window>
using System.Windows;
using System.Windows.Input;

namespace CustomWindow
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }

        protected void DragWindow( object sender, MouseButtonEventArgs e )
        {
            DragMove();
        }
    }
}

window3

Now lets add a drop shadow to the window. We need to add the PresentationFramework.Aero assembly. We can then use the SystemDropShadowChrome control.

<Window x:Class="CustomWindow.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:aero="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero"
    Title="Window1" Height="300" Width="300"
    AllowsTransparency="True" WindowStyle="None" Background="Transparent">

    <aero:SystemDropShadowChrome CornerRadius="10" Margin="10">
        <Border BorderThickness="1" BorderBrush="Black" Background="White"
            Margin="0" CornerRadius="10">
            <Border Height="40" Background="#01000000" VerticalAlignment="Top"
                CornerRadius="10,10,0,0" MouseLeftButtonDown="DragWindow"/>
        </Border>
    </aero:SystemDropShadowChrome>

</Window>

window4

Now we have a customized window. If you want to add a maximize, minimize, and close button, you can add them to the draggable header border and hook the events up. To max/min the window, set the WindowState = WindowState.Maximized, WindowState.Minimized or WindowState.Normal. To close the window just call Close().

You can download the example project here. Note: Be sure to change the extension from .doc to .zip.

Return To Forever

I had the pleasure of sitting 3rd row of the pit at the Orpheum Theatre Minneapolis for the Return To Forever show. For those of you who don’t know, Al Di Meola, Stanley Clarke and Chick Corea are 3 of the best musicians to ever walk this earth. I brought my father with as a father’s day present. He was pretty excited too. He had listened to them play while growing up.

I originally got tickets to see Al not knowing that the others were playing too. I knew Al was in a band with Chick at some point, but didn’t know the name and didn’t know that Stanley Clarke was in it. Even though I wanted to see Al play, I was quite happy to hear that these other 2 legends were playing also.

I didn’t think I was going enjoy Stanley or Chick that much, but I was completely blown away by both of them. Stanely Clarke has got to be one of the best, if not THE best, bass player ever. He played a lot of slap bass and his fingers moved at lightning speed. He did this on the electic bass, and the acoustic bass. I’ve never seen someone whale on an acoustic bass like that before. I just sat there in awe while watching him play.

Chick is an amazing composer and keyboardist. I know Al played several great songs composed by Chick on his albums, and the Return To Forever music is no exception. I was sitting too close to the stage to see Chick’s fingers move on the keyboard, but it sounded difficult to play. ;)

Al was amazing as usual. He plays faster than any guitarist I’ve ever heard and plays so cleanly that you can hear each individual note. None of them are muffled or run together. It’s simply insane. Al didn’t get to solo as much as I would have liked to see him since he’s playing with such other great musicians, but I was OK because of their superb performances. Oddly enough, all the members got up and talked to the audience for a bit except for Al. I would have like to hear him say a few words, but oh well.

I had never heard of Lenny White before and he wasn’t really that great. He did well at keeping the beat for the rest of them, but he had a fairly long drum solo that was just sub-par. Maybe he was doing some crazy time signatures or something that I didn’t catch, but it just wasn’t that interesting.

Seeing Al play live has always been something I’ve wanted to do and I was lucky enough to experience Stanley Clarke and Chick Corea along with him. I was never fortunate enough to see Stevie Ray Vaughan play live before his death, so I had to see Al the first chance I got. This was an absolutely unforgettable night. Now I need to find a way to see Pete Sampras play a tennis match live.

Windows Server 2008, Visual Studio 2008, and SQL Server 2008 Launch

Microsoft’s launch of these products is entitled "Heroes happen {here}". There is a community, trial software, and a launch event in most major cities. They are giving away copies of each product, so you can take them home to play with after learning about them.

Visual Studio 2008 FxCop Errors

I converted a 2005 solution over to 2008 and hit build. I received this error:

MSBUILD : error : Invalid settings passed to CodeAnalysis task

I figured out that the problem was Visual Studio was calling FxCop from the "Visual Studio 8" directory instead of "Visual Studio 9.0". To fix this I had to change an environment variable called "FXCOPDIR" to point to the 2008 instance of Visual Studio.

I’m not sure why the install of 2008 didn’t do this. Oh well.

DevConnections – Make WPF Data Binding Work Against Business Objects

This talk was given by Rockford (Rocky) Lhotka.

Rocky works for Magenic and is kind of a home town hero around here. People are always talking about him and his books and his CSLA Framework and etc, but I’ve never seem him speak before, so I was looking forward to this.

Rocky talked about how data binding works with WPF and gave some examples. The real meat of the talk was centered around the gotchas, and how to work around them. I’ll mention one of them here.

If you create custom objects and a custom data provider and bind that to WPF, you need to implement INotifyPropertyChange. This will cause the UI to refresh itself with the new data, when the data changes. There is a problem here though. When re-bind the data, WPF will check if the data has changed, if not, it won’t refresh the UI. WPF uses the .Equals method to do this, rather than comparing references. If you’re using a database, most of the time you’ll have the .Equals compare something like the Id of the record, and maybe a few other fields. If you update some data that isn’t a part of that, WPF will think it’s the same object and not re-bind. The way around this is to write an identity converter that doesn’t actually do any conversions. If a value from WPF runs through a converter, it will always update the UI afterwards.

Of course Rocky was pushing his CSLA Framework as a sort of a cure for all problems, but he did get into what he was doing in the framework, and why he had to do it. I’m personally not a big fan of the framework, but it was nice to hear the reasoning behind everything he’s doing. He’s definitely a smart man, and I have a lot of respect for him after hearing him speak.

WPF seems like a very powerful tool, but it will take some time for developers to get used to a new programming model like this. I think it has great potential, and is where most, if not all Windows development will be heading in the future.