Silverlight 4 Business Application Part 4 od n


Implementation of the DBNavigation control in Silvelright 4

naslovThis is 4th part of the series of Silverlight Business Application development, which I am writing. Today we will try to implement DBNavigator control.

With Silverlight 4 and RIA services you can develop full business application with backend SQL database on the similar way as you can do in Windows Forms and Windows Presentation Foundation. In the previous posts we have seen how easy connect database to your Silverlight application, and also how to use some patterns in Silvelright aplication like MVVM.
I this post we will see how to implement Database Navigation control like BindingNavigator from Windows Forms. On the other hand we will also see how to extend functionality of the existing Silverlight control by developing custom control derived from existing one, as well as the procedure how to create Silverlight User control.

Our Tutorial will start from the previous blog post, so you need to download source code sample, and start our today’s tutorial. When you download source code, open it in Visual Studio 2010.

 

  • Right click on the solution and chose  Add->New  Project
  • Select Silvelright Class Library project template, give it the name SLCustomCtrl, and click OK button.

sl1

Now that you have the new Silverlit Class Library project in your solution, you have to add reference to your main Silverlight project.

  • Right click on References of theSLDemoPart2 project,  and chose Add->Reference, click Project Tab in the new dialog, and chose SLCustomCtrl project.

Implementation of Custom Control

If you want to extent functionality from the existing Silverlight control you have to add the new Silverlight Templated Control, and starting extend the new functionality from the existing one.

  • Right click on the SLCustomCtrl project, chose Add->New Item, and choose Silverlight Templated Control, name it SLDBNavigator.cs, and hit Add button.

sl2Open SLDBNavigator.cs and put the following source code:

public class DBNavigationBaseCtrl : Grid
{
    public event RoutedEventHandler AddNew;
    public event RoutedEventHandler DeleteCurrent;
    public event RoutedEventHandler DomainDataChanged;

    public DBNavigationBaseCtrl()
    {

    }
    public DomainDataSource DomainData
    {
        get { return (DomainDataSource)GetValue(DomainDataProperty); }
        set
        {
            SetValue(DomainDataProperty, value);
            OnDomainDataChanged(new RoutedEventArgs());

        }
    }

    private void OnDomainDataChanged(RoutedEventArgs e)
    {
        if (DomainDataChanged != null)
            DomainDataChanged(new object(),e);
    }

    public static readonly DependencyProperty DomainDataProperty =
        DependencyProperty.Register("DomainData", typeof(DomainDataSource), typeof(DBNavigationBaseCtrl), new PropertyMetadata(null));
    public bool IsCustomDelete
    {
        get { return (bool)GetValue(IsCustomDeleteProperty); }
        set { SetValue(IsCustomDeleteProperty, value); }
    }

    public static readonly DependencyProperty IsCustomDeleteProperty =
        DependencyProperty.Register("IsCustomDelete", typeof(bool), typeof(bool), new PropertyMetadata(false));

    protected void OnEventAddNew(RoutedEventArgs e)
    {
        if (AddNew != null)
            AddNew(new object(), e);
    }
    protected void OnEventDeleteCurrent(RoutedEventArgs e)
    {
        if (DeleteCurrent != null)
            DeleteCurrent(new object(), e);
    }
}

Implementation of the previous source code contains the three Routed Event Handlers, and two properties. The source code is very simple so you can see very quickly what’s going on in the source code.

Implementation of User Control

Now that we have base custom control for manipulation database tables and views, we need to implement custom Silvelright control derived from it  to expose implemented properties and events from the base class in to XML.

  • Right click on SLCustmCtrls project, chose Add->New Item, select Silverlight User Control, name it DBNavigatorCtrl.xaml, and click Add button.

sl3

Implementation is achieved with putting  several buttons in to controls and subscribe to corresponded click events. The implementation of the DBNavigationCtrl is in the following two listing:

<!--DB Navigator-->
    <StackPanel Margin="2" Orientation="Horizontal" HorizontalAlignment="Center" >
        <Button Content="&lt;|" Height="Auto" Name="btnFirst"  Width="30" Click="btnFirst_Click" />
        <Button Content="&lt;" Height="Auto"  Name="btnPrev"   Width="30" Click="btnPrev_Click" />
        <TextBlock Width="70" Name="textCurrentItem" Text="" TextAlignment="Center" VerticalAlignment="Center"></TextBlock>
        <Button Content="&gt;" Height="Auto"  Name="btnNext"  Width="30" Click="btnNext_Click" />
        <Button Content="|&gt;" Height="Auto" Name="btnLast"  Width="30" Click="btnLast_Click" />
        <Button Content="+" Height="Auto"  Name="btnAdd"  Width="30" Click="btnAdd_Click" />
        <Button Content="-" Height="Auto" Name="btnDelete"  Width="30" Click="btnDelete_Click" />
    </StackPanel>
public partial class DBNavigatorCtrl : DBNavigationBaseCtrl
{
    public DBNavigatorCtrl()
    {
        InitializeComponent();
        this.DomainDataChanged += new RoutedEventHandler(DBNavigatorCtrl_Loaded);

    }

    void DBNavigatorCtrl_Loaded(object sender, RoutedEventArgs e)
    {
        if (DomainData != null)
        {
            DomainData.DataView.CurrentChanged += (ss, ee) =>
            {
                var dds = ss as DomainDataSourceView;

                if (dds != null)
                    textCurrentItem.Text = (dds.IndexOf(dds.CurrentItem) + 1).ToString() + "/" + dds.Count.ToString();
                else
                    textCurrentItem.Text = "0/0";
            };
        }
    }

    private void btnFirst_Click(object sender, RoutedEventArgs e)
    {

        if (DomainData != null)
            DomainData.DataView.MoveCurrentToFirst();
    }

    private void btnPrev_Click(object sender, RoutedEventArgs e)
    {
        if (DomainData != null)
            if (DomainData.DataView.CurrentPosition > 0)
                DomainData.DataView.MoveCurrentToPrevious();
    }

    private void btnNext_Click(object sender, RoutedEventArgs e)
    {
        if (DomainData != null)
            if (DomainData.DataView.CurrentPosition + 1 < DomainData.DataView.Count)
                DomainData.DataView.MoveCurrentToNext();
    }

    private void btnLast_Click(object sender, RoutedEventArgs e)
    {
        if (DomainData != null)
            DomainData.DataView.MoveCurrentToLast();
    }

    private void btnAdd_Click(object sender, RoutedEventArgs e)
    {
        if (DomainData == null)
            return;
        RoutedEventArgs e1 = new RoutedEventArgs();
        OnEventAddNew(e1);
    }

    private void btnDelete_Click(object sender, RoutedEventArgs e)
    {
        if (DomainData == null)
            return;
        if (IsCustomDelete)
        {
            RoutedEventArgs e1 = new RoutedEventArgs();
            OnEventDeleteCurrent(e1);
            return;
        }
        if (MessageBox.Show("Confirm delete by clicking the OK button",
                              "Deleting a record ...", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
        {
            DomainData.DataView.Remove(DomainData.DataView.CurrentItem);
        }
    }
}

Using DBNavigaorCtrl in Silvelright project

When we have DBNavigatorCtrl control, it is very easy to use it. Just put the control in to XAML, and in code behind assign it to domain data source of the Main Page.
Now select the main Silverlight project,and open MainPage.XAML, from the toolbox windows select DBNavigationCtrl item and drag and drop to mainpage, similar as picture shows below. If you don’t see DBNavigationCtrl in the ToolBox you have Rebuild the solution.

sl4

The result of our tutorial looks likes on the following picture:

sl5

The source code for this tutorial can be downloaded from here.
Implementation of the DBNavigation control in Silvelright 4

Advertisement

Silverlight 4 Business Application Part 3 of n


Implementation of the Login Dialog in Silverlight application by using MVVM pattern

imageIn the third article, of the series of the Silvelright Business application development, I will present Login dialog implementation by applying  MVVM pattern. Problems looks very simple but if you want to implement in MVVM fashion you could encounter some problems. MVVM pattern became very popular in Silverlight and WPF application development and it seams to be standard development pattern. More information about the pattern can be found on various blogs, internet sites and forums.  One of the first and the best article about MVVM patern is MSND article about MVVM patern by Josh Smith and it can be found here.

This tutorial assume that you know basic principles of the MVVM pattern as well as Silverlight application.

In tis tutorial we will use the MVVM toolkit the implementation of the MVVM pattern developed by Laurent Bugnion, which you can download at http://mvvmlight.codeplex.com/. Before we start the tutorial, download the toolkit and install it as it decribed on the codeplex site.

The idea of the Login dialog, presented here, not depends of the MVVM light toolkit, so it can be easily implemented with other MVVM pattern, like PRISM and others.

Start Visual Studio 2010, and select File->New –>Project, select Silverlight Application in the same way we implemented in Part 2. Instead of Silverlight Aplication, select MvvmLight (SL4) template as picture below shows. After we choose the template, and click OK, Visual Studio designer created Silverlight application which support MVVM pattern.

The picture below shows The New Project dialog window:

image

As you can see Visual Studio created Silverlight application, but not the ASP.NET web application project. For this tutorial we don’t need it.

image

The picture above shows project files and how files are arranged in the project. The folder ViewModel contains the ViewModels implementations. Lets create View folder, it will contain Views implementation.

Implementation of MainView and MainViewModel

MainViewContent will be our main content for the Silverlight application. It will be shown after we logged in.

1. Right Click on the recently created View folder, and choose Add->New Item

2. Select Silverlight User Control and give it name MainViewContent.xaml

image

3. In the XAML file put the following code:

<Grid x:Name="LayoutRoot" Background="White">
        <TextBlock Text="MAIN CONTENT OF THE SILVERLIGHT APPLICATION"
                   HorizontalAlignment="Center"
                   VerticalAlignment="Top"
                   FontSize="16" FontFamily="Arial Black" />
</Grid>

Implementation is simple. Just TextBlox with some text.

Now we need to create MainViewModelContent:

4. Right Click on the ViewModel folder, and choose Add->New Class

5. Name it MainViewModelContent.cs

Implementation of the MainViewModelContent is in the following listing:

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using GalaSoft.MvvmLight;

namespace SLPart3MvvmLoginDialog.ViewModel
{
    public class MainViewModelContent : ViewModelBase
    {

    }
}

The implementation is empty cause we want the empty view model without interaction with the view .

Implementation of LoginView and LoginViewModel

Similar as previous we create LoginView.Xaml and LoginViewModel.cs.

Xaml implementation of the LoginView contains controls and layout depicted in the first picture of the article. Here is the main xaml code:

<Border BorderThickness="1" BorderBrush="Black">
        <Grid x:Name="LayoutRoot1" Background="White">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="120" />
                <ColumnDefinition Width="120" />
                <ColumnDefinition Width="*" />
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="40" />
                <RowDefinition Height="30" />
                <RowDefinition Height="28" />
                <RowDefinition Height="28" />
                <RowDefinition Height="40" />
                <RowDefinition Height="28" />
                <RowDefinition Height="*" />
            </Grid.RowDefinitions>

            <Rectangle x:Name="rectangle1" Stroke="Black" StrokeThickness="1" Fill="#FFDE8836" Grid.ColumnSpan="4" />
            <TextBlock Grid.Row="2" x:Name="textBlock2" Text="User Name:" Padding="5" HorizontalAlignment="Right"
                       VerticalAlignment="Center" Grid.Column="1" Margin="0,9" />
            <TextBlock x:Name="textBlock3" Text="Password:" Grid.Row="3" Padding="5" HorizontalAlignment="Right"
                       VerticalAlignment="Center" Grid.Column="1" Margin="0,9" />
            <TextBox Grid.Column="2" Grid.Row="2" x:Name="textBox1" Margin="2" Text="{Binding UserName, Mode=TwoWay}" />
            <PasswordBox Grid.Column="2" Grid.Row="3" x:Name="passwordBox1" Margin="2"  Password="{Binding Password, Mode=TwoWay}"/>

            <Button Content="Cancel" Grid.Column="1" Grid.Row="5" x:Name="radButton1" Margin="5,2" />
            <Button Content="Login" x:Name="radButton2" Grid.Column="2" Grid.Row="5" Margin="5,2" >
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="Click">
                        <mvvmcmd:EventToCommand Command="{Binding LoginCommand, Mode=OneWay}"
                                CommandParameter="{Binding Main, Source={StaticResource Locator}}"/>
                    </i:EventTrigger>
                </i:Interaction.Triggers>
            </Button>
            <TextBlock x:Name="textBlock1" Text="Login Dialog" VerticalAlignment="Center" HorizontalAlignment="Center"
                       Grid.ColumnSpan="2" Margin="10,5,5,12" Grid.Column="1" FontFamily="Portable User Interface"
                       FontSize="20" FontStretch="SemiCondensed" FontWeight="SemiBold" Foreground="Black"/>
        </Grid>
</Border>

The main part of this xaml code above is that the MainViewModel is passed as a parameter of the Login button EventToCommand, and if the login is correct, the LoginModelView change IsLoggedIn property to true. Then main page switch the visibility property of the LoginView to Collapsed, and MainContentView to Visible.

Implementation of the LoginViewModel.cs is show on the next listing:

//Constructor
public LoginViewModel()
  {
    this.LoginCommand = new RelayCommand<object>(this.OnLogging, this.CanLogging);
  }
//Wnen the user click Login button in LoginView
private void OnLogging(object arg)
  {
   var vm = arg as MainViewModel;
   if (vm == null)
      return;

   //proces of logging
   vm.IsLogged = true;
   }

private bool CanLogging(object arg)
   {

     return true;
   }

ModelView coresponding classes is always derived from the ModelViewBase.

Putting all together in MainPage and ManViewModel

Now, when you implemented Login  and MainContent, we need put these objects in to MainPage. The MainPage is responsible of showing and hiding these views.

Implementation of the MainPage.xaml

<Grid x:Name="LayoutRoot">

        <my:MainViewContent Visibility="{Binding Main.IsLogged,
                      ConverterParameter=mainView,
                      Converter={StaticResource MainPageBoolLoginToVisibilityConverter1},
                      Source={StaticResource Locator}}"/>
            <my:LoginView Visibility="{Binding Main.IsLogged,
            ConverterParameter=loginView,
            Converter={StaticResource MainPageBoolLoginToVisibilityConverter1},
            Source={StaticResource Locator}}" HorizontalAlignment="Center" VerticalAlignment="Center" />
    </Grid>

Implementation of the MainViewModel

public const string IsLoggedPropertyName = "IsLogged";
private bool _islogged;
public bool IsLogged
 {
   get
    {
      return _islogged;
    }
   set
    {
      if (value != _islogged)
      {
        _islogged = value;
        RaisePropertyChanged(IsLoggedPropertyName);
      }
    }
  }

public MainViewModel()
  {
    if (IsInDesignMode)
    {
     // Code runs in Blend --> create design time data.
    }
    else
    {
     // Code runs "for real"
    }
}

As you can see we implemented IsLogged property, which is the switch between Login and MainViewContent. With BoolToVisibilityConverter class, we were implemented changing visibility of the Views. The converter class is in the source code of the project attached with this tutorial.
Now at the end we have to implement LoginVieModel and MainContentViewModel in to Locator class.
The implementation is very simple and you can see it in the sourcecode project. Now run the application and clik the Login button, The MainContentView appears.

Summary

This article present the simple technique you can easily implement in your Silverlight application with full fashion of the MVVM pattern.

The source code can be download from  here.

Silverlight 4 Business Application Part 2 od n


Connecting database to your Silverlight 4 Business application

The second article in series of the Silverlight Business application will cover Entity Framework and WFC RIA service, the two components by which you can achieve manipulation of database from your Silverlight Application.  A lot of blogs, articles and books you can find to learn about Silverlight Entity Framework and WFC RIA services. The blogs and book I would like to stress at the moment are http://jesseliberty.com/ the Silverlight and Windows Phone 7 Blog, and The book about Silverlight “Silverlight 4 UNLEASHED” by Laurent Bugnion . He is writing blog also at http://blog.galasoft.ch .

So, for now I will present how you can create Silverlight project from scratch, so you don’t need to use Visual Studio Template for Silverlight Business application. The reason is simple, if you don’t want to use ASP.Net generated database for users and logins, and want to use your own way of login the following tutorial is for you.

The requirements for the demo are the same as in previous post

1. First of all, Run Visual Studio 2010 any version (Ultimate, Professional or Express ), and chose File->New Project. The following picture shows New Project dialog and Silverlight Template projects.

image

2. Chose Silverlight from the left list box of project types, and select Silverlight  Application from the Silverlight project templates. Name the project as SLDemoPart2, and the Solution name let it be LSDemoPart2Solution.

After you click on OK button, another dialog appears, and you need to set some addition options about our Silverlight application. Check all option as picture show below, and click OK  button again.

image

Now, we have Silverlight empty project created within Visual Studio 2010. Every Silverlight application have to be hosted in Web page, so we need to create ASP.NET Application and host out Silverlight application in it.When the Visual Studio finished its jobs we can see the two projects: The Silverlight project we created, and ASP.NET Web application project  Visual Studio created for hosting our application.

Now that we have starting projects, we can start mapped our NorthWind database. If you need NorthWind database, please see previous post, where you can find the way you need to download NorthWind database.

Lets create Entity Framework Model and map the two common tables from the NorthWInd database: Orders and OrdersDetails.

3. Right Click on SLDemoPArt2.Web asp.net project, select Add –>New Item and chose ADO.NET Entity Data Model, name it the NorthWindModel.admx and click OK.

4. Follow the EF Wizard and define connection to your SQL Server database, and import mentioned tables. At the end finish the wizard window. When the VS 2010 finish rebuild the solution.The picture below shows the result:

image

We define our database model, but in this stage we cannot use it in Silverlight application, cause it is server component not client. To resolve this, we need such a service which can expose our database model to the client and make call to the database. RIA Services is component that you can achieve this. So lets create Domain data class one of the  component of the RIA Services.

5. Right Click on SLDemoPArt2.Web ASP.NETt project, select Add –>New Item and chose Domain Service Class . Type DDSNorthWindClient.cs in name edit box and click Add button.

Previously, if you rebuild your project now you can see the following dialog with Order and OrderDetails mapped tables. If you don’t see the tables, you have to rebuild the project.

image

Check the tables as well as check Enable Editing column, cause we want to read and modify the  data from the database as well. Click OK button. Now we are ready to use the NorthWind database from our Silverlight application.

Some of you may wonder, we didn’t touch Silverlight project, but how can we get our tables. The generated classes of the Domain Data Class, Visual Studio is exported to our Silverlight project in to Generated_Code folder, which is not included in to Silverlight project.

To prove that, click on Silverlight project, click on Show All Files toolbar of the the Solution Explorer Window, and we can see it. Try to open folder as well and generated file. You can see domain data class implementation in to Silverlight project.

image

Now that we convinced in to Domain Data Class implementation, we can use it in our Silverlight project.

6. Open MainPage.xaml in to XAML designer of the Silverlight project.

7. Chose main menu  Data->Show Data Sources, and we can see our tables within Data Sources Windows.

8. Drag  Orders table from Data Source Window in to MainPage XAML designer and what we can see?

image

We see completely the same technique like in WinForms application. Its Amassing !

Run the project and you can see Orders from your database in to your browser!

image

Source code for the tutorial can be downloaded from here.

Silverlight 4 Business Application Part 1 of n


Logins, Users, Roles, Page Content

Currently I am trying to learn Silverlight Business Application development, and during this phase I will try to post some interesting tips and tricks on which I will encounter. I hope you will find some of a code usefull.

In this post I will show how to create starting silverlight business application skeleton, and how you can manipulate with users, roles and content within Silverlight application. As you already know, Silverlight BA uses ASP.NET database model in order to display or hide business data via RIA Services. So, if you want to develop SL application with several modules and each module can access different set of users, you need to handle with users and rolls similar as in ASP.NET application. In this post we will make demo with three pages. Each page will be opened with different users, and admin can open all pages. The screenshot below shows the SL application.

So lets start VS 2010, and choose File New Project, and in list choose Silverlight Business Application see picture below:

Name the new project SLBAPart1 and choose OK button. The VS designer will do a lot of works for us in order to generate starter business application. VS designer generated the two page, completed login and user registration logic as well as database and RIA services. We will add another page called Product, and implementi another link button in mainpage.xaml (see picture below).

  1. To create the new Product.xaml page, right click on Views folder, and choose Add new item
  2. In opened dialog choose Silverlight Page name it Product and click OK.
  3. Add xaml code as depicted on the picture above.

When you run the application you can see the application similar as the first picture shows, which you can access all three pages. There is also “login” link button wich you can login as well as register a new user for SL application.

To define user membership in SL application, select SLBAPart1.Web project  and choose menu ASP.NET Configuration from the Project menu of Visual Studio 2010. Internet Explorer page shows content similar like picture below. Choose Security link button, and click on Creates and Manages roles. Define four roles like picture shows below.

Click Back button and create four users with corresponding roles. The final result of user defining is shown on picture below.

Each user has its own corresponding roles. When you use the attached sample pasword for each user is defined similar as for the first user “$user1user1“. Password for admin user is “$adminadmin“.

After we defined roles and users it is time to define content for each page. Open Product.xaml page from Visual Vtudio project, define content like picture below.

We have to define Public.xaml page which can be accessed if we not logged in. Similar to previous page creation define Public.xaml page, and put some text in it.

Next step in implementation is  prevent user to see content if it is not authorized. To implement that, we need to expand ContentFrame_Navigated event of the mainpage.xaml.cs.

private void ContentFrame_Navigated(object sender, NavigationEventArgs e)
{
     //Check to see if user has right to navigate
     if (!UserCanNavigate(e))
       return;

     foreach (UIElement child in LinksStackPanel.Children)
     {
         HyperlinkButton hb = child as HyperlinkButton;
         if (hb != null && hb.NavigateUri != null)
          {
            if (hb.NavigateUri.ToString().Equals(e.Uri.ToString()))
             {
                VisualStateManager.GoToState(hb, "ActiveLink", true);
             }
           else
            {
               VisualStateManager.GoToState(hb, "InactiveLink", true);
            }
         }
     }
}

When the user click for content ContentFrame_Navigated event fires up. Then UserCanNavigate method gets call. The implementation of this method is the following:

private bool UserCanNavigate(NavigationEventArgs sender)
{
    //if user is not authenticated show public content
    if (!WebContext.Current.User.IsAuthenticated)
    {
        ContentFrame.Source = new System.Uri("/Public", UriKind.RelativeOrAbsolute);
        return false;
    } //If the user is loged show only content on which is authorizated
    else
    {
        //If user is admin alow everithing
        if(WebContext.Current.User.IsInRole("AdminRols"))
            return true;
        //if user is in rol1 open Home content
        if (WebContext.Current.User.IsInRole("Rol1"))
        {
            ContentFrame.Source = new System.Uri("/Home", UriKind.RelativeOrAbsolute);
            return false;
        }//Similar to previous
        if (WebContext.Current.User.IsInRole("Rol2"))
        {
            ContentFrame.Source = new System.Uri("/About", UriKind.RelativeOrAbsolute);
            return false;
        }
        else
        {
            ContentFrame.Source = new System.Uri("/Product", UriKind.RelativeOrAbsolute);
            return false;
        }

    }
}

Build application and run. The picture below shows our application. If we try to navigate to any content before we LogedIn we always get the same public content. Depending on user information when we logged in ,we get coresponding content.

Thats all for now. We learned how we can manipulate with content and different user roles. Source code for this demo can be downloaded from here.