麥克斯做個不宅的工程師

Maxi’s idiotic programming.

Google Map + ASP.NET Series 1

I have made a little web page with google map api. Here are issues I dealed with.
Some of them are of ASP.NET, some of them are of Google Map.

Here are a little features description of my application.
1. Move to one of the marker and zoom in.
2. Pop up info window with information.
3. Showing the mouse Lat. and Lng.
4. Draging marker.
5. Show/hide maker’s name label.
6. Show/hide markers by category.
7. Show information of each station with label.
1-4 are features that provide by Google api.
5-7 are features that needs to work on.

1-3
4

The first thing you need to deal with will be ’s onload and onunload event.
Google’s simple guide is adding an initialize() to onload and adding GUnload() to onunload.
It is not a good idea if you have your on master page and
make it runat=”server”, putting javascript functions to it.

I get around like this. A div with Id=”GMap” and runat=”server”.
In code-behind:
Page.ClientScript.RegisterStartupScript(this.GetType(), "OnLoad", string.Format("AddOnLoadFunctionParam(initialize,\"{0}\");", GMap.ClientID), true);
Page.ClientScript.RegisterStartupScript(this.GetType(), "OnUnload", "GUnload();", true);

In Javascript:
function AddOnLoadFunctionParam(func, containerId) {
$addHandler(window, "load", function() { func(containerId) });
return;
}
function AddOnUnloadFunction(func) {
$addHandler(window, "unload", func);
return;
}
function initialize(id) {
var map = new google.maps.Map2(document.getElementById(id));
map.setCenter(new google.maps.LatLng(37.4419, -122.1419), 13);
//do what you need to do.
}

I pass the div’s Id to the javascript by using the registering it to the page. In that javascript function.
I am using ASP.NET AJAX Client Library function (although nothing AJAX here), to append it as an onload event handler.
This will preserve all other onload event handler. Do the same to onunload with GUnload().

Try it, and write to me if you get any question. Since I have done this quite a while ago.
And write this by memory, and I know my memory is not that good.

July 10, 2009 , Friday Posted by maxi326 | Programming | , , , | No Comments Yet

Branch in Visual sourcesafe

Amount all those version control system, visual source safe is not the best one for sure.
And maybe the worst…but company policy, so…
No matter what you are developing, branching will come to your face one day.
It is not that straight forward for roll-back and branching in VSS.

In the Visual SourceSafe Explorer, right-click on the project that you want to branch. Then Select Show History.
In the Project History dialog box, select the recursive option if all subprojects and their files are wanted. Click OK.
Select the version you want to branch, and click the Share button. Select the branch after share on the lower left.
Select the project in which you want to create the new branch. Click OK.
In the Share dialog box, type the name you want to give to the new branch and
check the recursive checkbox if you want to branch subprojects. Click OK.

July 5, 2009 , Sunday Posted by maxi326 | Server | , , | No Comments Yet

How to Rip DVD in for idiot like me

I have evaluate a few popular dvd ripping / transcoding softwares.
Most of them are free.

First thing first, there are some imformation you better know.
The resolution and the frame per second.
Optionally, the audio codec.
You can get these information by using a free software MediaInfo

Then you can pick one of these software to do the ripping.
Next Video Converter
This one is the easiest to use amount all there. Just choose file, choose codec, start.
But this one is not free software. It claim you can use its full features in evaluation version.
The catch is, you can only convert 1hr in 1 day. That is no DVD can be rip in one file.
Any DVD Converter
This one is very popular software recommended by many people from forums.
A little bit more difficult than Next Video Converter but still point and click easy.
With no limitation and free.
MediaCoder
This one is free and the most power amount these three softwares.
The trade off is, this one is not easy to use. I am going to walkthrough MediaCoder.

Run MediaCoder, press the add file icon on the upper left. Choose the dvd.
There are many files in a dvd. Usually there will be a VTS_01_0.IFO
with not much file size and many .VOB with bigger file size. Choose the .IFO.
Then there are many tab windows on the lower left.
We are going through them one by one.
Generic tab – output folder and etc, nothing special.
Video tab – this one is very important. We choose our video codec here.
I usually use H.264 since it is High quality video implementation of Mpeg-4.
And it is very popular choice. Then choose Bitrate-based mode. This variable is responsible for the file size and which will affect the video quality. Storage space is cheap so I use 1024, you may use any rate you like. Then on the right, there is a x264 tab. Profile select high, predictor frames 6, Motion Est. Mode Hexagonal, Range 16, B-Frames 5, subpel refinement 7.
Audio tab – select Nero Encoder, on the right Nero Encoder tab, select HE-ACC V2, CBR, 192 kbps.
Container tab – container use AVI
Picture tab – frame rate 30, click ‘effect’, will pop up a dialog, this one is important, De-interlacce choose YADIF, then you can preview the outcome. Click ok when finished.
Subtitle tab – set an ID.

This is it. Click start and lay back.

July 5, 2009 , Sunday Posted by maxi326 | 科技與人生 | , , , , , , , | No Comments Yet

Generate Statistic Chart with ZedGraph in ASP.NET

中文翻譯請稍候.
The chart generation work is handled by my former colleague Peter. But he left.
He did the job with his own little chart library which I don’t know how to use it.
So I look for an open source and/or free solution. I find ZedGraph and it looks pretty much 90% what I need.

After experiencing ZedGraph, it is very amazing how easy to use ZedGraph and its features are so complete!

Download ZedGraph first.
If you are not going to make your own version or dive into the source, just download dll only.

Create a Web Application, add both ZedGraph.dll and ZedGraph.Web.dll to the reference.
And then right click on the toolbox, add new server control by adding ZedGraph.Web.dll.
You can now drag the ZedGraph control to your design view.
Remember to *REMOVE* all other tags, just leave

and the ZedGraphWeb control behind.
Result in something like this :
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="GenerateLineChart.aspx.cs" Inherits="TaoYuan.HistoryData.ByItemGroup.GenerateLineChart" %>
<%@ Register Assembly="ZedGraph.Web" Namespace="ZedGraph.Web" TagPrefix="zgw" %>

As you can read in their document, ZedGraph works in two modes.
I am not going to explain it since their have nice document on that.
I will show how to use the stream mode to expose a Graph as a url.

Back to the page which we have a ZedGraph control.
We assign an event handler to RenderGraph event which will define how the graph is rendered. Assign like the following :
zedGraphControl.RenderGraph += new ZedGraph.Web.ZedGraphWebControlEventHandler(zedGraphControl_RenderGraph);
public void zedGraphControl_RenderGraph(ZedGraphWeb zgw, Graphics g, MasterPane masterPane){...}

Inside the handler method, you will be given a default master pane.
I maybe talk about master pane later, let’s just use one graph in this post.
What you need to do here is setup the graph style, bind data and done.
I will just show a demo snippet with a little explaination.

//get a graph pane
GraphPane masterPaneDefault = masterPane[0];
//style the title and axises
masterPaneDefault.Title.Text = m_selectedStation.Name;
masterPaneDefault.XAxis.Title.IsVisible = false;
masterPaneDefault.YAxis.Title.Text = m_selectedItemInfo.Name+'('+ m_selectedItemInfo.Unit +')';
//we are going to use line chart here
//use data to make a curve line
PointPairList theLine = new PointPairList();
foreach (DataRow dr in m_DataFound.Rows)
{
DateTime l_date = (DateTime)dr[0];
double x = (double)new XDate(l_date);
double y = 0;
if (!DBNull.Value.Equals(dr[1]))
{
y = (Single)dr[1];
theLine.Add(x, y);
}
}
//set angle of xaxis label
masterPaneDefault.XAxis.Scale.FontSpec.Angle = 45;
//add the line to our graph pane
LineItem theCurve = masterPaneDefault.AddCurve(m_selectedItemInfo.Name, theLine, Color.Red, SymbolType.XCross);
masterPaneDefault.XAxis.Type = AxisType.DateAsOrdinal;
masterPaneDefault.XAxis.Scale.Format = "yyyy/MM/dd HH:mm";
//smooth the curve
//theCurve.Line.IsSmooth = true;
// Make curves thicker
//theCurve.Line.Width = 3.0F;
// Add gridlines to the plot, and make them gray
masterPaneDefault.XAxis.MajorGrid.IsVisible = true;
masterPaneDefault.YAxis.MajorGrid.IsVisible = true;
masterPaneDefault.XAxis.MajorGrid.Color = Color.Gray;
masterPaneDefault.YAxis.MajorGrid.Color = Color.LightGray;
masterPaneDefault.XAxis.MinorGrid.IsVisible = true;
masterPaneDefault.XAxis.MinorGrid.Color = Color.Khaki;
// Move the legend location
masterPaneDefault.Legend.Position = LegendPos.Right;
// Add a background gradient fill to the axis frame
masterPaneDefault.Chart.Fill = new Fill(Color.White, Color.FromArgb(255, 255, 210), -45F);
masterPaneDefault.Fill = new Fill(Color.FromArgb(250, 250, 255));
//masterPaneDefault.XAxis.Scale.MajorStep = 2.5d;
masterPaneDefault.Legend.IsVisible = false;
//calculate the axis scale ranges
masterPaneDefault.AxisChange();

The result will look something like this.
line chart
That’s it. There are other great charting tools avaiable.
The MS Chart control and Flot are both great. Check them out if you like.

June 19, 2009 , Friday Posted by maxi326 | Programming | , , , | No Comments Yet

How To Cast ExecuteScalar Return Value

SqlCommand.ExecuteScalar(). I believe many of you use this handy method quite often.
But it is what it returns causing the trouble. This method returns an object.

If you try to cast that with (Type), this will almost always return you an invalid cast exception.
It is okay to use (Int32) or (string). But for (double), it needs to be done in another way.
Always use Convert.ToInt32() and Convert.ToDouble() for these situation.
This will save you a day.

June 19, 2009 , Friday Posted by maxi326 | Programming | , , | No Comments Yet

Modify App.Config Programmatically

That is pretty much alike to modifying web.config, see previous post here.

Code snippet as follow which open up the app.config, modify values, save it back.

Configuration l_appConfig = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
AppSettingsSection appSettings = (AppSettingsSection)l_appConfig.GetSection("appSettings");
//let say you want to modify the setting name DatabaseHost
appSettings.Settings["DatabaseHost"].Value = "blahblahblah";
l_appConfig.Save();
ConfigurationManager.RefreshSection("appSettings");

After you run the program and execute this code. You will find that the app.config won’t change.
Because the .config which get modified it in \bin\Debug or \bin\Release depends on what mode you are running.

June 17, 2009 , Wednesday Posted by maxi326 | 學習程式之道 | | No Comments Yet

Remembering ListView page index and restoring it.

I am using ListView with DataPager to get a paging feature of my list.
I want to redirect my page when I click on an entry in the list view, show some detail information.
When I am done, I want to go back and view the exact same list of information.
That is, remembering the page index.

我是用DataPager幫我的ListView做分頁功能.我想要在使用者點選列表上某一條目後,
轉跳到別的頁面,顯示一些詳細資訊後,完成後回到剛才的列表頁面,要能看到剛才的那一個分頁.
就是說,要記住之前的頁碼.

Inside your ItemCommand handler method, use the following code snippet to find the correct startRowIndex
在你的ItemCommand處理程序裡面,用下面的程式片段去找出正確的startRowIndex

//index of the clicked item within the whole list
int l_dataIndex = ((ListViewDataItem)e.Item).DataItemIndex;
//minus the index of the item in that page = startRowIndex
int l_startRowIndex = l_dataIndex - ((ListViewDataItem)e.Item).DisplayIndex;
Store this index whatever you want, I store it by using GET method.
把索引值存在你喜歡的地方,我把它儲存在GET方法裡

Why do I call the above correct startRowIndex and not using the DataPager.startRowIndex?
Because we are going to use DataPager.SetPageProperties() in Page_Load() to restore the page we previously looking at.
為甚麼我會說上面的是正確的startRowIndex還有不去用DataPager.startRowIndex呢?
因為我們將會在Page_Load()裡用DataPager.SetPageProperties()去顯示之前我們在看的分頁

dataPager.SetPageProperties(l_startRowIndex, dpg_dataPager.MaximumRows, true);

This will bring you back to the page as we expect. But after this call.
The startRowIndex won’t update now even though you click next/previous to change your page.
That is why I said this is not the correct startRowIndex. You can try this youself ^^.
這個調用會把你帶到之前的分頁,正如我們預期.但在這個調用後,
startRowIndex就會停止更新,就算你點選上一頁/下一頁也不會改變.
這就是為甚麼我說上面的才是正確的startRowIndex.你可以自己試一試 ^^.

It turns out that I have done something stupid. The SetPageProperties() have to be inside IsPostBack to work correctly.
Result in something like this.

//in ItemCommand handler
url += "&startRowIndex=" + dataPager.startRowIndex;

//in Page_Load
if (!IsPostBack)
{
dataPager.SetPageProperties(startRowIndex, dataPager.MaximumRows, true);
}

June 16, 2009 , Tuesday Posted by maxi326 | Programming | , , , , | No Comments Yet

Javascript little technique in browser url

You can run a little piece of javascript code on a webpage.
Type “javascript:” and the follow by your javascript code in the url space.
Then you code snippet will run and return the value on the browser.

I use this to call getCenter() when using google map to figure out where I am now.

June 16, 2009 , Tuesday Posted by maxi326 | Programming | , | No Comments Yet

What the hell is SOA?

SOA stand for service oriented architecture, has nothing to do with technology being used.
只是一種架構規範,與技術無關.

Define :
Unit – a unit can provide many service, for example a school department is a unit.
Service – an independent logic/process, such as registration service of administration department.
定義 :
單位 – 可以提供多種服務,例如學校行政組
服務 – 一個獨立的邏輯/流程,例如行政組的入學登記服務

SOA purpose is to let those services continuously being developed and accumulate, running separately. Cluster into new service.
In developer point of view. They should think of how to develop service instead of application. Think of stacking old services
to create new service. And the terminal of this is applications which consume services. In other word, think in the service oriented way.
SOA目的,讓服務可以持續累積/發展,分散運行.結合並產生新服務.
對於開發人員,應該去想開發甚麼服務,組合既有服務去建立新服務,到開發終端應用程式時去消耗這些服務.就是用服務導向的思維去想事情.

About the technology, we need to use open standards, such as web service, xml, ODBC, HTTP, etc.
Different web servers provide different services. When creating new application or service, you can consume multiple services from different source,
and then combine them into your new application or service.
關於技術,需要透過開放標準來組合服務,例如web service, xml, ODBC, HTTP 等.
不同的伺服器提供不同的服務,要開發新應用或服務時,可以從不同的來源找尋你需要的服務,再整合成你的新應用或新服務

Advantages
– service can explicitly reuse and accumulate
– integrate resources from different sources
– easily introduce redundancy
好處
– 服務可以較明確的重用/累積
– 整合不同來源的資源(前述的服務)
– 更容易做redundancy

OASIS defines SOA as the following:
A paradigm for organizing and utilizing distributed capabilities that may be under the control of different ownership domains. It provides a uniform means to offer, discover, interact with and use capabilities to produce desired effects consistent with measurable preconditions and expectations.

總結 : 在投入大量資源做SOA後,最難的就是怎樣去Discover那些service和安全性問題

June 16, 2009 , Tuesday Posted by maxi326 | Computer Science Knowledge | | No Comments Yet

資料庫正規化簡介(前四階段)

第一正規化(1NF) – 1. 排除重複群,即每欄位只放單一值 2. 每筆記錄都要有主鍵, 3. 同類事物只能用一個欄位

第二正規化(2NF) – 1. 1NF, 2. 每個欄都要跟整個主鍵有相依關係,而不是主鍵的部份有關,如果不是用複合主鍵,就一定是2NF

第三正規化(3NF) – 1. 2NF, 2. 非主鍵,屬性之間需互相完全無關

Boyce-Codd正規化(BCNF) – 1. 3NF, 2. 非候選鍵或候選鍵superset的欄位,限制了其他欄位的值,即存在欄位X->欄位Y的關係,就違反BCNF.如果表單裡沒有互相重疊的候選鍵,就必定BCNF

補充: 候選鍵即可唯一找出一筆資料的欄位組合,有可以作為鍵值潛力

還有四階NF, 4NF, 5NF, DKNF, 6NF, 通常用來處理特殊情況, 例如key不統一, 通常沒必要用到

June 16, 2009 , Tuesday Posted by maxi326 | Computer Science Knowledge | , | No Comments Yet