Thursday, August 30, 2012

Adding skins for custom controls in ASP.NET

Let's say we have a a custom control named MyTextBox which derives from TextBox  control and we need a skin for our MyTextBox control , we can do this by registering our custom control in the skin file

Ex :   <%@ Register Assembly = "WebControls.MyControls"  Namespace = "WebControls.MyControls" tagprefix = "cc1" %>

< cc1:MyTextBox runat="server" color = "black" backcolor="grey" />

Note: If your custom controls  are in the  App_Code folder then  we can omit Assembly attribute while registering.

That's it ,

Friday, October 30, 2009

Printing a DataGridView in C#.NET 2.0

DataGridView doesn't support any event which directly prints the table.
Well,we can accomplish the same by using the PrintDocument and PrintPriewDialog Classes.
The best part of .NET is the organization of classes like the PrintDocument Class which is derived from Printing Class and Printing class is in turn derived from System.Drawing class which has methods for drawing Shapes,Bitmaps and Text so the same methods can be used by PrintDocument Class.
Let's come to the point.

To print a datagridview we require a table with rows and columns.A table is nothing but collection of rectangles as mentioned above PrintDocument class supports drawing of shapes, so we can easily draw a rectangle given the parameters ,the rectangle method is overloaded the one which we are more interested in is:
DrawRectangle(Pens p,int x,int y,int width,int height) where x and y are the co-ordinnates on the print page in pixel units, the other two parameters specify the width and height of the rectangle.
we can specify the co-ordinate's say draw the first rectangle at location 20,20 but how do we get the exact width and height of the rectangle ? not to worry we can get the width parameter from
int width=dataGridView1.Columns[0].Width; //Gives the width of first column
and height parameter from
int height=dataGridView1.Rows[0].Height; //Gives the height of the first Row

At this point we have gathered all the required information do draw a rectangle but when and where to Draw ? PrintDocument supports a event called PrintPage which has 2 parameters the one which we are interested is of type PrintPageEventArgs which supports drawing of rectangle
here's a small snippet

private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)

//Draws a rectangle with same width and height of first column of datagridview.
e.Graphics.DrawRectangle(Pens.Black, 100, 100, dataGridView1.Columns[0].Width, dataGridView1.Rows[0].Height);

//Fills the above drawn rectangle with a light gray colour just to distinguish the header
e.Graphics.FillRectangle(Brushes.LightGray, new Rectangle(100, 100, dataGridView1.Columns[0].Width, dataGridView1.Rows[0].Height));

//Draws a text inside the above drawn rectangle whose value is same of the first column.

e.Graphics.DrawString(dataGridView1.Columns[0].HeaderText, dataGridView1.Font, Brushes.Black, new RectangleF(100, 100, dataGridView1.Columns[0].Width, dataGridView1.Rows[0].Height), str);


Now we are able to draw or say replicate the first column of the datagridview on the page at location 100,100

Now let's draw the second column which adjoins the first column horizontally the position of y co-ordinate remains the same as columns span horizontally but the x position of the second column will change, it will now become 100 +

so repeat the above code in the snippet by just changing the x position of the DrawRectangle and DrawRectangleF method respectively here's the first one

e.Graphics.DrawRectangle(Pens.Black, 100 + dataGridView1.Columns[0].Width, 100, dataGridView1.Columns[1].Width, dataGridView1.Rows[0].Height);

To keep things simple we will restrict our datagridview to only 2 columns.
Now qucikly let us draw the rows one by one by using the same trick as discussed above.

store the origins(x and y ) in variables say x=100 and y=100
width= x + dataGridView1.Columns[0].Width;


Before coding there are few more important points to be discussed.
1. We can get the No of Rows in a datagridview view by using the RowCount property.
2. We need to run a loop to draw all the rows as is in the datagridveiw one by one.
3. We need to check if you table height is exceeding the page height if it exceeds then the printing should continue on a new page ,before directly printing the row on the new page first it should draw the column headers and continue drawing the row.
4. Every time we print a new row we need to increase the table height(nothing but y co-ordinate) by rowheight and let the x co-ordinate be at the same position in our case it's 100
i.e. height+=rowheight;
5. When we are printing the cells of a row we only need to increase the x co-ordinate by colwidth each time and let the y co-ordinate(height) remain stationary.
i.e. width += colwidth;
Here's the code snippet
while (i <>


colwidth= dataGridView1.Columns[0].Width ; /*the coumns width is same for all columns

in our case */

if (height > e.MarginBounds.Height)
height = x; //maintains the y co-ordiante
width = y; //maintains the x co-ordinate
e.HasMorePages = true; /*start printing on a new page,setting this property to true

fires PagePrint event */

height += rowheight; //increment the y co-ordinate

e.Graphics.DrawRectangle(Pens.Black, x, height,colwidth,rowheight);

e.Graphics.DrawString(dataGridView1.Rows[i].Cells[0].FormattedValue.ToString(), dataGridView1.Font, Brushes.Black, new RectangleF(x, height, colwidth,rowheight), str);

e.Graphics.DrawRectangle(Pens.Black, y+ colwidth, height, colwidth, rowheight);

e.Graphics.DrawString(dataGridView1.Rows[i].Cells[1].Value.ToString(), dataGridView1.Font, Brushes.Black, new RectangleF(x+ colwidth, height, width, rowheight), str);
width += colwidth; //increment the x co- ordinate

Behind the print button type


Note: declare the variable i as static or a class level variable
Here's a screen shot of PrintPriewPage which display the datagriview.

Cheers :)

Monday, October 26, 2009

The Murder of Roger Ackroyd-Agatha cristie

Like most cristie's novels this novel too has a very complex plot and ofcourse the very famous detective Poirot.

Roger Ackroyd is a man who knows everything ,he knew his girlfriend had killed her husband few years ago which everyone had tought it was a drug overdose also he knew someone was blackmailing her . He would learn that who the blackmailer was by the evening post which his grilfriend had posted him but before he knew Ackroyd was found dead at his residence.
And From here the reall thrill starts your head starts spinning, till the last page you are totally baffled.Your finger points to every character in the novel. At the end when you learn who the murderer is you are totally suprised and again you start reading thinking which points you missed reading based on which the murderer is caught.
Initailly it takes a bit to understand the characters and what's exactly happening but once you understand then you can't stop.
overall this a very simple written detective novel and good to read .