Thursday, August 5, 2010

Silverlight Image Gallery Using MVVM and SQL Server Database

sample

Hi guys, here I am posting a new article for creating a Image Gallery Using MVVM and SQL Server Database.

Create new Silverlight project in Visual studio (I am using silverlight 3.0 with Visual studio 2008 with SP1). My project name is MVVM_WCF_Silverlight_ImageUpload.

Server Side Implementation

Create a table named image in one of your SQL Server database using the following script:

   1: CREATE TABLE [dbo].[image](
   2:     [imagesid] [int] IDENTITY(1,1) NOT NULL,
   3:     [imagecontent] [image] NULL,
   4:     [imagename] [varchar](50) NULL,
   5:  CONSTRAINT [PK_image] PRIMARY KEY CLUSTERED 
   6: (
   7:     [imagesid] ASC
   8: )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
   9: ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

Create three folders in MVVM_WCF_Silverlight_ImageUpload project


  1. Data
  2. Services
  3. DTO

Add a LINQ to SQL Classes named ImageDataClasses.dbml in your data folder.

Go to Server explorer and connect to the database containing table image.

Once it is connected, drag and drop the image table to the ImageDataClasses.dbml work space.

Add a WCF service file to your Services folder, I have given WCFImageService.svc as name.

Go to your web.config file and change binding="wsHttpBinding" to binding="basicHttpBinding"

I have defined a custom basicHttpBinding for my project add this code inside binding, following is the code for that:



   1: <basicHttpBinding>
   2:     <binding name="imageBinding" maxReceivedMessageSize="2000000" maxBufferSize="2000000">
   3:         <readerQuotas maxArrayLength="2000000" maxStringContentLength="2000000"/>
   4:     </binding>
   5: </basicHttpBinding>

Change the binding configuration as follows in your endpoint tag



   1: <endpoint address="" binding="basicHttpBinding" bindingConfiguration="imageBinding" contract="MVVM_WCF_Silverlight_ImageUpload.Web.Services.IWCFImageService">

I have defined a Data Type Object class called Picture.



   1: public class Picture
   2: {
   3:     public int ImageID { get; set; }
   4:     public string ImageTitle { get; set; }
   5:     public byte[] ImageStream { get; set; }
   6: }

Following is the code for my service project:

WCFImageService.cs



   1: public class WCFImageService : IWCFImageService
   2: {
   3:     public bool Upload(Picture imageFile)
   4:     {
   5:         using (ImageDataClassesDataContext db = new ImageDataClassesDataContext())
   6:         {
   7:             db.images.InsertOnSubmit(new image { imagecontent = imageFile.ImageStream, imagename = imageFile.ImageTitle });
   8:             try
   9:             {
  10:                 db.SubmitChanges();
  11:             }
  12:             catch (Exception ex)
  13:             {
  14:                 db.SubmitChanges();
  15:             }
  16:             return true;
  17:         }
  18:     }
  19:  
  20:     public List<Picture> ListImages()
  21:     {
  22:         using (ImageDataClassesDataContext db = new ImageDataClassesDataContext())
  23:         {
  24:             List<image> selectedImages = db.images.ToList<image>();
  25:             List<Picture> pictures = new List<Picture>();
  26:             if (selectedImages.Count > 0)
  27:                 foreach (image img in selectedImages)
  28:                     pictures.Add(new Picture { ImageID = img.imagesid, ImageTitle = img.imagename, ImageStream = img.imagecontent.ToArray() });
  29:             return pictures;
  30:         }
  31:     }
  32:  
  33:     public Picture Download(int imageId)
  34:     {
  35:         using (ImageDataClassesDataContext db = new ImageDataClassesDataContext())
  36:         {
  37:             image selectedImage = db.images.Where(r => r.imagesid == imageId) as image;
  38:             return new Picture { ImageID = selectedImage.imagesid, ImageTitle = selectedImage.imagename, ImageStream = selectedImage.imagecontent.ToArray() };
  39:         }
  40:     }
  41: }

WCFImageService.svc.cs



   1: [ServiceContract]
   2: public interface IWCFImageService
   3: {
   4:     [OperationContract]
   5:     bool Upload(Picture imageFile);
   6:  
   7:     [OperationContract]
   8:     List<Picture> ListImages();
   9:  
  10:     [OperationContract]
  11:     Picture Download(int imageId);
  12: }

Client Side Implementation


If you are done with the server side add the service reference in the silverlight project.

Right click on add reference => Add Service Reference => Click on Discover, Once the service is listed, select the service and give a name for your reference. I have given WCFImageService.

As I am using MVVM pattern in my project, Lets create 3 folders in Silverlight project


  1. Converters
  2. Model
  3. ViewModel
  4. View

In Converters you will be having one value converter classes for converting the bytes to bitmap image.

Following is the code for ImageConverter.cs



   1: public class ImageConverter : IValueConverter
   2: {
   3:    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
   4:    {
   5:        BitmapImage bi = new BitmapImage();//create bitmap image
   6:        if (value != null)
   7:        {
   8:            if (value != null)
   9:                bi.SetSource(new MemoryStream((Byte[])value));
  10:  
  11:            return bi;
  12:        }
  13:        return bi;
  14:    }
  15:  
  16:    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  17:    {
  18:        throw new NotImplementedException("PropertyViewer does not use ConvertBack.");
  19:    }
  20: }

In model create a model class file called Picture.cs. Following is the code for my model class:



   1: public class Picture : INotifyPropertyChanged
   2: {
   3:     #region Private Variables
   4:     private string _imageTitle;
   5:     private byte[] _imageStream;
   6:     #endregion
   7:  
   8:     #region Public Properties
   9:     public int ImageID { get; set; }
  10:     public string ImageTitle
  11:     {
  12:         get
  13:         {
  14:             return _imageTitle;
  15:         }
  16:         set
  17:         {
  18:             _imageTitle = value;
  19:             NotifyPropertyChanged("ImageTitle");
  20:         }
  21:     }
  22:     public byte[] ImageStream
  23:     {
  24:         get
  25:         {
  26:             return _imageStream;
  27:         }
  28:         set
  29:         {
  30:             _imageStream = value;
  31:             NotifyPropertyChanged("ImageStream");
  32:         }
  33:     }
  34:     public ICommand Click { get; set; }
  35:     #endregion
  36:  
  37:     #region INotifyPropertyChanged Members
  38:  
  39:     public event PropertyChangedEventHandler PropertyChanged;
  40:     private void NotifyPropertyChanged(String propertyName)
  41:     {
  42:         if (PropertyChanged != null)
  43:         {
  44:             PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
  45:         }
  46:     }
  47:  
  48:     #endregion
  49: }

In View Model folder create a class called ViewModelRTV.cs, here you can implement your logic for populating the tree from the database. Following is the code for the view model class:



   1: public class ViewModelImageUpload : INotifyPropertyChanged
   2: {
   3:     private Picture _pictureFile;
   4:     public Picture PictureFile
   5:     {
   6:         get
   7:         {
   8:             return _pictureFile;
   9:         }
  10:         set
  11:         {
  12:             _pictureFile = value;
  13:             NotifyPropertyChanged("PictureFile");
  14:         }
  15:     }
  16:  
  17:     private Picture _selectedItem;
  18:     public Picture SelectedItem
  19:     {
  20:         get
  21:         {
  22:             return _selectedItem;
  23:         }
  24:         set
  25:         {
  26:             _selectedItem = value;
  27:             NotifyPropertyChanged("SelectedItem");
  28:         }
  29:     }
  30:  
  31:     private ObservableCollection<Picture> _pictureList;
  32:     public ObservableCollection<Picture> PictureList
  33:     {
  34:         get
  35:         {
  36:             return _pictureList;
  37:         }
  38:         set
  39:         {
  40:             _pictureList = value;
  41:             NotifyPropertyChanged("PictureList");
  42:         }
  43:     }
  44:  
  45:     public ICommand CommandClick { get; set; }
  46:     public ICommand Click { get; set; }
  47:  
  48:     public ViewModelImageUpload()
  49:     {
  50:         PictureFile = new Picture
  51:         {
  52:             ImageTitle = "Image Not Selected",
  53:             ImageStream = null
  54:         };
  55:         PictureList = new ObservableCollection<Picture>();
  56:         WCFImageService.WCFImageServiceClient client = new WCFImageService.WCFImageServiceClient();
  57:         client.ListImagesCompleted += client_ListImagesCompleted;
  58:         client.ListImagesAsync();
  59:         CommandClick = new DelegateCommand<object>(argument =>
  60:                        {
  61:                            switch (argument.ToString())
  62:                            {
  63:                                case "Browse":
  64:                                    BrowseFile();
  65:                                    break;
  66:                                case "Upload":
  67:                                    UploadFile();
  68:                                    break;
  69:                                default:
  70:                                    break;
  71:                            }
  72:                        });
  73:     }
  74:  
  75:     void client_ListImagesCompleted(object sender, MVVM_WCF_Silverlight_ImageUpload.WCFImageService.ListImagesCompletedEventArgs e)
  76:     {
  77:         PictureList = new ObservableCollection<Picture>();
  78:         if (e.Result != null)
  79:         {
  80:             ObservableCollection<WCFImageService.Picture> lstPics = e.Result as ObservableCollection<WCFImageService.Picture>;
  81:             foreach (WCFImageService.Picture pic in lstPics)
  82:                 PictureList.Add(new Picture
  83:                     {
  84:                         ImageID = pic.ImageID,
  85:                         ImageTitle = pic.ImageTitle,
  86:                         ImageStream = pic.ImageStream,
  87:                         Click = new DelegateCommand<object>(obj =>
  88:                                 {
  89:                                     if (obj != null)
  90:                                         SelectedItem = obj as Picture;
  91:                                 })
  92:                     });
  93:             if (PictureList != null && PictureList.Count > 0)
  94:                 SelectedItem = PictureList[0];
  95:         }
  96:     }
  97:  
  98:  
  99:  
 100:  
 101:     private void BrowseFile()
 102:     {
 103:         OpenFileDialog openFileDialog = new OpenFileDialog { Filter = "JPEG files|*.jpg" };
 104:         if (openFileDialog.ShowDialog() == true)
 105:         {
 106:             using (Stream stream = (Stream)openFileDialog.File.OpenRead())
 107:             {
 108:                 byte[] bytes = new byte[stream.Length];
 109:                 stream.Read(bytes, 0, (int)stream.Length);
 110:                 PictureFile.ImageTitle = openFileDialog.File.Name;
 111:                 PictureFile.ImageStream = bytes;
 112:             }
 113:         }
 114:     }
 115:  
 116:     private void UploadFile()
 117:     {
 118:         WCFImageService.WCFImageServiceClient client = new WCFImageService.WCFImageServiceClient();
 119:         client.UploadCompleted += client_UploadCompleted;
 120:         client.UploadAsync(new WCFImageService.Picture { ImageTitle = PictureFile.ImageTitle, ImageStream = PictureFile.ImageStream });
 121:     }
 122:  
 123:     void client_UploadCompleted(object sender, WCFImageService.UploadCompletedEventArgs e)
 124:     {
 125:         if (e.Error == null)
 126:         {
 127:             WCFImageService.WCFImageServiceClient client = new WCFImageService.WCFImageServiceClient();
 128:             client.ListImagesCompleted += client_ListImagesCompleted;
 129:             client.ListImagesAsync();
 130:             MessageBox.Show("File Uploaded!!!");
 131:         }
 132:     }
 133:  
 134:     #region INotifyPropertyChanged Members
 135:  
 136:     public event PropertyChangedEventHandler PropertyChanged;
 137:     private void NotifyPropertyChanged(String propertyName)
 138:     {
 139:         if (PropertyChanged != null)
 140:         {
 141:             PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
 142:         }
 143:     }
 144:     #endregion
 145: }

In View create a Silverlight user control named UCImage.xaml, here you will the define the UI for your application in XAML. Following is the xaml code for the View:



   1: <UserControl x:Class="MVVM_WCF_Silverlight_ImageUpload.View.UCImage"
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
   4:     xmlns:commands="clr-namespace:Microsoft.Practices.Composite.Presentation.Commands;assembly=Microsoft.Practices.Composite.Presentation"
   5:     xmlns:converter="clr-namespace:MVVM_WCF_Silverlight_ImageUpload.Converters"
   6:     Width="730" Height="370">
   7:     <UserControl.Resources>
   8:         <converter:ImageConverter x:Key="ImageConverter" />
   9:     </UserControl.Resources>
  10:     <Grid x:Name="LayoutRoot" Background="White">
  11:         <Border Padding="5" Background="#FFD6D6D6" CornerRadius="5" OpacityMask="Black" BorderThickness="1">
  12:             <StackPanel Orientation="Horizontal">
  13:                 <Grid>
  14:                     <Grid.ColumnDefinitions>
  15:                         <ColumnDefinition></ColumnDefinition>
  16:                         <ColumnDefinition></ColumnDefinition>
  17:                     </Grid.ColumnDefinitions>
  18:                     <StackPanel Grid.Column="0">
  19:                         
  20:                             <ListBox ItemsSource="{Binding Path=PictureList, Mode=TwoWay}" 
  21:                      SelectedItem="{Binding Path=SelectedItem, Mode=TwoWay}"
  22:                      ScrollViewer.VerticalScrollBarVisibility="Auto"
  23:                                      MaxHeight="310"
  24: >
  25:                                 <ListBox.ItemTemplate>
  26:                                     <DataTemplate>
  27:                                         <Button commands:Click.Command="{Binding Click}" 
  28:                                 commands:Click.CommandParameter="{Binding}"
  29:                                 Background="Transparent" 
  30:                                 BorderThickness="0">
  31:                                             <Border Padding="5" Background="#FF0D253D" CornerRadius="5" OpacityMask="Black" BorderThickness="1" Width="170" >
  32:                                                 <Border.Effect>
  33:                                                     <DropShadowEffect BlurRadius="7" Opacity="0.5" ShadowDepth="3"/>
  34:                                                 </Border.Effect>
  35:                                                 <StackPanel Orientation="Horizontal">
  36:                                                     <Border Padding="5" Background="#FF8AB8E6" CornerRadius="5" OpacityMask="Black" BorderThickness="1">
  37:                                                         <Image Width="50" Height="40" 
  38:                        Source="{Binding Path=ImageStream, Mode=TwoWay, Converter={StaticResource ImageConverter}}" 
  39:                        Stretch="Uniform" 
  40:                        HorizontalAlignment="Center" ></Image>
  41:                                                     </Border>
  42:                                                     <TextBlock Text="{Binding Path=ImageTitle, Mode=TwoWay}" 
  43:                                                                HorizontalAlignment="Center" 
  44:                                                                VerticalAlignment="Center" 
  45:                                                                Foreground="White" 
  46:                                                                FontWeight="Bold" 
  47:                                                                FontSize="10.667"></TextBlock>
  48:                                                 </StackPanel>
  49:                                             </Border>
  50:                                         </Button>
  51:                                     </DataTemplate>
  52:                                 </ListBox.ItemTemplate>
  53:                             </ListBox>
  54:                         
  55:                     </StackPanel>
  56:                     <StackPanel Orientation="Vertical" Grid.Column="1">
  57:                         <StackPanel Orientation="Vertical">
  58:                             <Border Padding="5" Background="#FFFFFF" CornerRadius="5" OpacityMask="Black" BorderThickness="1" BorderBrush="#FF5D5D5D">
  59:                                 <Image Width="500" Height="300" 
  60:                        Source="{Binding Path=SelectedItem.ImageStream, Mode=TwoWay, Converter={StaticResource ImageConverter}}" 
  61:                        Stretch="Uniform" 
  62:                        HorizontalAlignment="Center" ></Image>
  63:                             </Border>
  64:                             <TextBlock Text="{Binding Path=SelectedItem.ImageTitle, Mode=TwoWay}" 
  65:                                                                HorizontalAlignment="Center" 
  66:                                                                Foreground="#000000" 
  67:                                                                FontWeight="Bold" 
  68:                                                                FontSize="10.667">
  69:                             </TextBlock>
  70:                         </StackPanel>
  71:                         <StackPanel Orientation="Horizontal">
  72:                             <Button Content="Browse File" 
  73:                         commands:Click.Command="{Binding CommandClick}" 
  74:                         commands:Click.CommandParameter="Browse" 
  75:                         Width="100" Margin="5,5,5,5"></Button>
  76:                             <Button Content="Upload File" 
  77:                         commands:Click.Command="{Binding CommandClick}" 
  78:                         commands:Click.CommandParameter="Upload" 
  79:                         Width="100" Margin="5,5,5,5"></Button>
  80:                         </StackPanel>
  81:                     </StackPanel>
  82:                 </Grid>
  83:             </StackPanel>
  84:         </Border>
  85:     </Grid>
  86: </UserControl>

Include the UCImage.xaml in MainPage.xaml. Following is the code for MainPage.xaml:



   1: <UserControl x:Class="MVVM_WCF_Silverlight_ImageUpload.MainPage"
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   4:     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
   5:     xmlns:local="clr-namespace:MVVM_WCF_Silverlight_ImageUpload.View"
   6:     mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">
   7:   <Grid x:Name="LayoutRoot">
   8:         <local:UCImage></local:UCImage>
   9:     </Grid>
  10: </UserControl>

Initialize your view model and set the data context of view in MainPage.xaml.cs. Following is the code for MainPage.xaml.cs:



   1: ViewModelImageUpload _vmiu;
   2: public MainPage()
   3: {
   4:     _vmiu = new ViewModelImageUpload();
   5:     InitializeComponent();
   6:     this.DataContext = _vmiu;
   7: }

Press F5………. You are done!!!!


Click here to find the complete source code for this article.


If you find any problem, please feel free to ask questions!!!


Thanks Guys!!!

8 comments:

Ashok said...

Hi Anilal,

I am using VS 2010 (Silverlight 4) and I think it should work. This is very nice project. I will let you know if there are any problems.

I want to create a Silverlight Website to show Images (Fading effects) like in main page of http://janoostudio.com/

Thanks a lot,
Ashok

Ashok said...
This comment has been removed by the author.
Ashok said...

I could not make it work on VS2010. After clicking Browse button, I did not see an image.
It kept on saying waiting for localhost.

Thanks anyway
Ashok

Anilal Sambasivan said...

Ashok,

I have run the application in VS 2010, You should create the table image and change the database name and machine name in config file in web project.

Thanks
Anilal Sambasivan

阿發仔 said...

The content is very rich. Thanks for your help

Unknown said...

Hi, probably our entry may be off topic but anyways, I have been surfing around your blog and it looks very professional. It’s obvious you know your topic and you appear fervent about it. I’m developing a fresh blog plus I’m struggling to make it look good, as well as offer the best quality content. I have learned much at your web site and also I anticipate alot more articles and will be coming back soon. Thanks you.

ASC Coding

Unknown said...

Hi,
I use this code.it's rely helpful.but when i press
browse button or upload button i didn't get any result.can you please explain the reason.

Catherine Higgins said...

Thanks for the awesome share
Hi we at Colan Infotech Private Limited , a company which is Situated in US and India, will provide you best service and our talented team will assure you best result and we are familiar with international markets, We work with customers in a wide variety of sectors. Our talented team can handle all the aspects of custom application development, we are the best among the dot net development companies in Chennai . asp .net web development company

We have quite an extensive experience working with
asp .net development services. we are the only
asp.net web development company which offer custom services to a wide range of industries by exceeding our client’s expectations. You can even interact directly with the team regarding your project, just as you would with your in-house team. hire asp.net programmers to achieve your dream product.

Custom application development company, asp.net development companies, asp .net web development company,Hire asp .net programmers,asp.net web development services,dot net development companies in chennai

Post a Comment