麥克斯做個不宅的工程師

Maxi’s idiotic programming.

Data Struct in HashTable is ReadOnly

I once use a HashTable to work as a fast data lookup for some struct.
And I use a delegate to implement the Find() method to lookup.

Everything works fine until I try to modify values of the struct that my Find() gives me.
I later find out that because struct is a value type variable.
That means, my Find() return a copy of that struct, modifying it is just useless.

So, HashTable with struct AS-IS readonly.
If you want to have a HashTable with object that is changable,
simply use Class instead of struct.

Well, actually, struct is recommended to use for read only data in MS press book.

September 2, 2009 , Wednesday Posted by maxi326 | Programming | , , | No Comments Yet

SQL server query for Concatenate column fail

You can query for combine columns using ‘+’ operator.

for example:
SELECT Col1 + Col2 AS CombineColumn

Question:
But this query will sometimes fail, how is that?

Answer:
This query will fail if either of the concatenating column contains ‘Null’ value.

Solution:
The isNull() Function can be used to check whether the column is Null.

Example With isNull() Function.
Select isnull(CAST(Customer.Contactid as nvarchar(10)),”) +’-'+ isnull(Customer.Firstname,”) +’-'+ isnull(Customer.LastName,”)
as [Full Name] from Customer

The first parameter is the column and the second parameter is what the method return if ‘Null’ was encountered.

September 2, 2009 , Wednesday Posted by maxi326 | Programming | , | No Comments Yet

C# Extension Method By Simple Example!

For Example, You want to add new methods to System.Web.UI.WebControls.CheckBoxList
Step One. Declare a static class with *any* name.
Step Two. Declare a static method just like any normal method. This method can have return value and arguments.
Remember, we need to have the first argument define like this *this ClassName object*. In our case :
public static void MethodName(this CheckBoxList checkBoxList)
{
...
}

Okay now, Let’s see an example. Let’s say we want to have all selected checkbox values.
We can do like this.
public static class CheckBoxListExtension
{
public static string[] GetSelectedValues(this CheckBoxList checkBoxList)
{
List l_selected = new List(5);
foreach (ListItem item in checkBoxList.Items)
{
if (item.Selected)
{
l_selected.Add(item.Value);
}
}return l_selected.ToArray();
}
}

Then, when you use it, .NET may tells you that it can’t find that method.
The auto add using won’t work in this situation.
That make sense since the extension methods is not in that extended class.
Just add using YourNameSpace manually and we are good.

July 30, 2009 , Thursday Posted by maxi326 | Programming | , , , | No Comments Yet

VS2008 Most Use Hot Key

Ctrl+J 啟動IntelliSense
Ctrl+Tab 輪跳到某個Tab
Shift+Alt+Enter 全畫面寫程式!!
Ctrl+E->D 自動重整程式碼
F7/Shift+F7 轉換成程式碼/設計檢視
Ctrl+K->C/Ctrl+K->U 變成/取消Comment
F12/shift+F12 移到定義/找出所有參考
Ctrl+Shift+S 儲存全部
Ctrl+G 到某一行
Shift+Del 刪除整行
Ctrl+left/Ctrl+right 用一個字做單位移動

July 22, 2009 , Wednesday Posted by maxi326 | Programming | , , | 1 Comment

中文化ReportViewer Toolbar

我都用ReportViewer在網頁上替客戶產生報表,他的好處是可以輸出Excel,pdf.

又可以在網頁上即時預覽,雖然是ActiveX,但它是應付客戶的最佳方法

但客戶才沒那麼好搞定,今天客戶說他看不懂上面的”select export format…”

所以我就去研究中文化了,以下就是中文化的三種方法.

1. ReportViewer 2005版

MS已經有提供語言包,在你的server安裝就可以

2. ReportViewer 2008手動部署

MS還沒提供語言包,所以方法就是在安裝有VS2008的電腦裡,把語言資源copy到伺服器

到%WINDOWS%\assembly裡面找下面兩個東西

Microsoft.ReportViewer.WebForms.resources.dll

Microsoft.ReportViewer.Common.resources.dll

在console用這個命令把他copy出來

xcopy %WINDOWS%\assembly\GAC_msil x:\GAC_MSIL /E /c

這樣檔案就會copy到x:\GAC_MSIL\

然後把兩個資源檔copy到你網頁專案的bin\裡面就可以

3. ReportViewer 2008寫程式修改
以下程式碼在MSDN有

using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using Microsoft.Reporting.WebForms;
namespace WebReport
{
public class ReportViewerMessagesZhtw : IReportViewerMessages
{
IReportViewerMessages Members#region IReportViewerMessages Members
public string BackButtonToolTip
{
get { return ("後退"); }
}
public string ChangeCredentialsText
{
get {return ("更改"); }
}
public string ChangeCredentialsToolTip
{
get { return ("ChangeCredentialsToolTip."); }
}
public string CurrentPageTextBoxToolTip
{
get { return ("當前頁"); }
}
public string DocumentMap
{
get { return ("文件地圖"); }
}
public string DocumentMapButtonToolTip
{
get { return ("文件地圖"); }
}
public string ExportButtonText
{
get { return ("匯出"); }
}
public string ExportButtonToolTip
{
get { return ("匯出"); }
}
public string ExportFormatsToolTip
{
get { return ("選擇匯出格式"); }
}
public string FalseValueText
{
get { return ("不正確的值"); }
}
public string FindButtonText
{
get { return ("尋找"); }
}
public string FindButtonToolTip
{
get { return ("尋找"); }
}
public string FindNextButtonText
{
get { return ("尋找下一筆"); }
}
public string FindNextButtonToolTip
{
get { return ("尋找下一筆"); }
}
public string FirstPageButtonToolTip
{
get { return ("第一頁"); }
}
public string InvalidPageNumber
{
get { return ("無效的頁數"); }
}
public string LastPageButtonToolTip
{
get { return ("最後一頁"); }
}
public string NextPageButtonToolTip
{
get { return ("下一頁"); }
}
public string NoMoreMatches
{
get { return ("沒有匹配"); }
}
public string NullCheckBoxText
{
get { return ("空值"); }
}
public string NullValueText
{
get { return ("空值"); }
}
public string PageOf
{
get { return ("/"); }
}
public string ParameterAreaButtonToolTip
{
get { return ("參數設定"); }
}
public string PasswordPrompt
{
get { return ("PasswordPrompt"); }
}
public string PreviousPageButtonToolTip
{
get { return ("上一頁"); }
}
public string PrintButtonToolTip
{
get { return ("列印"); }
}
public string ProgressText
{
get { return ("正在生成報表"); }
}
public string RefreshButtonToolTip
{
get { return ("刷新"); }
}
public string SearchTextBoxToolTip
{
get { return ("尋找"); }
}
public string SelectAValue
{
get { return ("SelectAValue"); }
}
public string SelectAll
{
get { return ("全選"); }
}
public string SelectFormat
{
get { return ("選擇格式"); }
}
public string TextNotFound
{
get { return ("未找到"); }
}
public string TodayIs
{
get { return ("TodayIs"); }
}
public string TrueValueText
{
get { return ("TrueValueText"); }
}
public string UserNamePrompt
{
get { return ("UserNamePrompt"); }
}
public string ViewReportButtonText
{
get { return ("查看報表"); }
}
public string ZoomControlToolTip
{
get { return ("縮放"); }
}
public string ZoomToPageWidth
{
get { return ("頁寬"); }
}
public string ZoomToWholePage
{
get { return ("整頁"); }
}
#endregion
}
}

然後要修改web.config的設定


因為我只有用到方法2就搞定了,方法3沒試過,有試過的人就說一下行不行吧

July 14, 2009 , Tuesday Posted by maxi326 | Programming | , , | No Comments Yet

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