Archive

Archive for November, 2011

CodeFluent Entities and WPF: Master/Details

November 30, 2011 2 comments

This one is actually dead easy in WPF thanks to its advanced data-binding mechanism.  In this post, we’ll start from a simple ListBox listing all our contacts, which upon selection of one of its item, will display its details underneath.

Here’s the XAML:

<StackPanel Margin="10">
    <TextBlock FontWeight="bold" Margin="5">Contacts:</TextBlock>
    <ListBox Name="_contactsListBox" />
    
    <TextBlock FontWeight="bold" Margin="5,10,5,5">Details:</TextBlock>
    <StackPanel DataContext="{Binding ElementName=_contactsListBox, Path=SelectedItem}" Margin="5">
        <TextBlock>FirstName:</TextBlock>
        <TextBox Text="{Binding Path=FirstName}" />

        <TextBlock>LastName:</TextBlock>
        <TextBox Text="{Binding Path=LastName}" />
    </StackPanel>
</StackPanel>

As you can see in the code above, we’ve got a ListBox listing our contacts, and underneath a StackPanel containing a couple TextBlocks and TextBoxes which detail the selected contact. This StackPanel is data-bound to the SelectedItem of the Contact ListBox, so selecting a contact will automatically display its details underneath.

Here’s the code-behind (just a single line to load all contacts in our ListBox):

public MasterDetail()
{
    InitializeComponent();
    _contactsListBox.ItemsSource = ContactCollection.LoadAll();
}

Here’s the result:

image

CodeFluent Entities and WPF: Paging Data

November 29, 2011 1 comment

Surprisingly, WPF DataGrid and ListView controls don’t provide built-in support to page data, nonetheless you can implement it pretty easily as illustrated with the WPF Pager Control example provided by Microsoft and available here: http://cid-51b2fdd068799d15.office.live.com/self.aspx/.Public/Samples%5E_2010/20100929%5E_DataPagerForWPF.zip

The DataPager control is a simple stack panel with buttons allowing to navigate pages. As provided in the sample, pages are built when assigning the full collection of elements, and it exposes a CurrentPage property which other controls can bind to. Consequently, here’s our paged window:

<StackPanel> 
    <ListView ItemsSource="{Binding ElementName=_dataPager, Path=CurrentPage}"> 
        <ListView.View> 
            <GridView> 
                <GridView.Columns> 
                    <GridViewColumn Header="FirstName" Width="100" DisplayMemberBinding="{Binding FirstName}"/> 
                    <GridViewColumn Header="LastName" Width="100" DisplayMemberBinding="{Binding LastName}"/> 
                </GridView.Columns> 
            </GridView> 
        </ListView.View> 
    </ListView> 
    <local:DataPager x:Name="_dataPager" ItemsPerPage="4" /> 
</StackPanel>

And here’s the code-behind of our window:

public PagingData() 
{ 
    InitializeComponent();
    _dataPager.ItemsSource = ContactCollection.LoadAll(); 
}

As you can see once initialized, we’re assigning the complete collection of items to our DataPager control, and our ListView is bound to the CurrentPage property of the pager.

Note 1: To use actual pages of data from database, you’d have to change the DataPager control so it uses behind the scenes the PageLoadAll method with the proper page index and page sizes, instead of loading everything and creating pages.

Note 2: for this sample to work, we slightly modified the DataPager provided so it uses the IList type (implemented by CodeFluent Entities generated classes) instead of the ObservableCollection<object> type.

Here’s the result:

image image

CodeFluent Entities and WPF: Selecting Data

November 28, 2011 1 comment

Following our ASP.NET post series, this post starts a new one but this time in WPF Smile

Selecting data in a WPF application using CodeFluent Entities generated .NET classes, known as the Business Object Model (BOM), is very straightforward. There’s actually very little to do since the generated classes implement all .NET interfaces so developers get the best experience possible when building there UI: IEnumerable, IEnumerable<T>, IList, IList<T>,  ICollection, ICollection<T>, IBindingList, INotifyPropertyChanged, INotifyCollectionChanged, IRaiseItemChangedEvents, etc.

Therefore, to display a list of items in an ItemsControl all you have to do is is set the loaded collection as the ItemsSource of the control:

XAML:

<StackPanel>
    <StackPanel Orientation="Horizontal" Margin="0,5,0,5">
        <Button Name="_loadAllButton" Content="LoadAll" Click="OnLoadAllButtonClick" Width="100" Margin="20,5,20,5" />
        <Button Name="_clearAll" Content="Clear" Click="OnClearAllClick" Width="100" Margin="20,5,20,5" />
    </StackPanel>
    
    <ListBox Name="_contactsListBox" />
</StackPanel>

C#:

private void OnLoadAllButtonClick(object sender, RoutedEventArgs e)
{
    _contactsListBox.ItemsSource = ContactCollection.LoadAll();
}

private void OnClearAllClick(object sender, RoutedEventArgs e)
{
    _contactsListBox.ItemsSource = null;
}

This will display the following:

image

As you can see, if no data template is specified, the Entity Display Name is used which in our case is the FirstName property of our Contact entity.

If you want to display your contacts in the following format: “<LastName>, <FirstName>” you can define a data template such as this:

<ListBox Name="_contactsListBox">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding LastName}" FontWeight="Bold" />
                <TextBlock Text=", " />
                <TextBlock Text="{Binding FirstName}" />
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

Here’s the result:

image

CodeFluent Entities and ASP.NET Web Forms: Validation

November 25, 2011 2 comments

In this post we’ll see how to implement validation in a form, data bound to a CodeFluent Entities generated class. We’re going to start from the page created in the Inserting Data post, and we’ll replace the DetailsView with a simple validation-enabled ASP.NET FormView.

Client Validation

First, we’ll start by adding ASP.NET field validators to avoid unnecessary server calls. Here’s the code:

<asp:ObjectDataSource runat="server" ID="ContactDataSource" TypeName="ContactAdmin.Contact"
    DataObjectTypeName="ContactAdmin.Contact" SelectMethod="LoadByEntityKey" InsertMethod="Insert">
    <SelectParameters>
        <asp:QueryStringParameter Name="key" QueryStringField="key" DefaultValue="-1" />
    </SelectParameters>
</asp:ObjectDataSource>
<asp:FormView runat="server" DefaultMode="Insert" OnItemInserted="OnContactInserted"
    DataKeyNames="Id, RowVersion" DataSourceID="ContactDataSource">
    <InsertItemTemplate>
        <p>
            <asp:Label runat="server" Text="First Name" /><br />
            <asp:TextBox ID="FirstNameBox" runat="server" AutoCompleteType="FirstName" Text='<%# Bind("FirstName") %>' />
            <asp:RequiredFieldValidator runat="server" Display="Dynamic" ErrorMessage="Field required."
                ControlToValidate="FirstNameBox" ValidationGroup="InsertContact" />
            <br />
            <br />
            <asp:Label runat="server" Text="Last Name" /><br />
            <asp:TextBox ID="LastNameBox" runat="server" AutoCompleteType="LastName" Text='<%# Bind("LastName") %>' />
            <asp:RequiredFieldValidator runat="server" Display="Dynamic" ErrorMessage="Field required."
                ControlToValidate="LastNameBox" ValidationGroup="InsertContact" />
        </p>
        <asp:LinkButton ID="InsertButton" runat="server" Text="Create" CommandName="Insert"
            ValidationGroup="InsertContact" />
    </InsertItemTemplate>
</asp:FormView>
<p>
    <asp:Label ID="errorText" runat="server" ForeColor="Red" />
</p>

As you can see in the code sample above, we added two RequiredFieldValidator controls which ensure that each of our text boxes (FirstName and LastName) are filled when submitting the form. This way, if the form is incomplete, they’ll display the “Field required.” error message.

Here’s the result in action, if you click create with at least one empty field, no server call will be issued, and an error is shown to the user:

image

 

Server Validation

You can also set-up server-side validation. To do so in CodeFluent Entities, you can add one or several validation rules to your entity, on properties, or also extend the automatically generated Validate method with your own custom code using the OnBeforeValidate and/or OnAfterValidate licycle event rules.

As an example, we added a simple String Validation rule on the FirstName and LastName properties indicating that those properties cannot be null or empty, and cannot contain the ‘_’ character:

image

If you generate over your model, your Business Object Model will now enforce the following rule, and if ever you send a value with an invalid character to the server, it’ll now throw a CodeFluentValidationException. You’ll now need to handle it in your UI, and this is exactly what we’re doing by subscribing to the OnItemInserted event of the FormView. Here’s the event handler:

<script runat="server">    
    private void OnContactInserted(object sender, FormViewInsertedEventArgs e)
    {
        if (e.Exception == null || e.Exception.InnerException == null)
            return;

        CodeFluent.Runtime.CodeFluentValidationException vex = e.Exception.InnerException as CodeFluent.Runtime.CodeFluentValidationException;
        if (vex == null)
            return; // Do nothing

        errorText.Text = vex.MessageWithoutCode;
        e.ExceptionHandled = true;
        e.KeepInInsertMode = true;
        return;
    }
</script>

And here’s the result:

image

Note: the validation message can be localized and customized using messages in your model.

New Online Documentation Release: R15

November 23, 2011 Leave a comment

A new version (R15) of the product documentation was released!

This new version includes:

Additions:

Updates:

  • Blob Cache

As well as miscellaneous corrections

Interested in some extra articles? Comment this post and tell us what you’d like to see in the next release!

PS: if you receive 404 errors or if the TOC don’t show when browsing this new documentation version, please reset your browser cache.

Storing Custom Files In Your CodeFluent Entities Project

November 23, 2011 Leave a comment

By default a CodeFluent Entities project contains the following elements:

image

  • a Default surface, and its part “Default.Surface.cfp” containing layout information (shapes, positions, etc.)
  • the project part named by your default namespace (e.g. “MyApplication.cfp” in the example above) and which contains the definition of all your entities, properties, rules, forms, views, etc.

Projects can contain multiple surfaces and multiple parts, which can be added by clicking on the Surfaces and Parts folder of your project.

Folders in your CodeFluent Entities  project are virtual. If you open the corresponding project folder in Windows Explorer here’s what you’ll see:

image

  • The project file (<ProjectName>.cfxproj)
  • The parts (<DefaultNamespace>.cfp and the other ones you created)
  • The surface parts (Default.Surface.cfp and possibly the other ones you created)

CodeFluent Entities projects also contain a “Files” folder which can contain any extra-files. Drop files in your project folder, and then using Solution Explorer’s “Show All Files” button and “Include in project” option.

Extra-Feature:

  • If you place a CFP file in your project folder, including it to your project will add it to the Parts folder,
  • If you place a XML file in your project folder which contains a valid root project node, including it to your project will automatically add it to the Parts folder,
  • Other than that, any extra-file goes in the Files folder.

CodeFluent Entities and ASP.NET Web Forms: Master/Details

November 22, 2011 2 comments

In this post we’ll see how to set-up Master/Details pages declaratively using CodeFluent Entities-generated classes and database.

First, we’ll start by creating a page letting us display and edit a Contact instance. This one is pretty much like the “insert page” we created in our previous post:

<asp:ObjectDataSource runat="server" ID="ContactDataSource" 
        TypeName="ContactAdmin.Contact" DataObjectTypeName="ContactAdmin.Contact"
        SelectMethod="LoadByEntityKey" UpdateMethod="Save">
    <SelectParameters>
        <asp:QueryStringParameter Name="key" QueryStringField="key" DefaultValue="-1" />
    </SelectParameters>
</asp:ObjectDataSource> 

<asp:DetailsView runat="server" DataSourceID="ContactDataSource" AutoGenerateRows="false"
        DefaultMode="Edit" DataKeyNames="Id, RowVersion">
    <Fields>
        <asp:BoundField HeaderText="First Name" DataField="FirstName" />
        <asp:BoundField HeaderText="Last Name" DataField="LastName" />
        <asp:ButtonField CommandName="Update" Text="Save" ButtonType="Button" />
    </Fields>
</asp:DetailsView>

This page contains an object data source which if ever there’s an entity key specified in the url, it loads it from database, and the DetailsView control uses it as a data source. This page will be our details page.

Now our master page will simply list all Contact instances stored in database and allow end-users to view the details of one of them. Here’s how to do it:

<asp:ObjectDataSource runat="server" ID="ContactsDataSource" SelectMethod="LoadAll"
    TypeName="ContactAdmin.ContactCollection" DataObjectTypeName="ContactAdmin.Contact" />
    
<asp:GridView ID="GridView" runat="server" DataSourceID="ContactsDataSource" AutoGenerateColumns="False"
    DataKeyNames="EntityKey, RowVersion">
    <Columns>
        <asp:HyperLinkField Text="Details" DataNavigateUrlFields="EntityKey" DataNavigateUrlFormatString="EditContact.aspx?key={0}" />
        <asp:BoundField HeaderText="Id" DataField="Id" />
        <asp:BoundField HeaderText="First Name" DataField="FirstName" />
        <asp:BoundField HeaderText="Last Name" DataField="LastName" />
    </Columns>
</asp:GridView>

The code is just like our first “Selecting Data” post, with the tiny difference that we added a HyperLinkField control which is configured to navigate to our details page created before, and using the current entity key so the details page will display the selected instance.

Master.aspx:

image

Details.aspx?key=1:

image