Silverlight-Draw Several Lines by Taking One Point as Core and Form Circle According to the Same Angle between Two Lines

In Silverlight, there is a basic class, Line which is used to draw straight line. As is known, a straight line can be displayed only if the location of two options is confirmed. In this article, I will show how to draw lines and form circle in silverlight. Take an example: we have three lines and need to form a circle. So, the angle of each line is 360/3 = 120. If we have eight lines, the angle is  360/8 = 45. We need to custom a line control to realize it. Set location of central point X, Y of  this line control and line length (radius of circle). Calculate radian of line and location of end point 2 according to line count. Then, form a circle with several lines.

Effect image shows as following:

Now, right click project name. Add one silverlight custome control and name it ucLine.xaml. Then add one Line in this custom control. Of course, this line must be in Canvas tab.

Copy the following code in ucLine.xaml:

         <Canvas x:Name=”LayoutRoot” Background=”White”>

<Line X1=”600″ Y1=”600″ X2=”1000″ Y2=”500″ x:Name=”LineD” Stroke=”Black” AllowDrop=”True” />


We need to create new properties: R, AngleAll, CenterX, CenterY for this control in ucLine.xaml.cs. These properties names line length, radian of this line, location of central point X, location of central point Y.


        private double _R;

        private double _AngleAll;

        private double _centerX;

        private double _centerY;


        ///Center Circle Radius


        public double R


            get { return _R; }

            set { _R = value; }


        private double _X2;

        private double _Y2;


        ///Customize Location of X2


        public double X2


            get { return _X2; }



                _X2 = value;

                this.LineD.X2 = this.X2;




        ///Customize Location of Y2


        public double Y2


            get { return _Y2; }



                _Y2 = value;

                this.LineD.Y2 = this.Y2;




        ///Location of Central Point X


        public double CenterX


            get { return _centerX; }



                _centerX = value;

                this.LineD.X1 = _centerX;




        ///Location of Central Point Y


        public double CenterY


            get { return _centerY; }



                _centerY = value;

                this.LineD.Y1 = _centerY;




        ///Threshold Bar Radian


        public double AngleAll


            get { return _AngleAll; }



                _AngleAll = value;

                // Calculate angle, and copy to end location of line. Note: add the beginning location of line when setting end location.

                double sinAngle = Math.Sin(this.AngleAll * Math.PI / 180);

                double cosAngle = Math.Cos(this.AngleAll * Math.PI / 180);

                this.LineD.X2 = cosAngle * this.R + this.CenterX;

                this.LineD.Y2 = this.CenterY – sinAngle * this.R;

                // = AngleAll.ToString();



We can set Line end point location accroding to radian when calling this control. Calculate radian and R length of each line according to line count and legnth in Mainpage.xaml.cs.



            //Get Line Count

            double lineCount = double.Parse((this.comboBox1.SelectedItem as ComboBoxItem).Content.ToString());

            //Get Line Length

            double lineLenth = double.Parse(this.textBox1.Text.ToString());

            //Get Average Angle

            double angle = 360.0 / lineCount;

            for (int i = 0; i < lineCount; i++)


                ucLine dline = new ucLine();

                //Set Radius

                dline.R = lineLenth;

                //Set Beginning Location of Line

                dline.CenterX = 250;

                dline.CenterY = 250;

                //Set Angle of this Line

                dline.AngleAll = angle * (i);


Two Components Recommend:

Spire.Doc, is used to operate MS Word document for .Net and Silverlight, including basic manipulations (generate, open, edit documents), mail merge and other Word functions manipulations.

Spire.XLS, is used to operate MS Excel for .NET and Silverlight, including basic manipulations (generate, open, edit files), chart creation and data exporting.


Silverlight—–Simulate Realization of Tooltip Based on Popup Floating Form Control

In this post, I want to introduce one tip: how to simulate Tip suspended effect by using Popup floating form. When we move mouse on one control, MouseMove method will be triggered. At the same time, Popup control setting will be displayed. Also, we can get the mouse location at that time. Accroding to changes of mouse location, we move Popup HorizontalOffset property (get or set horizontal distance between origin point and popup alignment point) and VerticalOffset property (get and set vertical distance between origin point and popup alignment point) meanwhile. If mouse is left custom control, set IsOpen property of Popup floating form as false to hide it.

Create a Custom Control and Name it TipWindow. XAML code as following:

<UserControl x:Class="SLRightMouseButton.TipWindow"
    d:DesignHeight="300" d:DesignWidth="400" xmlns:sdk="">
    <Grid x:Name="LayoutRoot" Background="White">
        <Popup x:Name="tip">
            <Grid x:Name="toolTip" Width="312" Height="200" >
                    <ImageBrush ImageSource="./BG.png"></ImageBrush>
                    <RowDefinition  Height="auto"/>
                    <RowDefinition />
                    <ColumnDefinition Width="auto"/>
                <TextBlock Grid.Row="0" Grid.Column="0" x:Name="mainContent" Foreground="White" FontSize="14" Height="Auto" HorizontalAlignment="Center"  Margin="0 20 0 0" VerticalAlignment="Top" />



                    <ImageBrush ImageSource="./BG.png"></ImageBrush>

The above sentences are used to set background image of Grid as BG.png under current category. So, we need to add this file as reference in project.

The following shows important part source code of TipWindow.cs.

        public void BindControl(UIElement uc)


            uc.MouseLeave += new MouseEventHandler(ti_MouseLeave);

            uc.MouseMove += new MouseEventHandler(ti_MouseMove);


        public void CancelBindControl(UIElement uc)



            uc.MouseLeave -= new MouseEventHandler(ti_MouseLeave);

            uc.MouseMove -= new MouseEventHandler(ti_MouseMove);



        ///Hide Tooltip when Mouse Leaving Custom Control


        ///<param name="sender"></param>

        ///<param name="e"></param>

        private void ti_MouseLeave(object sender, MouseEventArgs e)


            this.tip.IsOpen = false;



        ///Tooltip Moves when Mouse Moving


        ///<param name="sender"></param>

        ///<param name="e"></param>

        private void ti_MouseMove(object sender, MouseEventArgs e)


            this.tip.IsOpen = true;

            this.tip.HorizontalOffset = e.GetPosition(null).X – 158;

            this.tip.VerticalOffset = e.GetPosition(null).Y – 202;


There is a binding function BindControl(UIElement uc) on the above code. It can bind MouseMove and MouseLeave method by uc control which needs to get TipWindow floating box. Then, create a new custom control Rect.xaml and add a IsFlag propery, which indicates if TipWindow floating box is displayed. Add one rectangle control ti in xaml code.

        <Rectangle x:Name="ti" Width="50" Height="50" RadiusX="5" RadiusY="5" Fill="YellowGreen"></Rectangle>

Enter the following code in Rect.xaml.cs.

        private bool _IsFlag;

        TipWindow tipWindow = new TipWindow();


        ///Display TipWindow or not


        public bool IsFlag


            get { return _IsFlag; }



                _IsFlag = value;

                if (_IsFlag == true)






                   // tipWindow.CancelBindControl(this.ti);




Rect custom control is created. Instantiate it and set IsFlag property as True.


            Rect rect = new Rect();

            rect.Margin = new Thickness(250);

            rect.IsFlag = true;


Two Components Recommend:

Spire.Doc, is used to operate MS Word document for .Net and Silverlight, including basic manipulations (generate, open, edit documents), mail merge and other Word functions manipulations.

Spire.XLS, is used to operate MS Excel for .NET and Silverlight, including basic manipulations (generate, open, edit files), chart creation and data exporting.

Manipulate Excel with ASP.NET

This post is from CodeProject. Recently, I was learning how to operate MS Office documents with ASP.NET. This post is very helpful for me so that I share it in my blog and hope that it will be helpful for others who are learning the same thing with me.

If you want to get the original post, please click here:

Note: I get permissions to share this post from its author.


  • Environment Allocation
  • Excel Basic Manipulation with ASP.NET
  • Generate Excel DataTable with ASP.NET
  • Generate Excel Chart with ASP.NET
  • Browse, Download and Delete Excel Files on Server
  • Appendix

1. Environment Allocation

The following are the environments which I have tested.

  • Windows 9x + Personal Web Server (PWS) + Microsoft Office
  • Windows 2000 Professional + PWS + Microsoft Office
  • Windows 2000 Server + Internet Information Services (IIS) + Microsoft Office

At present, it tests successfully in the latter two environments. Generally speaking, any Office version is OK. But in consideration of uncertainty and incompatible of customers’ allocation, it’s better to choose the older version to avoid that it will not be displayed after downloading.

There are two discoveries.

There are errors when creating Excel objects if WPS 2002 is installed.

It is unstable to create object if opening FrontPage. Sometimes it is successful, sometimes not. It is difficult to create an Excel object if Microsoft Office is run on server.

On the server, COM component permissions must be set. Type DCOMCNFG in the command line and then enter COM setting interface. Choose Microsoft Excel and click properties. Select custom and add Everyone to all permissions. Save and restart server.

2. Excel Basic Manipulation with ASP.NET

a) Create Excel Object

set objExcelApp = CreateObject(“Excel.Application”)

objExcelApp.DisplayAlerts = false

objExcelApp.Application.Visible = false

b) Create a New Excel File


set objExcelBook = objExcelApp.ActiveWorkBook

set objExcelSheets = objExcelBook.Worksheets

set objExcelSheet = objExcelBook.Sheets(1)

c) Read Existed Excel File

strAddr = Server.MapPath(“.”)

objExcelApp.WorkBooks.Open(strAddr & “\Templet\Table.xls”)

set objExcelBook = objExcelApp.ActiveWorkBook

set objExcelSheets = objExcelBook.Worksheets

set objExcelSheet = objExcelBook.Sheets(1)

d) Save as Excel File

objExcelBook.SaveAs strAddr & “\Temp\Table.xls”

e) Save Excel File


f) Quit


set objExcelApp = Nothing

3. Generate Excel DataTable with ASP.NET

a) Insert Data in A Range

objExcelSheet.Range(“B3:k3”).Value = Array(“67”, “87”, “5”, “9”, “7”, “45”, “45”, “54”, “54”, “10”)

b) Insert Data in A Cell

objExcelSheet.Cells(3,1).Value=”Internet Explorer”

c) Select aRange

d) Draw Border on Cell. (Right, Left, Top and Bottom)

e) Set Cell Background Color

f) Merge Cell

g) Insert Row and Column

4. Generate Chart with ASP.NET

a) Create Chart


b) Set Chart Type

objExcelApp.ActiveChart.ChartType = 97

Note:4, Line charts; 5, Pie charts; 51, Bar charts.

c) Set Chart Title

objExcelApp.ActiveChart.HasTitle = True

objExcelApp.ActiveChart.ChartTitle.Text = “A test Chart”

d) Set Chart through Source Data

objExcelApp.ActiveChart.SetSourceData objExcelSheet.Range(“A1:k5”),1

e) Set Chart Data Directly


objExcelApp.ActiveChart.SeriesCollection(1).Name = “=””333″””

objExcelApp.ActiveChart.SeriesCollection(1).Values = “={1,4,5,6,2}”

f) Bind Chart

objExcelApp.ActiveChart.Location 1

g) Display DataTable

objExcelApp.ActiveChart.HasDataTable = True

h) Display Legend

objExcelApp.ActiveChart.DataTable.ShowLegendKey = True

5. Browse, Download and Delete Excel Files on Server.

There are several solutions to browse, Location.href=,Navigate,Response.Redirect. But it’s better to use server because it has more time to generate Excel with server.

It is a little troublesome to download. It is better to download component by using the server online or customize a component. The other way is to manipulate Excel component on server.

There are three programs to delete.

Name the Excel files which are generated by one users as same. So, the new file can cover the old one automatically.

Set to delete users’ temporary files when Session_onEnd method is aroused in Global.asa file.

Set to delete all the files in temporary folder when Application_onStart method is aroused in Global.asa file.

6. Appendix

Add “On Error Resume Next” before each file to avoid the progress dies when errors appear. Therefore, we must run “Application.Quit” no matter if there are errors in files to make sure that there are no dead progress left after completing program.


        strAddr = Server.MapPath(“.”)

        objExcelApp = CreateObject(“Excel.Application”)

        objExcelApp.DisplayAlerts = False

        objExcelApp.Application.Visible = False

        objExcelApp.WorkBooks.Open(strAddr & “\Templet\Null.xls”)

        objExcelBook = objExcelApp.ActiveWorkBook

        objExcelSheets = objExcelBook.Worksheets

        objExcelSheet = objExcelBook.Sheets(1)

        objExcelSheet.Range(“B2:k2”).Value = Array(“Week1”, “Week2”, “Week3”, “Week4”, “Week5”, “Week6”, “Week7”, “Week8”, “Week9”, “Week10”)

        objExcelSheet.Range(“B3:k3”).Value = Array(“67”, “87”, “5”, “9”, “7”, “45”, “45”, “54”, “54”, “10”)

        objExcelSheet.Range(“B4:k4”).Value = Array(“10”, “10”, “8”, “27”, “33”, “37”, “50”, “54”, “10”, “10”)

        objExcelSheet.Range(“B5:k5”).Value = Array(“23”, “3”, “86”, “64”, “60”, “18”, “5”, “1”, “36”, “80”)

        objExcelSheet.Cells(3, 1).Value = “Internet Explorer”

        objExcelSheet.Cells(4, 1).Value = “Netscape”

        objExcelSheet.Cells(5, 1).Value = “Other”



        objExcelApp.ActiveChart.ChartType = 97

        objExcelApp.ActiveChart.BarShape = 3

        objExcelApp.ActiveChart.HasTitle = True

        objExcelApp.ActiveChart.ChartTitle.Text = “Visitors log for each week shown in browsers percentage”

        objExcelApp.ActiveChart.SetSourceData(objExcelSheet.Range(“A1:k5”), 1)


        objExcelBook.SaveAs(strAddr & “\Temp\Excel.xls”)


        objExcelApp = Nothing

        ‘Method to Save table in Web

        ‘For example: ID=MYTABLE in Table

        sub btnExport_onclick()

        Dim objExcel

        On Error Resume Next

        objExcel = CreateObject(“excel.application”)

        With objExcel.visible = True


        End With

        m_row = “0”

        For a = 0 To document.all.mytable.rows.length – 1

            m_row = CStr(int(m_row) + 1)

            For b = 0 To document.all.mytable.rows(a).cells.length – 1

                m_col = chr(asc(“A”) + b)


                M_value = document.all.mytable.rows(a).cells(b).innerText

                objexcel.activecell.value = CStr(m_value)



        objexcel.visible = True


    End Sub


This post shows a method to manipulate Excel with ASP.NET, including basic operation, generate DataTable and chart, browse, download and delete Excel on server.

Finally, I want to recommend another tip in CodeProject, which is about how to export data to Excel and other files with ASP.NET.

Please click here to read:

Export Database to Excel, PDF, HTML, RTF, XML, etc. for ASP.NET without Automation

Oh, Summer

Summer is coming. My eyes are filled with Green.

Summer is a nice season but it makes me be irritated. OK, let me drink ice water and calm down.

Someone told me that beach is the most beautiful scene in Summer. Is it ture?

OK, it’s summer. Let’s enjoy it!

Generate Invoice with Mail Merge by Using C#


Mail merge is often used to print reports in bulk, such as financial statement, payroll or transcript. And the merged documents can be sent by E-mail.

In this article, I will show one way to generate mail merged reports via a .NET Word component, Spire.Doc.

Report Overview

This report includes multiple invoices, and each invoice starts in a new page. Invoice logo and supplier information will present in the header of every page.

Order, shipment, customer, order details and total price make up a completed invoice.

The following pictures show the appearance of invoice:

Content details in each invoice are shown as following:

Order Data Overview

All data in this example is from NorthWind database, which is a sample database provided by Microsoft Access 2003.

We will export data from table Orders, Shippers, Customers, Employees, [Order Details] and Products to generate our report. The following picture shows the relationship between the 6 tables.


We need to finish the following 3 steps to generate our report.

  1. Create a mail merge template.
  2. Load data from database.
  3. Merge data into template and save.

Every step includes several sub-steps and in #2 and #3 we need to write some code.

Create mail merge template

How to Create the Template

A template is a reusable document. It renders the pattern of our report. We could modify it to change our report without any modification of code.

Note: in this section, all tables mean DataTable instance, not physical table in database.

1. We can create the template in MS Word or by other program. Please see the following picture. It is the template we need to create. Data will be filled in the red party.

2. Insert mail-merge-field as placeholder into the red-block. There are three types of mail-merge-field which will be used in this example:

  a). GeneralField is a general Word mail-merge-field. It is real data field and our data will be filled in it during merge process. We need to insert a GeneralField to every red-block and name these fields with the corresponding data name. After inserting GeneralFields, our template will looks like:

   b). TableField is assistant mail-merge-field and used as a container of multiple related GeneralFields and other TableFields. So it is not data placeholder and no data will be filled in. It is composed of two special mail-merge-fields: TableStart:TableName and TableEnd:TableName. During merge process, the data of related GeneralFields contained by one same TableField will be from one same data table. For example, fields in Customer information block will be filled with data from data table Customer, so we need to put them in TableField Customer. Insert a mail-merge-field with field name TableStart:Customer immediately before the first CompanyName field and insert another mail-merge-field with field name TableEnd:Customer immediately after the field Country. And then our fields in Customer information block looks like:

During the merge process, data in column CompanyName of table Customer will be filled in the field CompanyName, Customer.Address to field Address, Customer.City to field City and so on.

Data of fields in column Salesperson in Order information table is from table Employee

Data of fields in column Ship Via in Order information table is from table Shipper

Data of fields in Order details table is from table Detail, except field ProductName. Data of field ProductName is from table Product. Dataof field InvoiceSubtotal and InvoiceTotal in Invoice total information is from table Total (virtual table)


  c). GroupField is assistant mail-merge-field too. It can contain multiple related GeneralFields and TableFields. It is composed of two special mail-merge-fields: GroupStart:GroupName and GroupEnd:GroupName. During merge process, all Word document elements included in a GroupField will be copied. One row in data table has one copy and data in the row will be filled into the fields in the copy. If the row has sub data table, the data in sub data table will be filled into the fields included in the corresponding TableField. If the sub data table has multiple data rows, the corresponding TableField will be copied and filled too. We need to insert a mail-merge-field named GroupStart:Order in the top of the template body and insert a mail-merge-field named GroupEnd:Order in the bottom of the template body. After this, our template looks like:

 You could find the complete template named InvoiceTemplate.doc in the attached source package.

Load Data from Database

Spire.Doc provides merge data from DataSet. So we will use DataAdapter to fill data table from NorthWind database to a DataSet and merge it into our template. Difference from DataRelation of DataSet, Spire.Doc has owned table relation functionality. So we don’t need to create DataRelation instance for the DataSet object. The code below just shows load Order data. Please see the attached source package for other code.

Merge data into template and save

In this section, we need to write some code to call Spire.Doc to merge our data table and template.

1. Create Spire.Doc.Document object and load template.

 2. Establish relationship between data tables.

In order to start each invoice in a new page, we insert a page-break-symbol immediately before the first paragraph when a new order row will be merged. To do this, we need to handle the event MergeField which is fired before a field merged.

Code of method InsertPageBreak


This article focuses on how to generate report by using mail merge with C#. In this method, we need to prepare data information and template firstly. Then, merge data in customized template. It helps us to generate report in bulk quickly and easily. 

For the component used in this example, please download from here.