Confessions of a .NET Developer!

How to convert bytes to BitmapImage WPF

In this short post I will explain how convert array of bytes to BitmapImage in WPF ofcourse. I happened to use it when I needed to display Images in a DataGrid. And that Image is stored in a column named LargePhoto of data type VARBINARY(MAX) in AdventureWorksDW2008 Database. The VARBINARY(MAX) actually gets transformed into byte[] after mapping the Database to Entity Framework(ya of type EDMX). So I created a Converter to convert the bytes to BitmapImage.

There is one link I found which works in case of Silverlight, haven’t tried in WPF: Byte to BitmapImage in Silverlight

This one by Jobi Joy at StackOverflow also works: Byte to BitmapImage in WPF
But the problem is that stream is left open after conversion, which seems to me is not correct.
In the above case, the stream can be closed using this:

image.StreamSource.Dispose();

Okay so below is the code which will return a BitmapImage when a byte[] is given.

private BitmapImage GetBitmapImageFromBytes(byte[] bytes)
{   
   BitmapImage btm;
   using (MemoryStream ms = new MemoryStream(bytes))
   {
      btm = new BitmapImage();
      btm.BeginInit();
      btm.StreamSource = ms;
      // Below code for caching is crucial.
      btm.CacheOption = BitmapCacheOption.OnLoad;
      btm.EndInit();
      btm.Freeze();
   }
   return btm;
}

This line:

btm.CacheOption = BitmapCacheOption.OnLoad;

is very important. It says that the Image will be loaded into memory, and each request for the Image will be fetched from that memory store. So after closing or disposing the memory stream, the Image will be available in the memory cache.

I also found this piece of code written by Kent Boogart in CodePlex done in a different and in a better way but serving the same purpose : Byte to BitmapImage in WPF (By Kent Boogart)

Hope this helps! Thanks for reading! :)

December 25, 2011 Posted by | C Sharp, WPF | 1 Comment

Auto-fixing height and width of Button in WPF DataGrid

This short post will explain how to automatically fix the height and width of a Button in WPF DataGrid.
The idea is to take the height and width of the cell containing the button. To set a proper margin, we can reduce both the parameters by using a converter.
First the DataGrid:

        <DataGrid VerticalContentAlignment="Center"
                  RowHeight="50" ColumnWidth="*"                  
                  ItemsSource="{Binding Path=Persons}" 
                  IsReadOnly="True"
                  AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTextColumn Header="First Name" Binding="{Binding Path=FirstName}"/>
                <DataGridTextColumn Header="Last Name" Binding="{Binding Path=LastName}"/>
                <DataGridTextColumn Header="Address" Binding="{Binding Path=Address}"/>
                <DataGridTemplateColumn Header="Select">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <Button Content="Select"
                                    Height="{Binding RelativeSource={RelativeSource AncestorType=DataGridCell}, Path=ActualHeight}"
                                    Width="{Binding RelativeSource={RelativeSource AncestorType=DataGridCell}, Path=ActualWidth}"/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>

Lets take a close look at the “Select” column. Its a DataGridTemplateColumn with each row having a Select button. The Button’s height and width is provided by its visual container DatGridCell using the RelativeSource Binding.
It will look something like this:
With no converter

But it doesn’t look good, what’s required is to provide margin. Simply giving margin won’t help.
A converter will be required here to reduce the height and width of the button. On further research, I figured out that a combination of converter and margin can solve the issue, but its still quite unclear to me how it works.

Here is the converter that is used:

    class HeightWidthFixerConverter : IValueConverter
    {
        #region IValueConverter Members

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (parameter != null && value != null)
            {
                double reduceBy;
                if (double.TryParse(parameter.ToString(), out reduceBy))
                    return (double)value - reduceBy;
            }
            return value;
        }

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

        #endregion
    }

The ConverterParameter will be used to specify how much height or width you want to reduce by.
The CellTemplate for the DataGrid will look something like this:
Here is the resource key for converter:

    <Window.Resources>
        <converter:HeightWidthFixerConverter x:Key="heightWidthFixer"/>
    </Window.Resources>

And the CellTemplate:

                <DataGridTemplateColumn Header="Select">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <Button Content="Select"
                                    Margin="2"
                                    Height="{Binding RelativeSource={RelativeSource AncestorType=DataGridCell}, Path=ActualHeight, Converter={StaticResource heightWidthFixer}, ConverterParameter=10}"
                                    Width="{Binding RelativeSource={RelativeSource AncestorType=DataGridCell}, Path=ActualWidth, Converter={StaticResource heightWidthFixer}, ConverterParameter=7}"/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>

The height and width has been reduced by 10 & 7 respectively.
The DataGrid will look like something like this:

With Converter

With Converter

It looks fine now, properly spaced. Surely this hack is not the finest, so I would like to hear your thoughts and suggestions for improvement. Somehow I feel there must be some better way to do this, until then I shall use this. Thank you for reading and have a nice day!

December 20, 2011 Posted by | WPF | 4 Comments

How to enlarge or re-size Calendar in WPF DatePicker

It has been a long time since my last post!
Okay so in this short article, I will show you how to increase the size of a calendar in WPF 4.0 DatePicker. Since I’m currently working on a touchscreen application, it required me to create a larger calendar so that the user can touch it.
So as usual, like normal developers, I started googling for answers, but it was unsuccessful(maybe I need to improve my googling skills!). It required me to think a little more, but finally I got the solution! This is how I did:
You can edit the template of the calendar by wrapping it in a ViewBox. So now the calendar will fit according to the size of the ViewBox. Simples!

Here is the Style for the calendar:

        <Style x:Key="styleCalendar" TargetType="{x:Type Calendar}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Calendar}">
                        <!-- Wrapping in ViewBox will enlarge calendar of that size.-->
                        <Viewbox Height="400"
                                 Width="400">
                            <CalendarItem x:Name="PART_CalendarItem"
                                          Background="{TemplateBinding Background}"
                                          BorderBrush="{TemplateBinding BorderBrush}"
                                          BorderThickness="{TemplateBinding BorderThickness}"/>
                        </Viewbox>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

And apply the style to the DatePicker:

        <DatePicker CalendarStyle="{StaticResource styleCalendar}" Height="25" HorizontalAlignment="Left" Name="datePicker1" Width="115" />

It will look something like this:

Re-size Calendar

Calendar Re-sized

Cool!
I hope it helped, do leave your comments or suggestions for further improvements.

Happy coding! :)

December 19, 2011 Posted by | C Sharp, WPF | 18 Comments

Saving forms settings(location, height) using Serialization

In some applications, there might be some requirements
where you have to load last used form settings like Location, Height and Width the next time you open the form. Well you can create an XML Document with attributes like Location, Width and Height and save it at some location. And then use the XMLDocument class to load and traverse the XML to retrieve the settings. I will bring another, easy way; by using Serialization.

I won’t be going to the details of what Serialization or Deserialization is, as it can be found in many introductory C# books and online tutorials. The only purpose here is to show how can I put Serialization to use.

Basically there are three types of Serialization:
1) BinaryFormatter
2) SoapFormatter
3) XMLFormatter

I will be using Soap as this is the preferred way to persist the object state to be used by any operating system or any framework. XMLFormatter is also a choice but it cannot serialize private fields.

Alright let’s get started.

First create a Windows Forms application and add the following labels as shown in the window.

Labels

Labels

These labels will show the location, height and width of the form to be crossed checked later when we next time open the form.

Next we will create a class named FormSettings whose object we want to persist. As we are using Serialization, this class will be a serialized class by specifying the [Serializable] attribute on top of the class declaration.
The class will look like this:

    [Serializable]
    class FormSettings
    {
        public Point FormLocation { get; set; }
        public FormWindowState WindowState{ get; set; }
        public int Height { get; set; }
        public int Width { get; set; }

        public FormSettings(Point _formLoc, FormWindowState _windowState, int _height, int _width)
        {
            FormLocation = _formLoc;
            WindowState = _windowState;
            Height = _height;
            Width = _width;
        }
    }

Lets get back to the code-behind of our form.
We will declare two private string fields, dirPath and filePath and and four event handlers as shown below.

    public partial class Form1 : Form
    {
        string dirPath = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) +
            @"\FormSettings\";

        string filePath;

        public Form1()
        {
            InitializeComponent();

            this.Load += new EventHandler(Form1_Load);
            this.FormClosed += new FormClosedEventHandler(Form1_FormClosed);
            this.Move += new EventHandler(Form1_Move);
            this.Resize += new EventHandler(Form1_Resize);
        }

dirPath is the folder where we will keep the file which in turn will store FormSettings class’s object’s data.

Let’s first discuss the Move and Resize event:

        void Form1_Move(object sender, EventArgs e)
        {
            lblX.Text = this.Location.X.ToString();
            lblY.Text = this.Location.Y.ToString();
        }

        void Form1_Resize(object sender, EventArgs e)
        {
            lblHeight.Text = this.Height.ToString();
            lblWidth.Text = this.Width.ToString();
        }

Whenever our form is moved or resized, the labels will update the current location and width and height accordingly.

Now let us discuss the Load event.

        void Form1_Load(object sender, EventArgs e)
        {
            LoadSettings();
        }

        private void LoadSettings()
        {
            if (!Directory.Exists(dirPath))
            {
                Directory.CreateDirectory(dirPath);
            }

            filePath = dirPath + @"\Settings.dat";

            if (File.Exists(filePath))
            {
                using (FileStream stream = new FileStream(filePath, FileMode.Open,
                    FileAccess.Read, FileShare.None))
                {
                    SoapFormatter sf = new SoapFormatter();
                    FormSettings settings = (FormSettings)sf.Deserialize(stream);

                    this.Location = settings.FormLocation;

                    if (settings.WindowState == FormWindowState.Maximized)
                    {
                        this.WindowState = FormWindowState.Maximized;
                    }
                    else
                    {
                        this.Width = settings.Width;
                        this.Height = settings.Height;
                    }
                }
            }
        }

Seems to be quite big but its simple.

Scenario 1: When the form is loaded for the very first time.

When the form is loaded for the very first time, it will create a Folder named FormSettings in CommonApplicationData(where all the users can share) directory. And the Settings.dat is appended to the dirPath creating a filePath string. But wait, as it is loaded for the very first time, we don’t have any previous data of location, width or height, hence no need to create the Settings.dat file.

We will create this file in the Closed event as shown below.

Next let us discuss the Closed event.

        void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            SaveSettings();   
        }

        private void SaveSettings()
        {
            FormSettings settings = new FormSettings(this.Location, this.WindowState, 
                this.Height, this.Width);

            using (FileStream stream = new FileStream(filePath, FileMode.Create, 
                FileAccess.ReadWrite, FileShare.None))
            {
                SoapFormatter sf = new SoapFormatter();
                sf.Serialize(stream, settings);
            }
        }

After moving and adjusting the height(to lets say 300), width(250) and location(50,50) (remember that we are considering scenario 1), let’s close the form. Before closing it, we need to save the location(50,50) and other settings to Settings.dat. But as we don’t have the file created, we will create it now by giving FileMode.Create enum which will create if the file doesn’t exist. Now that our file has been created, we will create an instance of SoapFormatter class and use the Serialize method to save the object in that file.
So what happened in our first scenario is that, the file got created and last used location(50,50), height(300) and width(250) got saved as FormSettings object in that file.
Below is the image showing the form position at (50,50).

Scenario1

Scenario1

Scenario2: Opening the form for the nth time.
Let’s again open the form. So the Load event will be called which in turn will call the LoadSettings function.
Let’s again have a look at it:

        private void LoadSettings()
        {
            if (!Directory.Exists(dirPath))
            {
                Directory.CreateDirectory(dirPath);
            }

            filePath = dirPath + @"\Settings.dat";

            if (File.Exists(filePath))
            {
                using (FileStream stream = new FileStream(filePath, FileMode.Open,
                    FileAccess.Read, FileShare.None))
                {
                    SoapFormatter sf = new SoapFormatter();
                    FormSettings settings = (FormSettings)sf.Deserialize(stream);

                    this.Location = settings.FormLocation;

                    if (settings.WindowState == FormWindowState.Maximized)
                    {
                        this.WindowState = FormWindowState.Maximized;
                    }
                    else
                    {
                        this.Width = settings.Width;
                        this.Height = settings.Height;
                    }
                }
            }
        }

When the program execution reaches this function, first it will check whether our directory exists. Yes it does exist when we first run the form before. Then it checks whether the file exists. Again yes it does exist, we created it when we first run the form and created on the Close event.
So now it enters the if(FileExists…) condition. We open the file using FileStream, create the SoapFormatter object and “deserialize” the FormSettings object from the stream. The deserialize method returns an object, hence we have to cast it to FormSettings, lets say the name of the FormSettings object is settings. Retrieve the FormLocation(50,50), width(250) and height(300) of the form from the settings object and set the form’s location, width and height accordingly. So now we got the last used the Width, Height and Location of the form. Excellent.
Below is the snapshot showing the form at (50,50) which was the location that was opened last time.

Scenario2(AfterOpening)

Scenario2 (After Opening)

Now play around with the form, change the location to (100,100) , width to 400, location to 500 and then close it. Now when we close it, SaveSettings function will be called, we need to store the settings that we changed just now back to the file.
Lets have a look at the SaveSettings function now:

        private void SaveSettings()
        {
            FormSettings settings = new FormSettings(this.Location, this.WindowState, 
                this.Height, this.Width);

            using (FileStream stream = new FileStream(filePath, FileMode.Create, 
                FileAccess.ReadWrite, FileShare.None))
            {
                SoapFormatter sf = new SoapFormatter();
                sf.Serialize(stream, settings);
            }
        }

Just to remind ourselves, we now need to store the location(remember 100,100?) and other settings which we just changed back to the file so that the next time the form is opened, the location of the form should be at (100,100).
The interesting thing is that, FileMode.Create won’t actually create another file, as our file already exists, it will instead overwrite the already present data and that is what we wanted! to store the new location(100,100).
So the serialize method will store the settings into the file. So when AGAIN when you open the form, the form will be set at 100,100.

Oh almost forgot, also check out the WindowState property. If it is maximized, then we don’t need the height and width of the form. Hence the next time the window opens, it will be in the maximized state only.

Phew! That’s it! Have fun playing around with it.
Do let me know if there is any kind of bugs that you found.
Cheers!

July 5, 2011 Posted by | C Sharp, Winforms | 1 Comment

Give underline effect to a textbox in WPF using Adorners

Shahin had a doubt, he wanted to give an underline to a textbox when it recieves focus. You can see the question here: Question.

I pondered for a while and thought why not use an Adorner. An Adorner will simple place a layer(here a line) on the textbox. Adorners won’t disturb the control. It will just decorate over the control. The idea is, whenever the textbox gets focus, add the adorner and when it loses the focus, remove it. Here is the solution that I provided to Shahin: Solution
Here is a nice introduction to Adorners: Adorners

Let’s get started. First create a WPF Application named Adornerrs.
Then create a class named AdornOnTextBox which will inherit the Adorner class.
It looks something like this:

using System.Windows.Documents;
using System.Windows;
using System.Windows.Media;

namespace Adornerss
{
    class AdornOnTextBox : Adorner
    {
        public Brush UnderlineBrush { get; set; }
        public double UnderlineThickness { get; set; }

        public AdornOnTextBox(UIElement adornedElement, Brush _underlineBrush, double _underlineThickness)
            : base(adornedElement)
        {
            UnderlineBrush = _underlineBrush;
            UnderlineThickness = _underlineThickness;
        }

        protected override void OnRender(System.Windows.Media.DrawingContext drawingContext)
        {
            //Provides area around the AdornedElement(here, TextBox) where the adorner will be used.
            Rect adornedElementRect = new Rect(AdornedElement.RenderSize);

            //Draw over the control using the Pen.
            Pen pen = new Pen(UnderlineBrush, UnderlineThickness);

            //We will draw the line from bottom-left to bottom right ___________
            drawingContext.DrawLine(pen, adornedElementRect.BottomLeft, adornedElementRect.BottomRight);
        }
    }
}

Wondering why I overrided the OnRender method? The textbox undergoes a series of layout measurements while doing arranging and measuring passes. So it is safe to apply the adorner only after these passes are performed and OnRender is the place to do it. For complex cases, you might want to override ArrangeOverride and MeasureOverride methods but that will be beyond the scope of this article.

Next in the window, add a textbox and name it txtBox.
And then do this:

using System.Windows;
using System.Windows.Documents;
using System.Windows.Media;

namespace Adornerss
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        //Create a reference object for AdornOnTextBox
        AdornOnTextBox adornIt;

        //Create a reference object for AdornerLayer
        AdornerLayer adornLayer;

        public Window1()
        {
            InitializeComponent();
            this.Loaded += new RoutedEventHandler(Window1_Loaded);
            
            // Attach the event handlers.
            txtBox.GotFocus += new RoutedEventHandler(txtBox_GotFocus);
            txtBox.LostFocus += new RoutedEventHandler(txtBox_LostFocus);
        }

        void Window1_Loaded(object sender, RoutedEventArgs e)
        {
            //Instantiation
            adornIt = new AdornOnTextBox(txtBox, Brushes.Red, 2);

            //Get the AdornerLayer of our TextBox.
            adornLayer = AdornerLayer.GetAdornerLayer(txtBox);
        }

        void txtBox_GotFocus(object sender, RoutedEventArgs e)
        {
            //Add the adorner
            adornLayer.Add(adornIt);
        }

        void txtBox_LostFocus(object sender, RoutedEventArgs e)
        {
            //Remove the adorner
            adornLayer.Remove(adornIt);
        }
    }
}

The code is self-explanatory.

And here is our final result:

GotFocus

GotFocus

LostFocus

LostFocus

I have also used a button so that, when the button is clicked, the focus on the textbox will be lost and so will be the Red underline.
That’s it!

There is also another solution provided by nit-singh. Solution 2
But it won’t give you the exact underline but worth giving it a try if you are a XAML freak! I have edited his answer a bit to show the underline more clear.

Happy coding!

July 4, 2011 Posted by | C Sharp, WPF | 2 Comments

Tricky delegates

One day I stumbled upon a curious thing that I noticed while working with delegates.
Let me explain with an example:

using System;
using System.Collections.Generic;

namespace Weird
{
    class Program
    {
        //Delegate declared
        private delegate void ShowValue();

        static void Main(string[] args)
        {
            List<ShowValue> lst = new List<ShowValue>();

            for (int j = 0; j < 5; j++)
            {
                //Instantiating the delegates
                lst.Add(delegate { Console.WriteLine(j); });
            }

            //Invoking the delegates
            //for (int i = 0; i < 5; i++)
            //{
            //    lst[i]();
            //}           
            //In short, using ForEach extension
            lst.ForEach((ShowValue sv) => { sv(); });

            Console.ReadLine();
        }
    }
}

So I have declared a delegate, instantiating and adding them into a List and then invoking them later.
What do you think is the answer? Most of you might be thinking its 0 1 2 3 4. Not quite correct!

This is the result:

Result

Result


Suprising isn’t it!
Now how did that happen, I started investigating. I started to read John Skeet’s C# in Depth, from here I got the idea. The thing is, the delegate actually captures the variable i. Behind the scene, when we declare a delegate, a separate class is created by the compiler which derives from the MultiCastDelegate class. The delegate instance in the for-loop will create a reference to the variable i. So each time it’s instantiated, it actually refers to the same variable. After the loop gets over, i will be 5 and hence when invoked, 5 will be printed.

For the solution, well its quite simple. Here it goes, first the code:

class Program
    {
        private delegate void ShowValue();

        static void Main(string[] args)
        {
            List<ShowValue> lst = new List<ShowValue>();

            for (int j = 0; j < 5; j++)
            {
                int k = j;
                lst.Add(delegate { Console.WriteLine(k); });
            }

            //for (int i = 0; i < 5; i++)
            //{
            //    lst[i]();
            //}           
            //In short, using ForEach extension
            lst.ForEach((ShowValue sv) => { sv(); });

            Console.ReadLine();
        }
    }

The only change I made is to add a new variable k in the for loop. The trick is, as a new k variable is created for every loop, the delegate will always capture a new k and hence references a different variable. And the result will be: 0 1 2 3 4

FinalResult

FinalResult

Perfect! Hope you got the idea.
Happy Coding! :)

June 30, 2011 Posted by | C Sharp | 1 Comment

How to dynamically load assemblies including unreferenced assemblies

This post will explain how to load the dll dynamically and use the class’s methods in that dll. We will use the Activator class to create an instance of a class from the dll and invoke the required methods. So lets get started.

First of all, create a base class library and name it as AClassLibrary:

ClassLibrary

ClassLibrary

Add a new class named AClass, it will look like this:

    public class AClass
    {
        public void WriteDefault()
        {
            Console.WriteLine("A text");
        }

        public void WriteIt(string text)
        {
            Console.WriteLine(text);
        }

        public void WriteIt(string text1, string text2)
        {
            Console.WriteLine(text1 + text2);
        }
    }

Do note that we have two overloaded functions named WriteIt, I will let you know its significance later.

Now lets create another Console Application project in the same solution named CaptureAssembly.
After that, Add Reference to the project AClassLibrary:

AddReference

AddReference

Before explaining, let me show you the whole code:

using System;
using System.Reflection;

namespace CaptureAssembly
{
    class Program
    {
        static void Main(string[] args)
        {
            Assembly a = Assembly.LoadFrom("AClassLibrary.dll");

            Type clsType = a.GetType("AClassLibrary.AClass");
            
            //Create the instance of the class
            object clsInstance = Activator.CreateInstance(clsType, null);

            //Calls the WriteDefault method of AClass
            clsType.InvokeMember("WriteDefault", BindingFlags.InvokeMethod, null, clsInstance, null);

            //Calls the WriteIt methods
            clsType.InvokeMember("WriteIt", BindingFlags.InvokeMethod, null, clsInstance, new object[] { "Hello", " Tarun Kumar" });
            clsType.InvokeMember("WriteIt", BindingFlags.InvokeMethod, null, clsInstance, new object[] { "Hello" });

            Console.ReadLine();
        }
    }
}

First we get the type of AClass using the Reflection. The Activator class will use it to create the instance of the class which we name it as clsInstance.
Next step is to call the 3 methods of AClass. We will use the InvokeMember property using clsType. Let’s take the case of the fist InvokeMethod. The first parameter will take the name of the method, second will help us streamline the search for the method as Reflection is used for this purpose. Third parameter is of no use for now. Fourth parameter, the target is the class instance named clsIntance and the last parameter will take the array of objects used to pass the parameters for the method, as WriteDefault doesn’t have any parameters, hence it will remain null.
The next two invoke methods is for the two overloaded methods WriteIt, the first one will call the method which has two parameters as we are passing two items in the object array(last parameter). As the second invoke method has one item in the object array, hence WriteIt(string text) will be called.

And here is the result:

Result

Result

For loading Unreferenced Assemblies

You can also load the assembly without adding any reference. Suppose the base class library(dll) is in some location, then we can use Assembly.LoadFile method to load the assembly.

Just replace

Assembly a = Assembly.LoadFrom("AClassLibrary.dll");

with

Assembly a = Assembly.LoadFile(@"C:\AClassLibrary\bin\Debug\AClassLibrary.dll");

and you will get the same result.

Happy coding!

June 30, 2011 Posted by | C Sharp, Winforms, WPF | 1 Comment

Using Extension methods – Convert Image to Byte or Base64

Lot of people have questions like, how to convert an Image to byte array or to a Base64 string. I will solve these problems using the Extension methods feature.

With extension methods, you don’t have the need to use Inheritance to use the methods. An extension method is applied to a particular class or structure. An example can help understand more about it.
To start using Extension methods, firstly you need to create a static class which (obviously) will have static methods. In our example, two methods will be created, one which converts Image to byte array and another converts Image to Base 64 string.

    static class ExtensionClass
    {
        public static byte[] GetImageInBytes(this Image img, System.Drawing.Imaging.ImageFormat format)
        {
            using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
            {
                if (format != null)
                {
                    img.Save(ms, format);
                    return ms.ToArray();
                }
                else
                {
                    img.Save(ms, img.RawFormat);
                    return ms.ToArray();
                }
            }
        }

        public static string GetImageInBase64(this Image img, System.Drawing.Imaging.ImageFormat format)
        {
            using (System.IO.MemoryStream ms = new System.IO.MemoryStream())
            {
                if (format != null)
                {
                    img.Save(ms, format);
                    return Convert.ToBase64String(ms.ToArray());
                }
                else
                {
                    img.Save(ms, img.RawFormat);
                    return Convert.ToBase64String(ms.ToArray());
                }
            }
        }
    }

The first parameter has “this” keyword which tells the compiler that “please add this method as an extension method to the Image class to be used by it’s object”. The second parameter takes the ImageFormat as parameter.

Let’s implement this.

    class Program
    {
        static string path = @"C:\Documents and Settings\All Users\Documents\My Pictures\Sample Pictures\Sunset.jpg";
        static void Main(string[] args)
        {
            using (Image myImage = Image.FromFile(path))
            {
                //Extension method used here
                byte[] a = myImage.GetImageInBytes(System.Drawing.Imaging.ImageFormat.Gif);
            }

            using (Image myImage = Image.FromFile(path))
            {
                //Extension method used here also
                string s = myImage.GetImageInBase64(null);
            }
        }
    }

Simple to use, isn’t it. No need of inheritance.

When you type to find the extension method, you can see a down-arrow indicating an extension method.

ExtensionMethod

ExtensionMethod

June 29, 2011 Posted by | C Sharp | Leave a comment

Allow numbers or letters and disable right-click in textbox

I have seen a number of people asking how to allow only numbers to be added in to a textbox, sometimes only letters etc. Also to disable right-click to disable pasting. One such question can be found here: http://www.codeproject.com/Answers/208641/Wish-to-use-text-box-to-only-allow-numeric-Data-en/?cmt=114369#answer4 to which my friend Chanakya(a pro-photographer with excellent technical skills) gave an excellent, sweet and simple answer, also do read the comments. I got inspiration from him to write this post.
So I will create a new TextBox which will handle all the above things. Its a “derived” control where I create a class which derives from TextBox class.

Here is the class:

    class NewTextBox : System.Windows.Forms.TextBox
    {
        private ContextMenu OrgContextMenu;
        private RestrictType _restrictOptions = RestrictType.None;
        public RestrictType RestrictOptions
        {
            get { return _restrictOptions; }
            set { _restrictOptions = value; }
        }

        private bool _allowPaste = true;
        private ContextMenu PrevContextMenu { get; set; }
        private bool _setOnceFlag = false;

        public bool AllowPaste
        {
            get { return _allowPaste; }
            set
            {
                _allowPaste = value;
                DisableRightClick(value);
            }
        }

        protected override void OnKeyDown(KeyEventArgs e)
        {
            //To only allow numbers 
            if (RestrictOptions == RestrictType.OnlyNumbers)
            {
                if (char.IsNumber((char)e.KeyValue) || (((char)e.KeyData) == '\b'))
                {
                    e.SuppressKeyPress = false;
                }
                else { e.SuppressKeyPress = true; }
            }

            // To only allow letters
            else if (RestrictOptions == RestrictType.OnlyLetters)
            {
                if (char.IsLetter((char)e.KeyValue) || (((char)e.KeyData) == '\b'))
                {
                    e.SuppressKeyPress = false;
                }
                else { e.SuppressKeyPress = true; }
            }

            //To only allow 0's and 1's
            else if (RestrictOptions == RestrictType.OnlyBinary)
            {
                if (((char)e.KeyValue).Equals('1') || ((char)e.KeyValue).Equals('0')
                    || (((char)e.KeyData) == '\b'))
                {
                    e.SuppressKeyPress = false;
                }
                else { e.SuppressKeyPress = true; }
            }
        }

        //To disable Cntl + V for pasting
        protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
        {
            if (AllowPaste.Equals(false))
            {
                if (keyData == (Keys.Control | Keys.V))
                {
                    return true;
                }
                else { return false; }
            }
            else { return false; }
        }

        // Disable Right-click for pasting
        private void DisableRightClick(bool enable)
        {
            if (_setOnceFlag == false)
            {
                OrgContextMenu = this.ContextMenu;
                _setOnceFlag = true;
            }
            if (enable.Equals(false))
            {
                // This will create a new ContextMenu with no options, hence no dropdown will be visible.
                this.ContextMenu = new ContextMenu();
            }
            // Set the original context menu.
            else
            { this.ContextMenu = OrgContextMenu; }
        }
    }

And an enum called RestrictType:

    public enum RestrictType
    {
        OnlyNumbers,
        OnlyLetters,
        OnlyBinary,
        None
    }

The code is self-explanatory. To briefly explain, I have created three properties, one is RestrictOptions which is of type RestrictType to let the user choose he/she wants allow numbers or letters or binary. Then the second property is to whether to disable pasting or not. The ProcessCmdKey function will take care of Ctrl + V, disabling it whenever the combination is used, and then using DiableRightClick function to disable Right-click by showing an empty ContextMenu. These two will be set by the user and by default, AllowPaste is true and RestrictType is None. The other property which is private is OrgContextMenu which will store the initial and original ContextMenu of the Textbox which will be set only one time.

Time to use it:

        public Form1()
        {
            InitializeComponent();
            newTextBox1.RestrictOptions = RestrictType.OnlyNumbers;
            newTextBox1.AllowPaste = false;
        }

Please do give your comments and valuable suggestions for improvement. :)
Happy Coding!

June 26, 2011 Posted by | C Sharp, Winforms | 1 Comment

How to use Owner Drawn Controls

There are few controls which support Owner-drawing such as ListBox, ListView,
TreeView, Combobox to name a few. With owner-drawing, you can manipulate the individual items in the above mentioned controls. Each item can be painted using the Graphics object.

In our example, we will use a Listbox having a list of all names of Brushes. Then we will supply the BackColor of each item based on the item’s text(name of Brush).
First step is to set the DrawMode property which takes the DrawMode enum as value. It has three options:
1)Normal – Drawn by operating system, not in our control.
2)OwnerDrawFixed – To be drawn by using our logic with the condition that all the items will be having the same height and width.
3)OwnerDrawVariable – Same as OwnerDrawFixed except that we have to supply the logic for height and width.

Normal won’t be of use in this example as we are going to apply our own logic for drawing of items.
Lets consider using OwnerDrawFixed.
Now to draw the items, we would have to use DrawItem event of ListBox.

Before that, first let us load all the names of the Brushes in the ListBox.

        void Form1_Load(object sender, EventArgs e)
        {
            foreach (PropertyInfo info in typeof(Brushes).GetProperties())
            {
                listBox1.Items.Add(info.Name);
            }
        }

We are using Reflection here to get all the properties and adding each property’s name in to the ListBox.

This is how the window will look like:

SimpleView

SimpleView

Our next task is to give a Background Color for each item in the ListBox depending on the item’s text. For that we will set the DrawMode of ListBox1.

listBox1.DrawMode = DrawMode.OwnerDrawFixed;

Next use the DrawItem event.

listBox1.DrawItem += new DrawItemEventHandler(listBox1_DrawItem);

And the method definition:

void listBox1_DrawItem(object sender, DrawItemEventArgs e)
{
    Brush brush;
    // Take the text from the current listbox item
    string text = listBox1.Items[e.Index].ToString();
    brush = new SolidBrush(Color.FromName(text));
    // Fill the background
    e.Graphics.FillRectangle(brush, e.Bounds);
    // Display the text using the default font and with black foreground
    e.Graphics.DrawString(text, e.Font, Brushes.Black, e.Bounds.X, e.Bounds.Y);
}

And our window will look like this:

OwnerDrawFixed

OwnerDrawFixed

But one small issue is the spacing, the items are closely spaced. Lets provide more spacing by increasing the height of each item. For that we have to set the DrawMode property to OwnerDrawVariable.

listBox1.DrawMode = DrawMode.OwnerDrawVariable;

Our DrawItem event will remain the same but we have to use an additional event “MeasureItem” to alter the height.

listBox1.MeasureItem += new MeasureItemEventHandler(listBox1_MeasureItem);

And the method definition:

void listBox1_MeasureItem(object sender, MeasureItemEventArgs e)
{
   e.ItemHeight = 20;            
}

So now our final window will look like this:

OwnerDrawVariable

OwnerDrawVariable

This is the final source code:

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            this.Load += new EventHandler(Form1_Load);
            //listBox1.DrawMode = DrawMode.OwnerDrawFixed;
            listBox1.DrawMode = DrawMode.OwnerDrawVariable;
            listBox1.DrawItem += new DrawItemEventHandler(listBox1_DrawItem);
            listBox1.MeasureItem += new MeasureItemEventHandler(listBox1_MeasureItem);
        }

        void listBox1_MeasureItem(object sender, MeasureItemEventArgs e)
        {
            e.ItemHeight = 20;            
        }

        void listBox1_DrawItem(object sender, DrawItemEventArgs e)
        {
            Brush brush;
            string text = listBox1.Items[e.Index].ToString();
            brush = new SolidBrush(Color.FromName(text));
            e.Graphics.FillRectangle(brush, e.Bounds);

            e.Graphics.DrawString(text, e.Font, Brushes.Black, e.Bounds.X, e.Bounds.Y);
        }

        void Form1_Load(object sender, EventArgs e)
        {
            foreach (PropertyInfo info in typeof(Brushes).GetProperties())
            {
                listBox1.Items.Add(info.Name);
            }
        }
    }

June 26, 2011 Posted by | Winforms | Leave a comment

Follow

Get every new post delivered to your Inbox.