Android Addicted Apps Creator

September 18, 2009

How to make a business rule in BLL and use it wisely

Filed under: WPF — alinberce @ 21:08
Tags: , , , , ,

Based on previous tutorial we will try to make a business rule for user name. The simplest rule possible is that the Username must not be empty. We must be able to check for this in the BLL and, in case of error, display a message in UI. Sounds simple ? Now let’s make it.

In this case it’s a simple rule, but just imagine that for our method GetUser(…) we can have many validations (Username must be at least 5 characters, Password can’t be blank… etc) so, after checks are being done a list of errors could appear, this means we must have possibility to store all errors and make them available to the UI. For achieving this purpose we’ll create a new Class called BusinessRule in which we will store some information regarding the failed checks:

public class BusinessRule
    {
        private String _RuleType;
        public String RuleType
        {
            get { return _RuleType; }
            set { _RuleType = value;}
        }

        private String _Message;
        public String Message
        {
            get { return _Message; }
            set { _Message = value; }
        }

        private String _Property;
        public String Property
        {
            get { return _Property; }
            set { _Property = value; }
        }

        public BusinessRule()
        {
        }

        public BusinessRule(String _RuleType, String _Message, String _Property)
        {
            RuleType = _RuleType;
            Message = _Message;
            Property = _Property;
        }
    } 

We could have different type of checks which will return different type of messages: Warnings, Errors or Info. This will be stored in RuleType. The message is pretty self explanatory, the message displayed on rule fail. The property will store the property name that failed the checks (Username in our case) and will help the UI to focus the problematic controls.

Now let’s get back to the userBo class and make some changes to use the BusinessRule class.

public List<BusinessRule> BrokenRules = new List<BusinessRule>();  

        public User GetUser(string UserName)
        {

            if (string.IsNullOrEmpty(UserName))
            {
                BrokenRules.Add(new BusinessRule("Error","User name cannot be empty","UserName"));
                BrokenRules.Add(new BusinessRule("Warning", "You have 3 more retries", "UserName"));
                BrokenRules.Add(new BusinessRule("Info", "User name has a minimum length of 5 characters", "UserName"));
            }

            if (BrokenRules.Count.Equals(0))
            {
               UserDO usrDO = new UserDO();
               return  usrDO.GetUser(UserName);
            }
            else
                return null;
        }

If check fails, all the errors will be added to the BrokenRules list. This list is Public, so it can be used by the UI.

Making the UI use the BrokenRules list

Imagine that a list of BrokenRules will be available for all classes in UserBO, so we’ll need to make a window and provide a datasource to it programatically. The layout of the window will be as follow:

image

<Window x:Class="NoiaUI.Message"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Message" Height="300" Width="300" WindowStartupLocation="CenterScreen">
    <Window.Resources>
        <CollectionViewSource x:Key="MessagesSource"/>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="auto"></RowDefinition>
            <RowDefinition></RowDefinition>
            <RowDefinition Height="auto"></RowDefinition>
        </Grid.RowDefinitions>
        <TextBlock Grid.Row="0" Text="Atentie" FontSize="14" Margin="5"/>
        <ListBox Name="lstMessages"  ItemsSource="{Binding Source={StaticResource MessagesSource}}" Grid.Row="1">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <Image Margin="5"  Source="{Binding Path=Image}" Stretch="Fill" Width="16" Height="16"/>
                        <TextBlock Margin="5" Text="{Binding Path=Message}"/>
                    </StackPanel>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ListBox>
        <Button Name="btnContinue" Grid.Row="2" MaxWidth="100" MaxHeight="25" Click="btnContinue_Click" Margin="4">Continue</Button>

    </Grid>
</Window>

We declare a CollectionViewSource as a Window Resource that will be the ItemsSource of the listbox. Here you can see something interesting, in the ItemTemplates I added a StackPanel in which we have 2 controls, a Image and a Textbloc. To make the window better looking, will add some icons for RuleTypes, it’s much nicer to see a Error icon instead of the text “Error”.

In the cs file we take care of everything

public partial class Message : Window
    {
        public Message()
        {
            InitializeComponent();
        }

        private class MessageFormat
        {
            public BitmapImage Image { get; set; }
            public string Message { get; set; }
            public string Property { get; set; }
        }

        public void SetMessagesSource(List<BusinessRule> lstMessages)
        {
            List<MessageFormat> finalMessage = new List<MessageFormat>();
            DirectoryInfo ImageDir = new DirectoryInfo(@"..\..\Images");

            foreach (BusinessRule br in lstMessages)
            {
                FileInfo fi = new FileInfo(@"..\..\Images\"+br.RuleType+".png");
                Uri uri = new Uri(fi.FullName);
                finalMessage.Add(new MessageFormat { Image = new BitmapImage(uri), Message=br.Message, Property=br.Property });
            }

            CollectionViewSource MessagesSource = (CollectionViewSource)this.Resources["MessagesSource"];
            MessagesSource.Source = finalMessage;

        }

        private void btnContinue_Click(object sender, RoutedEventArgs e)
        {
            this.Close();
        }
    }

A class, MessageFormat is used to store the ruleType as BitmapImage. A public methon, SetMessageSource, is used to read the image files, add the entire content to the finalMessage list and set the CollectionViewSource source. In this way, we instantiate the windows, call the SetMessageSource method and then display it on the screen.

Let’s see how to use it in real life enviroment. In the Login window, btnLogin click event will look like this:

private void btnLogin_Click(object sender, RoutedEventArgs e)
        {

            UserBO usrbo = new UserBO();
            User usr = usrbo.GetUser(txtUserName.Text);

            if (usr == null)
            {
                if (usrbo.BrokenRules.Count.Equals(0))
                {
                    MessageBox.Show("Wrong username");
                }
                else
                {
                    Message msg = new Message();
                    msg.SetMessagesSource(usrbo.BrokenRules);
                    msg.ShowDialog();
                }
            }
            else
                MessageBox.Show("Wellcome " + txtUserName.Text);
        }

Run it, don’t type anything, just press the login button. The window should look like this:

image

The app must not allow to continue until the BrokenRules list is empty. Furthermore, based on property field in list, we could set focus to controls that failed checks. I hope you enjoyed this tutorial. Until next time, Happy coding.

And of course  the video, this time in HD 😉

September 17, 2009

WPF N-Tier using Entity Framework

Filed under: WPF — alinberce @ 21:35
Tags: , ,

Noia development has begin with baby steps. Right now I am trying to make a application core that will support further changes very easy. Today we are going to learn how to make layer for application and how to make them communicate. As you’ve learned so far about me I won’t give many details and explanations, the main purpose is to get the result needed as fast as possible. This being said, let’s begin our tutorial.

Let’s start by creating a new solution called Noia. In this solution we will have 4 projects as follow:

  • NoiaDAL – represents the Data Access Layer. Project type Class Library
  • NoiaBLL – represents the Business Logic Layer. Project type Class Library
  • NoiaUI – will take care of User Interface layer. Project type WPF Application
  • NoiaEF – which will contain Entities. Project type Class Library

Also, we will make a new folder NoiaDB in which we will copy the NoiaDB.sdf (SQL Server CE database).

In order to make this layers communicate, we must create the references between them:

  • In NoiaUI create reference to NoiaEF
  • In NoiaBLL create references to NoiaDAL and NoiaEF
  • In NoiaUI create references to NoiaBLL and NoiaEF

In the NoiaED we will add a new item of type Ado.Net Entity Data Model named NoiaEntityModel.edmx. When ask the Model Content we will choose Generate from database and we’ll create a new connection string pointing to the NoiaDB.sdf file. The generated connection string will look like:

metadata=res://*/NoiaEntityModel.csdl|res://*/NoiaEntityModel.ssdl|res://*/NoiaEntityModel.msl;provider=System.Data.SqlServerCe.3.5;provider connection string="Data Source=C:\Noia\NoiaDB\NoiaDB.sdf"

After the model is generated we can see all the entities created. We will rename all the be singular. I don’t want to have a object Users, I want to have a object User. Also, in properties for each entity we will rename the Entity Set Name from UserSet to Users and so on, for all the entities that require it. At the end, it should look like this:

image

What I want to achieve in this tutorial is to be able to create a login screen and check if the user name provided by UI is valid or not. The information will travel between all layers forth and back. Please remember that each layer will have it’s unique characteristics and none of the layers will overlap.

NoiaDAL (Data Access Layer)

In DAL we will need to have a class for each entity we want to use. For our particular example we will add a new class and name it UserDO (from User Data Object). In this class we must have a method to search for a user based on the user named taped by the front user. In searching for the user we will use a Linq statement. Complete class code is:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NoiaEF;

namespace NoiaDAL
{
    public class UserDO
    {
        public User GetUser(string UserName)
        {
            NoiaDBEntities ne = new NoiaDBEntities();

            var usr = from u in ne.Users
                  where u.UserID == UserName
                  select u;

            return usr.FirstOrDefault();
        }
    }
}

In order to be able to use the Entities we must add a reference at the project to System.Data.Entities. This pretty much makes the job done in the DAL.

NoiaBLL (Business Logic Layer)

As in DAL, in here we will have another class for User, in this case it will be named UserBO (User business object). Because the UI layer must not access DAL directly, the BLL will be an intermediary, and after validations and checks, the BLL will decide if will ask the DAL for information or provide direct feedback to the UI if validations failed. Because validation is the scope of the next tutorial, the UserBo will only redirect the request to DAL. Again, we must add a reference at the project to System.Data.Entities.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NoiaDAL;
using NoiaEF;

namespace NoiaBLL
{
    public class UserBO
    {
        public User GetUser(string UserName)
        {
                UserDO usr = new UserDO();
                return usr.GetUser(UserName);
        }
    }
}

NoiaUI (User Interface Layer)

We will create the login window. It must contain two textboxes for user input (one for User name one for Password) and a Login button. Add a new Windows (WPF) in NoiaUI project and name it Login

<Window x:Class="Noia.Login"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Login" Width="370" Height="120" Background="#185d7c" WindowStartupLocation="CenterScreen">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="Auto"/>
        </Grid.ColumnDefinitions>
        <Label Name="lblUserName" Grid.Row="1" Grid.Column="0" Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="5" >User name</Label>
        <Label Name="lblPassword" Grid.Row="2" Grid.Column="0" Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Center" Margin="5">Password</Label>
        <TextBox Name="txtUserName" Grid.Row="1" Grid.Column="1" MinWidth="200" Margin="5"></TextBox>
        <PasswordBox Name="txtPassword" Grid.Row="2" Grid.Column="1" Margin="5"></PasswordBox>
        <Button Name="btnLogin"  Click="btnLogin_Click" Grid.Row="2" Grid.Column="2" MaxWidth="50" MaxHeight="25">Login</Button>
    </Grid>
</Window>

The login button click event must communicate with the BLL and ask for data.

  private void btnLogin_Click(object sender, RoutedEventArgs e)
        {
            UserBO usrbo = new UserBO();

            User usr = usrbo.GetUser(txtUserName.Text);

            if (usr == null)
               MessageBox.Show("Wrong username");
            else
                MessageBox.Show("Wellcome " + txtUserName.Text);
        }

There are a few more things that need to be done: add a reference at the project to System.Data.Entities. Copy the App.Config file from NoiaEF to NoiaUI because we need the connection string. Set in App.xaml the startup window to login

<Application x:Class="NoiaUI.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    StartupUri="Login.xaml">
    <Application.Resources>

    </Application.Resources>
</Application>

Run it and see the result… it should work like a charm

image

Next time we shall see how to make a business rule in BLL and how to send error list from BLL to UI. It will be interesting.

P.S. Very important note: it seems that there is a problem for Linq to Entity access the SQL CE Database file with the existing SP1. In order to make things work, you must uninstall SQL CE SP1 and install this hot fix: http://support.microsoft.com/kb/958478

And the videos… as you can hear I was pretty tired when making them, so a lot of ufffs and offfs 🙂

September 11, 2009

NOIA – Planning and analyze. The beginning…

Filed under: WPF — alinberce @ 20:03
Tags: , ,

    What does NOIA stand for ? NOIA is “Not Another Invoice Application”. Pretty explanative what it should do: a application for invoices and stocks which will deal with input and output, in a small level CRM, goods stock and payments.  The reason why I mention this is because while developing it, I will make a chain of tutorials describing each important step in development. As I will learn I will share knowledge.

Technical specifications

     Because it’s not either big size or complex the platform used for development will be Visual C# 2008 Express edition. The data sources will be two, SQL Server 2008 Express Edition and SQL Server Compact Edition 3.5. Those two database systems are suitable for most cases, for small to medium clients.

Thank you Microsoft for providing a free tools to developers.

Architecture

The architecture will be layered designed, so long live the n-tier. Main goals to achieve will be:

  • Changing one layer of the system should have a minimal impact over the rest of the layers. This will help maintenance, bug fixing and unit testing. It also makes the architecture more flexible
  • Unrelated components should be loosely coupled
  • Separation between User interface, Business objects and Database

image

Each layer will be developed as follow:

– Presentation Layer: Windows Presentation Foundation (WPF) and C#

– Business Objects Layer: C#

– Data Access Layer: C# and Linq   The database will contain only a few tables needed for fresh start (like Users, Companies etc.). The rest of the tables will be added as the development progresses.

The interface

     I am planning to make a extremely user friendly interface. I give a big deal about user pleasing, this makes the app sale. Just imagine that by my design flaw, a user must lose one second each time he saves an invoice (a freaking’ message box maybe), for a number of 3000 invoices/month there will be a lose of time around 1 hour. As I am a big fan of n-tier architecture, also, I am a big fan of outlook interface. This means the interface will have a very outlookish style. Plus some other enhancements as they come along.

image

         As a friend used to say, I’ve made a map to the user so it won’t get lost. This isn’t really true, but the workflow could help and it would be easier to go to a certain operation if remembered visually. The New/Save/Delete won’t be as in the image, there will be a combo box so that the user could select company or date or stuff like this. The upper image is a WIP (Work in Progress) so it can be changed. It may seem very colored now, at the end will have a more professional look.

This was a pretty boring post, even if I tried to make it as short as possible. If you have any suggestions please send them.

Until next time we “meet”, Happy coding.

P.S. – I would like to take a moment and THANK Cristi for help, support and ideas. So, thank you man.