Archive

Archive for July, 2010

Problems customizing the layout of a DataForm using a Grid – Part III

July 22, 2010 1 comment

So let’s move on to a little more complicated scenario where we have a master detail layout all within the same DataForm. I like to embed all of my data entry layout within the same DataForm so that it can be tracked and submitted back using WCF RIA Services. We will continue to use the same object model from the last two posts.

Again we will start with our beloved Grid and perform the same layout as before with a new row underneath that will show our detail. For the detail, I am just creating a TabControl with a single TabItem and a DataGrid bound to the same object model collection.

<UserControl x:Class="SilverlightApplication2.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400"
    xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
    xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit"
    xmlns:l="clr-namespace:SilverlightApplication2.Models"
    >
    <UserControl.Resources>
		<DataTemplate x:Key="DataFormGridTemplate">
			<Grid>
				<Grid.ColumnDefinitions>
					<ColumnDefinition Width="Auto" />
					<ColumnDefinition Width="Auto" />
				</Grid.ColumnDefinitions>
				<Grid.RowDefinitions>
					<RowDefinition Height="Auto"/>
					<RowDefinition Height="Auto"/>
					<RowDefinition Height="Auto"/>
					<RowDefinition Height="*"/>
				</Grid.RowDefinitions>
				<toolkit:DataField Label="First Name" Grid.Column="0" Grid.Row="0">
					<TextBox Text="{Binding FirstName, Mode=TwoWay}" />
				</toolkit:DataField>
				<toolkit:DataField Label="Last Name" Grid.Column="0" Grid.Row="1">
					<TextBox Text="{Binding LastName, Mode=TwoWay}" />
				</toolkit:DataField>
				<toolkit:DataField Label="Business Name" Grid.Column="1" Grid.Row="0">
					<TextBox Text="{Binding BusinessName, Mode=TwoWay}" />
				</toolkit:DataField>
				<toolkit:DataField Label="Bio of Business" Grid.Column="1" Grid.Row="1">
					<TextBox Text="{Binding BusinessBio, Mode=TwoWay}" />
				</toolkit:DataField>
				<toolkit:DataField Label="Fax" Grid.Column="0" Grid.Row="2">
					<TextBox Text="{Binding Fax, Mode=TwoWay}" />
				</toolkit:DataField>
				<toolkit:DataField Label="Phone" Grid.Column="1" Grid.Row="2">
					<TextBox Text="{Binding Phone, Mode=TwoWay}" />
				</toolkit:DataField>

                		<sdk:TabControl Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2">
                    			<sdk:TabControl.Items>
                        			<sdk:TabItem Header="Test 1">
                            				<sdk:DataGrid MinHeight="200" 
								HorizontalAlignment="Left" 
								VerticalAlignment="Top">
                                				<sdk:DataGrid.ItemsSource>
                                    					<l:Customers />
                                				</sdk:DataGrid.ItemsSource>
                            				</sdk:DataGrid>
			                        </sdk:TabItem>
		                    </sdk:TabControl.Items>
                		</sdk:TabControl>
			</Grid>
		</DataTemplate>
    </UserControl.Resources>
    <Grid x:Name="LayoutRoot" Background="White">
        <toolkit:DataForm Header="Data Entry Sample"
			AutoGenerateFields="False"
			ReadOnlyTemplate="{StaticResource DataFormGridTemplate}"
			EditTemplate="{StaticResource DataFormGridTemplate}"
            >
            <toolkit:DataForm.ItemsSource>
                <l:Customers />
            </toolkit:DataForm.ItemsSource>
        </toolkit:DataForm>
	</Grid>
</UserControl>

When we render this DataTemplate, you will notice that the space between the two columns has stretched out to accommodate the width of the DataGrid. We will come back to this:

DataForm using a Grid with Master Detail layout

Now let’s look at how what the template would like for the StackPanel:

<UserControl x:Class="SilverlightApplication2.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400"
    xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
    xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit"
    xmlns:l="clr-namespace:SilverlightApplication2.Models"
    >
    <UserControl.Resources>
        <DataTemplate x:Key="DataFormStackPanelTemplate">
			<StackPanel>
				<StackPanel Orientation="Horizontal">
					<StackPanel toolkit:DataField.IsFieldGroup="True">
						<toolkit:DataField Label="First Name">
							<TextBox Text="{Binding FirstName, Mode=TwoWay}" />
						</toolkit:DataField>
						<toolkit:DataField Label="Last Name">
							<TextBox Text="{Binding LastName, Mode=TwoWay}" />
						</toolkit:DataField>
						<toolkit:DataField Label="Fax">
							<TextBox Text="{Binding Fax, Mode=TwoWay}" />
						</toolkit:DataField>
					</StackPanel>
					<StackPanel toolkit:DataField.IsFieldGroup="True">
						<toolkit:DataField Label="Business Name">
							<TextBox Text="{Binding BusinessName, Mode=TwoWay}" />
						</toolkit:DataField>
						<toolkit:DataField Label="Bio of Business">
							<TextBox Text="{Binding BusinessBio, Mode=TwoWay}" />
						</toolkit:DataField>
						<toolkit:DataField Label="Phone">
							<TextBox Text="{Binding Phone, Mode=TwoWay}" />
						</toolkit:DataField>
					</StackPanel>
				</StackPanel>
				<StackPanel toolkit:DataField.IsFieldGroup="True">
					<sdk:TabControl>
						<sdk:TabControl.Items>
							<sdk:TabItem Header="Test 1">
								<sdk:DataGrid MinHeight="200" HorizontalAlignment="Left" VerticalAlignment="Top">
									<sdk:DataGrid.ItemsSource>
										<l:Customers />
									</sdk:DataGrid.ItemsSource>
								</sdk:DataGrid>
							</sdk:TabItem>
						</sdk:TabControl.Items>
					</sdk:TabControl>
				</StackPanel>
			</StackPanel>
        </DataTemplate>
    </UserControl.Resources>
    <Grid x:Name="LayoutRoot" Background="White">
        <toolkit:DataForm Header="Data Entry Sample"
			AutoGenerateFields="False"
			ReadOnlyTemplate="{StaticResource DataFormStackPanelTemplate}"
			EditTemplate="{StaticResource DataFormStackPanelTemplate}"
			>
            <toolkit:DataForm.ItemsSource>
                <l:Customers />
            </toolkit:DataForm.ItemsSource>
        </toolkit:DataForm>
	</Grid>
</UserControl>

When we render this out, we get the what we would expect in the layout:

DataForm using a StackPanel with Master Detail layout

So what am missing in the Grid template? The problem is that I have only defined two Column definitions with their value set to “Auto”. All we need to do is add another Column definition with its width set to “*”. The following Grid template shows how to remedy this issue:

<UserControl x:Class="SilverlightApplication2.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400"
    xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
    xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit"
    xmlns:l="clr-namespace:SilverlightApplication2.Models"
    >
    <UserControl.Resources>
		<DataTemplate x:Key="DataFormGridTemplate">
			<Grid>
				<Grid.ColumnDefinitions>
					<ColumnDefinition Width="Auto" />
					<ColumnDefinition Width="Auto" />
					<ColumnDefinition Width="*" />
				</Grid.ColumnDefinitions>
				<Grid.RowDefinitions>
					<RowDefinition Height="Auto"/>
					<RowDefinition Height="Auto"/>
					<RowDefinition Height="Auto"/>
					<RowDefinition Height="*"/>
				</Grid.RowDefinitions>
				<toolkit:DataField Label="First Name" Grid.Column="0" Grid.Row="0">
					<TextBox Text="{Binding FirstName, Mode=TwoWay}" />
				</toolkit:DataField>
				<toolkit:DataField Label="Last Name" Grid.Column="0" Grid.Row="1">
					<TextBox Text="{Binding LastName, Mode=TwoWay}" />
				</toolkit:DataField>
				<toolkit:DataField Label="Business Name" Grid.Column="1" Grid.Row="0">
					<TextBox Text="{Binding BusinessName, Mode=TwoWay}" />
				</toolkit:DataField>
				<toolkit:DataField Label="Bio of Business" Grid.Column="1" Grid.Row="1">
					<TextBox Text="{Binding BusinessBio, Mode=TwoWay}" />
				</toolkit:DataField>
				<toolkit:DataField Label="Fax" Grid.Column="0" Grid.Row="2">
					<TextBox Text="{Binding Fax, Mode=TwoWay}" />
				</toolkit:DataField>
				<toolkit:DataField Label="Phone" Grid.Column="1" Grid.Row="2">
					<TextBox Text="{Binding Phone, Mode=TwoWay}" />
				</toolkit:DataField>

                		<sdk:TabControl Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="3">
                    			<sdk:TabControl.Items>
                        			<sdk:TabItem Header="Test 1">
                            				<sdk:DataGrid MinHeight="200" 
								HorizontalAlignment="Left" 
								VerticalAlignment="Top">
                                				<sdk:DataGrid.ItemsSource>
                                    					<l:Customers />
                                				</sdk:DataGrid.ItemsSource>
                            				</sdk:DataGrid>
			                        </sdk:TabItem>
		                    </sdk:TabControl.Items>
                		</sdk:TabControl>
			</Grid>
		</DataTemplate>
    </UserControl.Resources>
    <Grid x:Name="LayoutRoot" Background="White">
        <toolkit:DataForm Header="Data Entry Sample"
			AutoGenerateFields="False"
			ReadOnlyTemplate="{StaticResource DataFormGridTemplate}"
			EditTemplate="{StaticResource DataFormGridTemplate}"
            >
            <toolkit:DataForm.ItemsSource>
                <l:Customers />
            </toolkit:DataForm.ItemsSource>
        </toolkit:DataForm>
	</Grid>
</UserControl>

So I added a new Column definition and I also updated the ColumnSpan of the TabControl from “2” to “3”. That it! Let’s take a look at what the output would be:

DataForm using a Grid with Master Detail adjusted layout

So hopefully you can see some of the areas that you need to be aware of when you start making your layout a little advanced.

Note: It is worth noting that the StackPanel approach with the IsFieldGroup attribute is better in my opinion because it will also constrain your TabStop of your controls to follow the contraints of the group and then move to another. I have found that if I get my Grid layout mixed up, that my TabStops go crazy. This is easy to fix but I find that the grouping is sometimes easier.

Hope this helps…

Problems customizing the layout of a DataForm using a Grid – Part II

July 22, 2010 1 comment

I had a great comment from my good friend Karl Shifflett yesterday pointing out that if I would only put in “Auto” or a fixed size in the Width and Height of my Column and Row definitions, the DataForm would like as expected using the Grid.

Note: We will use the same object model that was presented in the last post.

Let’s review what I originally put and then see how it looks with a little more attention to the Column and Row definitions:

<UserControl x:Class="SilverlightApplication2.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400"
    xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
    xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit"
    xmlns:l="clr-namespace:SilverlightApplication2.Models"
    >
    <UserControl.Resources>
		<DataTemplate x:Key="DataFormGridTemplate">
			<Grid>
				<Grid.ColumnDefinitions>
					<ColumnDefinition />
					<ColumnDefinition />
				</Grid.ColumnDefinitions>
				<Grid.RowDefinitions>
					<RowDefinition />
					<RowDefinition />
					<RowDefinition />
				</Grid.RowDefinitions>
				<toolkit:DataField Label="First Name" Grid.Column="0" Grid.Row="0">
					<TextBox Text="{Binding FirstName, Mode=TwoWay}" />
				</toolkit:DataField>
				<toolkit:DataField Label="Last Name" Grid.Column="0" Grid.Row="1">
					<TextBox Text="{Binding LastName, Mode=TwoWay}" />
				</toolkit:DataField>
				<toolkit:DataField Label="Business Name" Grid.Column="1" Grid.Row="0">
					<TextBox Text="{Binding BusinessName, Mode=TwoWay}" />
				</toolkit:DataField>
				<toolkit:DataField Label="Bio of Business" Grid.Column="1" Grid.Row="1">
					<TextBox Text="{Binding BusinessBio, Mode=TwoWay}" />
				</toolkit:DataField>
				<toolkit:DataField Label="Fax" Grid.Column="0" Grid.Row="2">
					<TextBox Text="{Binding Fax, Mode=TwoWay}" />
				</toolkit:DataField>
				<toolkit:DataField Label="Phone" Grid.Column="1" Grid.Row="2">
					<TextBox Text="{Binding Phone, Mode=TwoWay}" />
				</toolkit:DataField>
			</Grid>
		</DataTemplate>
    </UserControl.Resources>
    <Grid x:Name="LayoutRoot" Background="White">
        <toolkit:DataForm Header="Data Entry Sample"
			AutoGenerateFields="False"
			ReadOnlyTemplate="{StaticResource DataFormGridTemplate}"
			EditTemplate="{StaticResource DataFormGridTemplate}"
            >
            <toolkit:DataForm.ItemsSource>
                <l:Customers />
            </toolkit:DataForm.ItemsSource>
        </toolkit:DataForm>
	</Grid>
</UserControl>

Like in the last post, my template produces the following output:

DataForm Grid Template

Now let’s just add a little more detail to the Column and Row definitions:

<UserControl x:Class="SilverlightApplication2.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400"
    xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
    xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit"
    xmlns:l="clr-namespace:SilverlightApplication2.Models"
    >
    <UserControl.Resources>
		<DataTemplate x:Key="DataFormGridTemplate">
			<Grid>
				<Grid.ColumnDefinitions>
					<ColumnDefinition Width="Auto" />
					<ColumnDefinition Width="Auto" />
				</Grid.ColumnDefinitions>
				<Grid.RowDefinitions>
					<RowDefinition Height="Auto"/>
					<RowDefinition Height="Auto"/>
					<RowDefinition Height="Auto" />
				</Grid.RowDefinitions>
				<toolkit:DataField Label="First Name" Grid.Column="0" Grid.Row="0">
					<TextBox Text="{Binding FirstName, Mode=TwoWay}" />
				</toolkit:DataField>
				<toolkit:DataField Label="Last Name" Grid.Column="0" Grid.Row="1">
					<TextBox Text="{Binding LastName, Mode=TwoWay}" />
				</toolkit:DataField>
				<toolkit:DataField Label="Business Name" Grid.Column="1" Grid.Row="0">
					<TextBox Text="{Binding BusinessName, Mode=TwoWay}" />
				</toolkit:DataField>
				<toolkit:DataField Label="Bio of Business" Grid.Column="1" Grid.Row="1">
					<TextBox Text="{Binding BusinessBio, Mode=TwoWay}" />
				</toolkit:DataField>
				<toolkit:DataField Label="Fax" Grid.Column="0" Grid.Row="2">
					<TextBox Text="{Binding Fax, Mode=TwoWay}" />
				</toolkit:DataField>
				<toolkit:DataField Label="Phone" Grid.Column="1" Grid.Row="2">
					<TextBox Text="{Binding Phone, Mode=TwoWay}" />
				</toolkit:DataField>
			</Grid>
		</DataTemplate>
    </UserControl.Resources>
    <Grid x:Name="LayoutRoot" Background="White">
        <toolkit:DataForm Header="Data Entry Sample"
			AutoGenerateFields="False"
			ReadOnlyTemplate="{StaticResource DataFormGridTemplate}"
			EditTemplate="{StaticResource DataFormGridTemplate}"
            >
            <toolkit:DataForm.ItemsSource>
                <l:Customers />
            </toolkit:DataForm.ItemsSource>
        </toolkit:DataForm>
	</Grid>
</UserControl>

Now we get the output that we would normally expect:

DataForm using a Grid with Column and Row definitions

So it looks like you can use either a Grid or StackPanel to manage your layout. We shall see….

Stay tuned for the next post and let’s see if we can solve my next opportunity.

Problems customizing the layout of a DataForm using a Grid.

July 22, 2010 1 comment

The DataForm is a pretty powerful control. It comes built with a lot of functionality that you don’t need to write multiple times. One of the things I do a lot with the DataForm is override the ReadOnly and Edit templates. In this post I am going to show a simple model class that would represent a Customer object and collection. I will then go into the using the AutoGeneration=”True” attribute of the DataForm. Finally, I will walk you through two paths of customizing the look and feel of the DataForm. The first path seemed to me to be the better of the two but as we look at the output we will quickly realize that the latter is by far the better.

Okay so lets first examine the data object we will be using in your example:

namespace DataFormSample.Models
{
    public class Customer
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string BusinessName { get; set; }
        public string BusinessBio { get; set; }
        public string Fax { get; set; }
        public string Phone { get; set; }
    };
    public class Customers : ObservableCollection<Customer>
    {
        public Customers()
        {
            Customer c = new Customer()
            {
                FirstName = "George",
                LastName = "Washington",
                BusinessName = "Washington Mutual",
                BusinessBio = "This company specializes in watching your money.",
                Phone = "8005551212",
                Fax = "8005551213"
            };
            this.Add(c);
            c = new Customer()
            {
                FirstName = "Abraham",
                LastName = "Lincoln",
                BusinessName = "Lincoln Cabins",
                BusinessBio = "Good lodging for good folk.",
                Phone = "8005558100",
                Fax = "8005558101"
            };
            this.Add(c);

        }
    };
}

As you can see from the source code, I am exposing two classes. The first class is just a simple data transfer object with the name of Customer. The other class is a sample hydrated ObservableCollection that will act as the ItemsSource of the DataForm. You can see that I have added two records.

We will now look at the XAML required to get this class wired up to a DataForm with the AutoGenerateFields attribute set to “True”.

<UserControl x:Class="SilverlightApplication2.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400"
    xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
    xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit"
    xmlns:l="clr-namespace:SilverlightApplication2.Models"
    >
    <Grid x:Name="LayoutRoot" Background="White">
        <toolkit:DataForm Header="Data Entry Sample"
                          AutoGenerateFields="True">
            <toolkit:DataForm.ItemsSource>
                <l:Customers />
            </toolkit:DataForm.ItemsSource>
        </toolkit:DataForm>
	</Grid>
</UserControl>

When the sample appliation is run the output looks like this:

DataForm with AutoGenerateFields='True'

As you can see, the DataForm is great for generating simple admin screens. It doesn’t really look like something that you would want to throw in front of a client though.

Let’s look at the next set of approaches that will have the AutoGenerateFields attribute set to “False”.

The first example of XAML involves using a Grid for managing the layout in a DataForm:

<UserControl x:Class="SilverlightApplication2.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400"
    xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
    xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit"
    xmlns:l="clr-namespace:SilverlightApplication2.Models"
    >
    <UserControl.Resources>
		<DataTemplate x:Key="DataFormGridTemplate">
			<Grid>
				<Grid.ColumnDefinitions>
					<ColumnDefinition />
					<ColumnDefinition />
				</Grid.ColumnDefinitions>
				<Grid.RowDefinitions>
					<RowDefinition />
					<RowDefinition />
					<RowDefinition />
				</Grid.RowDefinitions>
				<toolkit:DataField Label="First Name" Grid.Column="0" Grid.Row="0">
					<TextBox Text="{Binding FirstName, Mode=TwoWay}" />
				</toolkit:DataField>
				<toolkit:DataField Label="Last Name" Grid.Column="0" Grid.Row="1">
					<TextBox Text="{Binding LastName, Mode=TwoWay}" />
				</toolkit:DataField>
				<toolkit:DataField Label="Business Name" Grid.Column="1" Grid.Row="0">
					<TextBox Text="{Binding BusinessName, Mode=TwoWay}" />
				</toolkit:DataField>
				<toolkit:DataField Label="Bio of Business" Grid.Column="1" Grid.Row="1">
					<TextBox Text="{Binding BusinessBio, Mode=TwoWay}" />
				</toolkit:DataField>
				<toolkit:DataField Label="Fax" Grid.Column="0" Grid.Row="2">
					<TextBox Text="{Binding Fax, Mode=TwoWay}" />
				</toolkit:DataField>
				<toolkit:DataField Label="Phone" Grid.Column="1" Grid.Row="2">
					<TextBox Text="{Binding Phone, Mode=TwoWay}" />
				</toolkit:DataField>
			</Grid>
		</DataTemplate>
    </UserControl.Resources>
    <Grid x:Name="LayoutRoot" Background="White">
        <toolkit:DataForm Header="Data Entry Sample"
			AutoGenerateFields="False"
			ReadOnlyTemplate="{StaticResource DataFormGridTemplate}"
			EditTemplate="{StaticResource DataFormGridTemplate}"
            >
            <toolkit:DataForm.ItemsSource>
                <l:Customers />
            </toolkit:DataForm.ItemsSource>
        </toolkit:DataForm>
	</Grid>
</UserControl>

This time when we run the application, the output looks like this:

DataForm Grid Template

Clearly something is wrong with the way I wrote that DataTemplate.

Update: It turns out that this is not at all a problem with the DataForm. It is merely an issue with my Grid definition. Please see Part II for further clarification.

Let’s take a look at the DataTemplate when it is outside of the DataForm:

<UserControl x:Class="SilverlightApplication2.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400"
    xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
    xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit"
    xmlns:l="clr-namespace:SilverlightApplication2.Models"
    >
    <UserControl.Resources>
		<DataTemplate x:Key="DataFormGridTemplate">
			<Grid>
				<Grid.ColumnDefinitions>
					<ColumnDefinition />
					<ColumnDefinition />
				</Grid.ColumnDefinitions>
				<Grid.RowDefinitions>
					<RowDefinition />
					<RowDefinition />
					<RowDefinition />
				</Grid.RowDefinitions>
				<toolkit:DataField Label="First Name" Grid.Column="0" Grid.Row="0">
					<TextBox Text="{Binding FirstName, Mode=TwoWay}" />
				</toolkit:DataField>
				<toolkit:DataField Label="Last Name" Grid.Column="0" Grid.Row="1">
					<TextBox Text="{Binding LastName, Mode=TwoWay}" />
				</toolkit:DataField>
				<toolkit:DataField Label="Business Name" Grid.Column="1" Grid.Row="0">
					<TextBox Text="{Binding BusinessName, Mode=TwoWay}" />
				</toolkit:DataField>
				<toolkit:DataField Label="Bio of Business" Grid.Column="1" Grid.Row="1">
					<TextBox Text="{Binding BusinessBio, Mode=TwoWay}" />
				</toolkit:DataField>
				<toolkit:DataField Label="Fax" Grid.Column="0" Grid.Row="2">
					<TextBox Text="{Binding Fax, Mode=TwoWay}" />
				</toolkit:DataField>
				<toolkit:DataField Label="Phone" Grid.Column="1" Grid.Row="2">
					<TextBox Text="{Binding Phone, Mode=TwoWay}" />
				</toolkit:DataField>
			</Grid>
		</DataTemplate>
    </UserControl.Resources>
    <Grid x:Name="LayoutRoot" Background="White">
        <ContentControl Content="{Binding Customer}"
			ContentTemplate="{StaticResource DataFormGridTemplate}">
            <ContentControl.DataContext>
                <l:CustomerSample />
            </ContentControl.DataContext>
        </ContentControl>
	</Grid>
</UserControl>

When run we get this output which looks more like what I would have expected:

Grid Template

So is there something inherently wrong with the DataForm? It took me some time to stop staring at my DataTemplate and start examing what the documentation showed for building custom layout for the DataForm.

It turns out that the following DataTemplate example is the best suited for the DataForm:

<UserControl x:Class="SilverlightApplication2.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400"
    xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
    xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit"
    xmlns:l="clr-namespace:SilverlightApplication2.Models"
    >
    <UserControl.Resources>
        <DataTemplate x:Key="DataFormStackPanelTemplate">
            <StackPanel Orientation="Horizontal">
                <StackPanel toolkit:DataField.IsFieldGroup="True">
                    <toolkit:DataField Label="First Name">
                        <TextBox Text="{Binding FirstName, Mode=TwoWay}" />
                    </toolkit:DataField>
                    <toolkit:DataField Label="Last Name">
                        <TextBox Text="{Binding LastName, Mode=TwoWay}" />
                    </toolkit:DataField>
                    <toolkit:DataField Label="Fax">
                        <TextBox Text="{Binding Fax, Mode=TwoWay}" />
                    </toolkit:DataField>
                </StackPanel>
                <StackPanel toolkit:DataField.IsFieldGroup="True">
                    <toolkit:DataField Label="Business Name">
                        <TextBox Text="{Binding BusinessName, Mode=TwoWay}" />
                    </toolkit:DataField>
                    <toolkit:DataField Label="Bio of Business">
                        <TextBox Text="{Binding BusinessBio, Mode=TwoWay}" />
                    </toolkit:DataField>
                    <toolkit:DataField Label="Phone">
                        <TextBox Text="{Binding Phone, Mode=TwoWay}" />
                    </toolkit:DataField>
                </StackPanel>
            </StackPanel>
        </DataTemplate>
    </UserControl.Resources>
    <Grid x:Name="LayoutRoot" Background="White">
        <toolkit:DataForm Header="Data Entry Sample"
			AutoGenerateFields="False"
			ReadOnlyTemplate="{StaticResource DataFormStackPanelTemplate}"
			EditTemplate="{StaticResource DataFormStackPanelTemplate}"
			>
            <toolkit:DataForm.ItemsSource>
                <l:Customers />
            </toolkit:DataForm.ItemsSource>
        </toolkit:DataForm>
	</Grid>
</UserControl>

When run, we get this output as expected:

DataForm StackPanel Template

So the secret is in the sauce! Well not really it is actually a little attached property that tells the StackPanel that it is in a FieldGroup. Once you have that in place, you should be able to author your custom DataForm layouts to your heart’s desire.

Note: It may seem like this is an intuitive problem but I was certain that I was doing something wrong with my Grid and it took me way too long to solve this. I personally lean towards using the Grid as a carpentar would lean toward this hammer.

Hope this helps you and keeps you from any frustrations that I have already had! 🙂

WCF RIA Services – An entity with the same identity already exists in this EntitySet.

July 16, 2010 3 comments

WCF RIA Services is pretty powerful and does a lot for you when it comes to quickly building business applications. I came across something interesting today when I was working with a client.

For this post, I am going to be focusing on WCF RIA Services in conjunction with the EntityFramework. It turns out that if you have designed your tables with identities and you have set your seed for the table to be zero (0), then you will have problems right after your first record has been created and saved to the database.

The following is a screen shot of a given table in SQL Server with the identity seed set at zero (0):

Identity Seed

The moment you try to create a subsequent record, you will get the following error:

InValidOperationException was unhandled by user code: An entity with the same identity already exists in this EntitySet.

The reason for this is that RIA Services tries to created a new record that has an identity of zero (0) and as soon as you try and add it to the underlying collection it throws an exception since a record with that value already exists.

In WCF RIA Services, I don’t believe there is a way to change the default behavior for when a new record is inserted. It looks like it follows whatever datatype is defined as the identity column that in the table. So if the column is defined as an integer than the default value would be zero (0).

I believe I remember being able to bypass this issue in ADO.NET with DataSets with the ability to define what the default value would be for adding a new record.

More than anything else, I wanted you to be aware of a possible exception that may not intuitively makes sense at first but then becomes clear once you see the data. You may get tricked into thinking that your system is working if you have an empty table and insert your first record. This will work perfectly fine since it will insert a record with the identity value being zero (0). The moment you try to add an additional record you will get the exception mentioned above.

I would like to stress that for most scenarios you should not need be concerned unless your team has designed your tables with the seed of your identity columns to be zero (0) instead of one (1). In SQL Server 200X, the default value for the seed of an integer identity is one (1).

Hope this helps to prevent any confusion. Also, if anyone knows how to rememdy this problem please let me know.

Posting source code on my blog

I had a request from a reader as to how they could post sample code in response to an article I had written. I thought this was an excellent question and it can be hard to find the right answer when all you want to do is post your question.

The following is a quick example of posting a code snippet for XAML which is actually XML. If you want to submit XAML in a post or comment then you must wrap it with the following tag:

XAML snippet

It will then look like this once rendered:

<TextBox Text="Hello World" />

There are many other language targets. I use these common ones:

• csharp
• vb
• sql
• xml

Refer to this link for other targets as well.

Hope that helps….

Categories: English Tags: , , , , , ,

Microsoft MVP

July 1, 2010 2 comments

Just wanted to let you know that I received a Microsoft MVP award. I am very excited and honored to receive such a prestigious award and want to thank all my readers for their support. I also want to thank all of the local supporters who have come out to hear me speak here in the Charlotte area.

This is a great honor and I will try my best to continue to earn it moving forward.

Categories: English