Confessions of a .NET Developer!

List all the Colors in WPF

Here I am going to make a WPF application that will list all the colors together with its HEX and its RGB value.

Here is how the Application will look like :

ColorWindow

ColorWindow

Here is the code-behind :

    public partial class ListTheColors : Window
    {
        public ListTheColors()
        {
            InitializeComponent();
            this.Loaded += new RoutedEventHandler(ListTheColors_Loaded);
        }

        void ListTheColors_Loaded(object sender, RoutedEventArgs e)
        {           
            listColors.ItemsSource = typeof(Colors).GetProperties();
        }
    }

So here I am using Reflection to get the Properties in the Colorsclass.
The GetProperties() function will return an array of PropertyInfo which is set as ItemsSource to our ListBox.
The PropertyInfo will contain all the Public Properties of the class Colors.
We will extract the name property from it, as it will contain the name of the Color.

Lets move over to the XAML of our application :
Firstly lets specify the DataTemplate for the ListBox which is defined in the Grid.Resources

    <Grid>
        <Grid.Resources>
            <local:BrushToHexConverter x:Key="conv"/>

            <DataTemplate x:Key="BoxTemplate">
                <StackPanel Orientation="Horizontal">
                    <Border Background="{Binding Path=Name}"
                            CornerRadius="5"
                            Width="50"
                            Height="50"/>
                    <StackPanel Orientation="Vertical" Margin="5">
                        <TextBlock Text="{Binding Path=Name}" Margin="5"/>
                        <TextBlock Text="{Binding Path=Name,Converter={StaticResource conv}}" Margin="2"/>
                    </StackPanel>
                </StackPanel>
            </DataTemplate>

So the Border’s background is painted by extracting the Name property which in turn contains the name of the Color.
The first TextBlock displays the name of the Color and the second displays the A,R,G and B of the Color.
The second TextBlock’s uses a Converter to do its job which will convert the Color to RGB values.
Here is the Converter class named BrushToHexConverter which implements IValueConverter interface.

    class BrushToHexConverter:IValueConverter
    {
        #region IValueConverter Members

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            String colorName = value.ToString();
            BrushConverter conv = new BrushConverter();
            SolidColorBrush brush = conv.ConvertFromString(colorName) as SolidColorBrush;
            Color color = brush.Color;
            StringBuilder buildString = new StringBuilder();
                buildString.AppendLine(brush.ToString()).Append("A: ").Append(color.A).Append("  R:").Append(color.R).Append("  G:").Append(color.G).Append("  B:").Append(color.B);
            return buildString;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }

        #endregion
    }

We use a BrushConverter class to extract the color using the ConvertFromString function which takes the name of the color(for ex. AliceBlue) and converts it to a Brush and use the Color property of the Brush to get the Color.
From that color we can extract the A,R,G and B values.

Next I have used a Style for each ListBoxItem.

            <Style x:Key="ItemStyle" TargetType="ListBoxItem">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="ListBoxItem">
                            <Border CornerRadius="2" 
                                    Margin="3"
                                    BorderBrush="Gray"
                                    BorderThickness="2">
                                <ContentPresenter Margin="2"/>
                            </Border>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>

Here is the full XAML :

    <Grid>
        <Grid.Resources>

            <local:BrushToHexConverter x:Key="conv"/>
            
            <DataTemplate x:Key="BoxTemplate">
                <StackPanel Orientation="Horizontal">
                    <Border Background="{Binding Path=Name}"
                            CornerRadius="5"
                            Width="50"
                            Height="50"/>
                    <StackPanel Orientation="Vertical" Margin="5">
                        <TextBlock Text="{Binding Path=Name}" Margin="5"/>
                        <TextBlock Text="{Binding Path=Name,Converter={StaticResource conv}}" Margin="2"/>
                    </StackPanel>
                </StackPanel>
            </DataTemplate>
            
            <Style x:Key="ItemStyle" TargetType="ListBoxItem">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="ListBoxItem">
                            <Border CornerRadius="2" 
                                    Margin="3"
                                    BorderBrush="Gray"
                                    BorderThickness="2">
                                <ContentPresenter Margin="2"/>
                            </Border>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
            
        </Grid.Resources>

        <ListBox ItemTemplate="{StaticResource BoxTemplate}"
                 ItemContainerStyle="{StaticResource ItemStyle}"
                 Name="listColors" Margin="20">
        </ListBox>
    </Grid>

Perfect!

[Edit:
I would like to add one more feature in this application. Its like adding a TextBox on top of ListBox to filter the Colors. For example, if you want to find a particular color, just type in it and it will return the results.

For this we will use the Text_Changed event of the TextBox and in it use the Filter property of the ICollectionView to filter the results.

This is the code-behind :


       private ICollectionView view;

       //Add this Loaded event of the Window
      view = CollectionViewSource.GetDefaultView(listColors.ItemsSource);

        void txtName_TextChanged(object sender, TextChangedEventArgs e)
        {
            view.Filter = delegate(object item)
            {
                PropertyInfo info = item as PropertyInfo;
                return info.Name.ToLower().StartsWith(txtName.Text.ToLower());
            };
        }

Here is how it will look like :

With Filter

With Filter

Happy coding! 🙂

March 25, 2011 Posted by | WPF | 1 Comment

Show a list of Fonts using WPF

As the headline says, I will be displaying all the available fonts in your system using WPF.

This is how it will look like :

Font Window

Font Window

So the fonts are displayed in the ListBox and the result of selecting it is shown in the TextBox.

This again will be done in XAML itself.
Here is the ListBox.

        <ListBox Margin="20,20,20,77"
                 Name="listFonts"
                 ItemsSource="{x:Static Fonts.SystemFontFamilies}"
                 FontSize="13"/>

As you can see, the way ItemsSource is set. Fonts is a Static Class and it has a Property SystemFontFamilies which is a Collection of type FontFamily.

Now what we want is that, the text written in the TextBox should have the Font Family as selected in the ListBox.

        <TextBox Height="27" Margin="20,0,20,35" Name="textBox1" Padding="3" Text="Tarun Kumar Singh" FontSize="13" VerticalAlignment="Bottom"
                 FontFamily="{Binding ElementName=listFonts, Path=SelectedItem}">            
        </TextBox>

So I have used Binding telling the FontFamily that, bind it to the selected item of the listBox.

If you want to show the Font Family in each of the ListBoxItems, then do this :

        <ListBox Margin="20,20,20,77"
                 Name="listFonts"
                 ItemsSource="{x:Static Fonts.SystemFontFamilies}"
                 FontSize="13">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding}" FontFamily="{Binding}"/>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

I have specified a DataTemplate for the ListBox. So the items displayed in ListBox will be TextBlocks and Binding its Text and FontFamily taken from the ItemsSource. This {Binding} means that it will take the source from its parent.

So it will look like this :

Font Window2

Font Window2

That’s it!
Happy Coding! 🙂

March 23, 2011 Posted by | WPF | Leave a comment

Creating a Circular Buffering Control

In this post I shall explain to create a Circular Buffering control like the one seen in websites when your video loads.
As I was learning about Animation and wrote my first post about it here :

Here is how it will look like :

Buffer

Window

No code-behind is used for this, its done in pure XAML!

Here is a Style that I am using for all the Ellipses involved :

        <Grid.Resources>            
            <Style TargetType="{x:Type Ellipse}">
                <Setter Property="Height" Value="12"/>
                <Setter Property="Width" Value="12"/>
                <Setter Property="Fill" Value="Turquoise"/>
                <Setter Property="Opacity" Value="0"/>
            </Style>
        </Grid.Resources>

<!-- And the Grid containing all the Ellipses and Animations-->

    <Grid>
        <Ellipse Margin="103,0,0,72" Name="e1" Stroke="Black" VerticalAlignment="Bottom" HorizontalAlignment="Left"/>
        <Ellipse Name="e2" Stroke="Black" VerticalAlignment="Bottom" Margin="110,0,0,86" HorizontalAlignment="Left" />
        <Ellipse Margin="126,0,0,91" Name="e3" Stroke="Black" VerticalAlignment="Bottom" HorizontalAlignment="Left" />
        <Ellipse Margin="142,0,0,87" Name="e4" Stroke="Black" VerticalAlignment="Bottom" HorizontalAlignment="Left" />
        <Ellipse HorizontalAlignment="Left" Margin="150,0,0,72" Name="e5" Stroke="Black" VerticalAlignment="Bottom"/>
        <Ellipse HorizontalAlignment="Left" Margin="110,0,0,57" Name="e8" Stroke="Black" VerticalAlignment="Bottom"/>
        <Ellipse Opacity="0" Margin="126,0,0,47" Name="e7" Stroke="Black" VerticalAlignment="Bottom" HorizontalAlignment="Left"/>
        <Ellipse HorizontalAlignment="Left" Margin="144,0,0,57" Name="e6" Stroke="Black" VerticalAlignment="Bottom"/>

        <Button Height="23" Margin="87,72,116,0" Name="button4" VerticalAlignment="Top" Content="Animate!">
            <Button.Triggers>
                <EventTrigger RoutedEvent="Button.Click">
                    <BeginStoryboard>
                        <Storyboard RepeatBehavior="Forever">
                            <DoubleAnimation Storyboard.TargetName="e1"
                                             Storyboard.TargetProperty="Opacity"
                                             From="0"
                                             To="1"
                                             AutoReverse="True"
                                             Duration="0:0:0.5"/>
                            <DoubleAnimation Storyboard.TargetName="e2"
                                             Storyboard.TargetProperty="Opacity"
                                             From="0"
                                             To="1"
                                             BeginTime="0:0:0.2"
                                             AutoReverse="True"
                                             Duration="0:0:0.5"/>
                            <DoubleAnimation Storyboard.TargetName="e3"
                                             Storyboard.TargetProperty="Opacity"
                                             From="0"
                                             To="1"
                                             BeginTime="0:0:0.4"
                                             AutoReverse="True"                                            
                                             Duration="0:0:0.5"/>
                            <DoubleAnimation Storyboard.TargetName="e4"
                                             Storyboard.TargetProperty="Opacity"
                                             From="0"
                                             To="1"
                                             AutoReverse="True"                                           
                                             BeginTime="0:0:0.6"
                                             Duration="0:0:0.5"/>
                            <DoubleAnimation Storyboard.TargetName="e5"
                                             Storyboard.TargetProperty="Opacity"
                                             From="0"
                                             To="1"
                                             AutoReverse="True"                                           
                                             BeginTime="0:0:0.8"
                                             Duration="0:0:0.5"/>
                            <DoubleAnimation Storyboard.TargetName="e6"
                                             Storyboard.TargetProperty="Opacity"
                                             From="0"
                                             To="1"
                                             AutoReverse="True"                                           
                                             BeginTime="0:0:1"
                                             Duration="0:0:0.5"/>
                            <DoubleAnimation Storyboard.TargetName="e7"
                                             Storyboard.TargetProperty="Opacity"
                                             From="0"
                                             To="1"
                                             AutoReverse="True"                                           
                                             BeginTime="0:0:1.2"
                                             Duration="0:0:0.5"/>
                            <DoubleAnimation Storyboard.TargetName="e8"
                                             Storyboard.TargetProperty="Opacity"
                                             From="0"
                                             To="1"
                                             AutoReverse="True"                                           
                                             BeginTime="0:0:1.4"
                                             Duration="0:0:0.5"/>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
            </Button.Triggers>
        </Button>
    </Grid>

So what happens here is that when the Button is Clicked a Click event is fired which will animate the 8 ellipses there.
As you can see, the BeginTime is set to every DoubleAnimation with a difference 0.2 seconds. So after first 0.2 seconds are over, the second ellipse starts, when 0.4 seconds are over, the third starts etc. AutoReverse is also given to give a fading-in fading-out effect to each ellipse.
Now you must be wondering that how come it is getting repeated over and over again. Answer is, I have set the RepeatBehaviour propety of the StoryBoard to Forever.

That’s it! It wasn’t that tough, please feel free to leave your comments, feedbacks and your valuable suggestions if you have a better idea on this.
Thanks for reading! 🙂

March 18, 2011 Posted by | WPF | Leave a comment

WPF Tutorial : Change opacity using Animation

Here I will be using Simple Animations to give a “fading in and fading out” rectangle by reducing its opacity.

For the example, When I click on a Button, the Rectangle’s opacity will be reduced from 1 to 0 in a timespan of 3 seconds, and vice-versa

Here is the code-behind way of doing it :

        private void button3_Click(object sender, RoutedEventArgs e)
        {
            DoubleAnimation da = new DoubleAnimation();
            da.From = 1;
            da.To = 0;
            da.Duration = new Duration(TimeSpan.FromSeconds(2));
            da.AutoReverse = true;
            da.RepeatBehavior = RepeatBehavior.Forever;
            //da.RepeatBehavior=new RepeatBehavior(3);
            rectangle1.BeginAnimation(OpacityProperty, da);
        }

Here rectangle1 is our rectangle whose opacity will be changed. We are creating a DoubleAnimation(opacity is of type Double). From and To properties are set to decrease opacity from 1 to 0, Duration is set for 2 seconds. AutoReverse is cool as when the animation finishes(ie. from 1 to 0) , it will start to animate the property from 0 to 1! And RepeatBehaviour property is set as Forever so that it will animate forever. The commented line says that the animation will be repeated 3 times.
But I would recommend everyone to do it in XAML to prevent cluttering the code-behind.

Here is how its done in XAML :

        <Button Height="23" Margin="102,95,100,0" Name="button3" VerticalAlignment="Top" Content="Opacity">
            <Button.Triggers>
                <EventTrigger RoutedEvent="Button.Click">
                    <BeginStoryboard>
                        <Storyboard>
                            <DoubleAnimation Storyboard.TargetName="rectangle1"
                                             Storyboard.TargetProperty="Opacity"
                                             From="1"
                                             To="0"
                                             Duration="0:0:2"
                                             AutoReverse="True"
                                             RepeatBehavior="3x"/>
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
            </Button.Triggers>    
        </Button>

This does the same thing as explained above! Go ahead and have fun with it 🙂
Have a nice day!

March 18, 2011 Posted by | WPF | 2 Comments

Using BackgroundWorker in WPF Applications

In this post i shall explain a simple way for making your UI responsive while handling huge collection of data. For this, i found BackgroundWorker as the best solution. BackgroundWorker is under System.ComponentModel namespace.

The reason why i am using BackgroundWorker is because it is very easy to implement it. Not only that, it is completely thread safe as it takes an available thread from the 25 worker threads that is available in the Thread pool.
The BackgroundWorker also supports Cancellation of the current work, Support for progressbar.

In the example here i will take the case of loading images and displaying it to a ListBox.

Our window will look like this :

Window

Window

So our window will have a Browse button. This will use the FolderBrowserDialog to browse for images. On the right of the button is a progress bar which will show how much work has been done.

Lets first create our BackgroundWorker. This can either be done in XAML or in the code-behind, but i would rather prefer declaring it in the XAML. So here is the XAML declaring the BackgroundWorker.

        <cm:BackgroundWorker x:Key="backgroundWorker"
                             DoWork="BackgroundWorker_DoWork"
                             ProgressChanged="BackgroundWorker_ProgressChanged"
                             RunWorkerCompleted="BackgroundWorker_RunWorkerCompleted"
                             WorkerReportsProgress="True"
                             WorkerSupportsCancellation="True">
        </cm:BackgroundWorker>

You might be wondering what’s this cm?
You have to give a namespace to use the BackgroundWorker like below :

xmlns:cm="clr-namespace:System.ComponentModel;assembly=System"

In simple terms remember one thing, The BackgroundWorker_DoWork will do the long running work and BackgroundWorker_RunWorkerCompleted is the place where the result from the Do_Work is updated in the UI. Also remember that in the DoWork, you cannot update the UI, you cannot access the UI Elements.

All these events be present in the code-behind.
Now to use this BackgroundWorker in our code-behind, do the below :

        private BackgroundWorker backgroundWorker;

        public Window3()
        {
            InitializeComponent();
            
            backgroundWorker = (BackgroundWorker)this.FindResource("backgroundWorker");
        }

The above code will find our backgroundworker defined in the Windows Resources in our XAML.

Next lets implement the simple code for our Browse button :

        private void btnBrowse_Click(object sender, RoutedEventArgs e)
        {
            FolderBrowserDialog openIt = new FolderBrowserDialog();
            //openIt.RootFolder = Environment.SpecialFolder.Desktop;
            openIt.RootFolder = Environment.SpecialFolder.MyComputer;
            DialogResult result = openIt.ShowDialog();
            if (result == System.Windows.Forms.DialogResult.OK)
            {
                txtBrowse.Text = openIt.SelectedPath;
            }
            //backgroundWorker.RunWorkerAsync(@"C:\Documents and Settings\singhta\Desktop");
        }

Now we are in a position to discuss how to show images in the Listbox.
In this example i am using DataBinding, so first i will show you the classes which i will be using.
Here is the FileInfoClass :

    class FileInfoClass
    {
        private String fileName;
        public String FileName
        {
            get { return fileName; }
            set { fileName = value; }
        }

        private BitmapImage btm;
        public BitmapImage Btm
        {
            get { return btm; }
            set { btm = value; }
        }

        private Decimal size;
        public Decimal Size
        {
            get { return size; }
            set { size = value; }
        }
        
    }

And this is our FileInfoCollection class :

class FileInfoCollection:ObservableCollection<FileInfoClass>
    {
    }

The above collection will store the collection of objects of type FileInfoClass.

Its time to implement the BackgroundWorker.
So when after selecting folder, the user will click the Load button .

Here is how its going to be implemented :

        private void btnLoad_Click(object sender, RoutedEventArgs e)
        {
            backgroundWorker.RunWorkerAsync(txtBrowse.Text);
        }

        private void BackgroundWorker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
        {
               if(backgroundWorker.CancellationPending)
                {
                     e.Cancel=true;
                     return;
                }
            String path = (String)e.Argument;
            e.Result = ShowImages(path);
        }

        private ObservableCollection<FileInfoClass> ShowImages(String path)
        {
            FileInfoCollection fic = new FileInfoCollection();

            DirectoryInfo di = new DirectoryInfo(path);
            IEnumerable<FileInfo> query = from FileInfo fi in di.GetFiles()
                                          where fi.Extension.ToUpper().Equals(".JPG") || fi.Extension.ToUpper().Equals(".PNG")
                                                || fi.Extension.ToUpper().Equals(".GIF")
                                          select fi;

            int i = 0;
            int totalItems = query.Count();
            foreach (FileInfo fi in query)
            {
                BitmapImage btm = new BitmapImage(new Uri(fi.FullName));
                btm.Freeze();
                fic.Add(new FileInfoClass()
                {
                    Btm = btm,
                    FileName = fi.Name,
                    Size = (fi.Length / 1024 / 1024)
                });
                backgroundWorker.ReportProgress((int)((100 / totalItems) * i));
                i = i + 1;
            }
            return fic;
        }

Don’t get worried! Its simple. So when Load button is clicked, we will use RunWorkerAsync method of the backgroundWorker which will call BackgroundWorker_DoWork function. RunWorkerAsync method will pass an argument containing the path. This path will be extracted using the e.Argument and subsequently passed to the ShowImages function which will recieve the path from where the images will be taken.

In the ShowImages function, i am using a LINQ query which will extract images of type jpg,png and gif. In the for loop we will create BitmapImage objects and assign it to the FileInfoClass. The freeze method is very important, or else you will get this exception :
“The calling thread cannot access this object because a different thread owns it.”

Next there is ReportProgress which will help us to provide values for our progress bar named progress.
Do remember one thing that to enable this feature, you must set ReportsProgress property to true(which i did in XAML itself).
Same goes for Cancellation too.
If you remember i have mentioned that BackgroundWorker provides an easy way to report how much progress has been made in progress bar.
The argument in ReportProgress takes value as %, it takes from 0 to 100.
The value in the ReportProgress arguement will be used in the below function :

        private void BackgroundWorker_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
        {
            progress.Value = e.ProgressPercentage;
        }

Remember that in the BackgroundWorker_DoWork function, you cannot use the controls defined in the form or else it will throw an exception. The ShowImages function will return FileInfoCollection object and assign it to the Result. This result will be used in the below function :

        private void BackgroundWorker_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
        {
            if(e.Cancelled)
            {
                MessageBox.Show("Browsing Images has been cancelled");
            }
            progress.Value = 0;
            this.DataContext = e.Result as FileInfoCollection;
        }

So in the above function, we can access our controls. I have provided the DataContext to the window.

To cancel the work, use the CancelAsync method like below :

        private void btnCancel_Click(object sender, RoutedEventArgs e)
        {
            backgroundWorker.CancelAsync();
        }

This is our Listbox in the XAML :

        <ListBox ItemsSource="{Binding}" Grid.Row="2" Margin="2" Name="lstImages"
                 ItemTemplate="{StaticResource BoxTemplate}"
                 ItemsPanel="{StaticResource BoxPanel}">           
        </ListBox>

The itemsource will take the DataContext defined above.
In the Window.Resources, i have declared the Itemtemplate and itemspanel for ListBox :

<Window.Resources>
        <DataTemplate x:Key="BoxTemplate">
            <Image Source="{Binding Path=Btm}" Stretch="Fill"/>
        </DataTemplate>
        
        <ItemsPanelTemplate x:Key="BoxPanel">
            <WrapPanel Orientation="Horizontal" ItemHeight="80" ItemWidth="80"/>
        </ItemsPanelTemplate>       
    </Window.Resources>

In the DataTemplate, i have specified the Image that will be displayed by Binding it to Btm property of the FileInfoClass class. I have used a WrapPanel as the ItemsPanel.

Now it should run smoothly as shown in the window above!

I will post the whole code-behind here :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Media.Imaging;
using System.ComponentModel;
using System.IO;
using System.Collections.ObjectModel;
using System.Windows.Forms;

namespace PhotoViewer
{
    /// <summary>
    /// Interaction logic for Window3.xaml
    /// </summary>
    public partial class Window3 : Window
    {
        private BackgroundWorker backgroundWorker;

        public Window3()
        {
            InitializeComponent();
            
            backgroundWorker = (BackgroundWorker)this.FindResource("backgroundWorker");
        }

        private void btnBrowse_Click(object sender, RoutedEventArgs e)
        {
            FolderBrowserDialog openIt = new FolderBrowserDialog();
            //openIt.RootFolder = Environment.SpecialFolder.Desktop;
            openIt.RootFolder = Environment.SpecialFolder.MyComputer;
            DialogResult result = openIt.ShowDialog();
            if (result == System.Windows.Forms.DialogResult.OK)
            {
                txtBrowse.Text = openIt.SelectedPath;
            }
            //backgroundWorker.RunWorkerAsync(@"C:\Documents and Settings\singhta\Desktop");
        }

        private ObservableCollection<FileInfoClass> ShowImages(String path)
        {
            FileInfoCollection fic = new FileInfoCollection();

            DirectoryInfo di = new DirectoryInfo(path);
            IEnumerable<FileInfo> query = from FileInfo fi in di.GetFiles()
                                          where fi.Extension.ToUpper().Equals(".JPG") || fi.Extension.ToUpper().Equals(".PNG")
                                                || fi.Extension.ToUpper().Equals(".GIF")
                                          select fi;

            int i = 0;
            int totalItems = query.Count();
            foreach (FileInfo fi in query)
            {
                BitmapImage btm = new BitmapImage(new Uri(fi.FullName));
                //btm.Freeze();
                fic.Add(new FileInfoClass()
                {
                    Btm = btm,
                    FileName = fi.Name,
                    Size = (fi.Length / 1024 / 1024)
                });
                backgroundWorker.ReportProgress((int)((100 / totalItems) * i));
                i = i + 1;
            }
            return fic;
        }

        private void BackgroundWorker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
        {
            String path = (String)e.Argument;
            e.Result = ShowImages(path);
        }

        private void BackgroundWorker_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
        {
            progress.Value = e.ProgressPercentage;
        }

        private void BackgroundWorker_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
        {
            progress.Value = 0;
            this.DataContext = e.Result as FileInfoCollection;
        }

        private void btnCancel_Click(object sender, RoutedEventArgs e)
        {
            backgroundWorker.CancelAsync();
        }

        private void btnLoad_Click(object sender, RoutedEventArgs e)
        {
            backgroundWorker.RunWorkerAsync(txtBrowse.Text);
        }
    }
}

And the whole XAML here :

<Window x:Class="PhotoViewer.Window3"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:cm="clr-namespace:System.ComponentModel;assembly=System"
    Title="Window3" Height="204" Width="540">
    <Window.Resources>
        <cm:BackgroundWorker x:Key="backgroundWorker"
                             DoWork="BackgroundWorker_DoWork"
                             ProgressChanged="BackgroundWorker_ProgressChanged"
                             RunWorkerCompleted="BackgroundWorker_RunWorkerCompleted"
                             WorkerReportsProgress="True"
                             WorkerSupportsCancellation="True">
        </cm:BackgroundWorker>
        
        <DataTemplate x:Key="BoxTemplate">
            <Image Source="{Binding Path=Btm}" Stretch="Fill"/>
        </DataTemplate>
        
        <ItemsPanelTemplate x:Key="BoxPanel">
            <WrapPanel Orientation="Horizontal" ItemHeight="80" ItemWidth="80"/>
        </ItemsPanelTemplate>
        
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="30"/>
            <RowDefinition Height="30"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <DockPanel>
            <TextBox Name="txtBrowse" Width="200" Margin="2"/>
            <Button Name="btnBrowse" Click="btnBrowse_Click" Width="50" Margin="2" Content="Browse"/>
            <ProgressBar Name="progress" Margin="2"/>
        </DockPanel>
        <StackPanel Orientation="Horizontal" Grid.Row="1">
            <Button Margin="3" Width="60" Content="Load" Name="btnLoad" Click="btnLoad_Click" />
            <Button Margin="3" Width="60" Content="Cancel" Name="btnCancel" Click="btnCancel_Click" />
        </StackPanel>
        <ListBox ItemsSource="{Binding}" Grid.Row="2" Margin="2" Name="lstImages"
                 ItemTemplate="{StaticResource BoxTemplate}"
                 ItemsPanel="{StaticResource BoxPanel}">           
        </ListBox>
    </Grid>
</Window>

Please do check the FileInfoClass and FileInfoCollection classes that i have declared above.

Oh well that was it about BackgroundWorker.
Hope you enjoyed it!
Do drop in you feedback, comments and your valuable suggestions.
Cheers and happy coding! 🙂

March 14, 2011 Posted by | WPF | 1 Comment

Difference between Elements and Descendants

This is a small post regarding the confusion that most XLINQ developers have when they start learning it, that what is the difference between Elements and Descendants?

Well basically both of them take the same arguments and also both return IEnumerable of type XElement, so what makes them different?
Lets take an Example :
here is the XML(it has a root node “users”) :

XML

XML

So the exercise is the return the collection of node “mname” :
First let us use Elements,

XDocument xDoc=XDocument.Load("C:\MyXml.xml");
 IEnumerable<XElement> query = From XElement elem in xDoc.Element("users").Element("user").Element("model").Elements("mname")
Select elem;

As you can see to get to that node we have to start from the top and reach mname node.
Not to forget that, the above code will return only the first user(ie. Tarun), it won’t go to the next user. I would suggest you not to use Elements.

But that’s not the case with Descendants. With Descendants, it returns all the node mname, irrespective of its parent node.
Like this :

IEnumerable<XElement> query=From XElement elem in xDoc.Descendants("mname")
Select elem;

Hope you got the difference.
Have a nice day!

March 7, 2011 Posted by | LINQ | Leave a comment

My own Glassy Button

In this post i will explain my implementation of a Glassy Button.
I have also created a round edged button here : Round Edged Button

Here is how the glassy button will look like :

Glassy

Glassy Button


Cool!

Here are the simple brushes used :

Brushes

Brushes

Here is the XAML of the Button in two parts (Its a bit big!)

XAML Part1

XAML Part1

In the above XAML, i have created an outer border which will contain two inner borders. These 2 inner borders will in a grid divided in half(see the row definitions). So upper border will have the upper Brush and lower one with lower brush. Simple solution!

Next part is this the control template with triggers to get the zoom effect:

XAML Part2

XAML Part2

Cool!
Hope you liked it! 🙂

March 3, 2011 Posted by | WPF | | 1 Comment

WPF Tutorial – How to use IDataErrorInfo in WPF

In this post I shall explain how to use IDataErrorInfo in a WPF Application. IDataErrorInfo takes into consideration the powerful databinding that WPF has provided. If you are Binding your controls using the Binding techinque, then for validations, IDataErrorInfo is recommended as it is easier to implement.

Lets get started!

First we will create a User class :

    class User:IDataErrorInfo,INotifyPropertyChanged
    {

        private String _firstName;
        public String FirstName
        {
            get { return _firstName; }
            set
            {
                _firstName = value;
                OnPropertyChanged("FirstName");
            }
        }

        private String _lastName;
        public String LastName
        {
            get { return _lastName; }
            set
            {
                _lastName = value;
                OnPropertyChanged("LastName");
            }
        }

        private int _age;
        public int Age
        {
            get { return _age; }
            set
            {
                _age = value;
                OnPropertyChanged("Age");
            }
        }

        #region IDataErrorInfo Members

        public string Error
        {
            get { return String.Empty; }
        }

        public string this[string columnName]
        {
            get
            {
                String errorMessage = String.Empty;
                switch (columnName)
                {
                    case "FirstName":
                        if (String.IsNullOrEmpty(FirstName))
                        {
                            errorMessage = "First Name is required";
                        }
                        break;
                    case "LastName":
                        if (String.IsNullOrEmpty(LastName))
                        {
                            errorMessage = "Last Name is required";
                        }
                        break;
                    case "Age":
                        if (Age < 1)
                        {
                            errorMessage = "Age cannot be less than one";
                        }
                        break;
                }
                return errorMessage;
            }
        }

        #endregion
    
        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler  PropertyChanged;
        private void OnPropertyChanged(String propertyName)
        {
            if(PropertyChanged!=null)
            {
                PropertyChanged(this,new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion
}

In the above class, I implemented two Interfaces, IDataErrorInfo to provide validation and INotifyPropertChanged to notify that the Property has changed.
You can see the IDataErrorInfo readonly properties.
The second one is what we need. It has a column name parameter, which will be the Properties of the User class.
For each property, we are assigning specific rules such as, the FirstName and the LastName should not be empty. The age should not be less than one. The errorMessage field will be initialised with the Error Message that you want to show when these rules are not followed.

Then there is a Users class which will inherit the ObservableCollection(of User). It will hold the collection of User.

   class Users:ObservableCollection
    {
        public Users()
        {
            Add(new User()
            {
                FirstName = "Tarun",
                LastName = "Singh",
                Age = 22
            });
        }
    }

So now we can create a window to display our data.

Window

Window

And here is the XAML :
I shall XAML parts by parts:

Here is the Resources used :

Resources - TextBox

Resources - TextBox

Here I have created a style for all the textboxes. Note the TargetType, I have written it as {x:Type TextBox}, thus this style will be applied to all the Style in the Grid. Firstly, I have added a Trigger to set the ToolTip whenever there is a Validation Error.
Next I have provided the ErrorTemplate for the textbox. Basically whenever there is a validation we can provide our own template for it using AdornedElementPlaceHolder(pretty long one!). This will place a layer above the element, as in this I placed a Border above the TextBox with a Red BorderBrush. And then I have provided a TextBlock to the Right of the TextBox which will give a Red star indicating an error together with the ToolTip.

Next step will be disabling the Button when Validation fails in any of the TextBoxes.

Resources - Button

So here in the XAML, you can see I have added DataTrigger(ya i should have used a MultiDataTrigger with Conditions, but all the Conditions will have to be true so i will be coming with a solution for this!). Each datatrigger is bound to textboxes to check for Validation Errors, if errors found then, the button will be disabled! Cool isn’t it!

Now lets turn our attention to the XAML of Controls that we have used as this part does the Binding.
SO here it is :

XAML - Controls

XAML - Controls

There are two important things to take care of.
First is the use of ValidatesOnErrors. This should be declared in Binding Expression and set to True if we are using IDataErrorInfo.

Second is the use of Binding.ValidationRule. There are two reasons why we are using this is. First is because if we leave Age empty, no validation will be evaluated. Second is if on adding characters to the age, still no validation will be fired. Try removing the Binding.ValidationRule and you can see the difference. So to handle this, we will create a class AgeValidation to solve this problem.

Here is the class:

    class AgeValidation:ValidationRule
    {
        public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
        {
            int age;
            Boolean noIllegalChars;
            noIllegalChars = int.TryParse(value.ToString(), out age);

            if (value.ToString().Length < 1)
            {
                return new ValidationResult(false,"Age field cannot be empty");
            }
            else if(noIllegalChars==false)
            {
                return new ValidationResult(false, "Illegal Characters");
            }
            else
            {
                return new ValidationResult(true, null);
            }
        }
    }

This class inherits the ValidationRule and overrides the ValidationRule function. Here we can check for illegal characters and also check for empty entry in the Textfield. This function will return the Error Message that you want to show. Awesome! 🙂

Do add the namespace to locate this class in the assembly.

xmlns:local=”clr-namespace:WpfApplication1″;

Finally in the code-behind of our window, in the class constructor, we can provide the DataContext like below:

    public partial class Window2 : Window
    {
        public Window2()
        {
            InitializeComponent();
            DataContext = new Users();
        }
    }

Lets see its working now!

Running Example

Cool!

That’s it!
So this is how Validation is handled in WPF.
Hope you enjoyed it! Do leave your comments, suggestions, feedbacks on how you liked this article. 🙂
Have a nice day!

March 3, 2011 Posted by | WPF | 10 Comments