2014年1月28日 星期二

C# Win Form如何利用GotFocus和LostFocus事件來變更焦點focus於button的樣式

看到論壇問到,因為User在操作系統時常常用tab鍵+enter來快速操作,但預設的focus只會在button上有虛線邊框,有時因為螢幕的因素可能會看不清楚,故希望focus的button能清楚明顯一些,而這個需求,就可以將button註冊GotFocus和LostFocus就能達到,我們先看看結果圖:

btn

做法是抓取所有的Button,並註冊這兩個事件:

public Form1()
{
    InitializeComponent();
    foreach (var control in this.Controls)
    {
        if (control.GetType() == typeof(Button))
        {
            Button btn = (Button)control;
            btn.GotFocus += btn_GotFocus;
            btn.LostFocus += btn_LostFocus;
        }
    }
}

void btn_LostFocus(object sender, EventArgs e)
{
    //改變該Button的樣式
    Button btn = (Button)sender;
    btn.BackColor = SystemColors.Control;
}

void btn_GotFocus(object sender, EventArgs e)
{
    //改變該Button的樣式
    Button btn = (Button)sender;
    btn.BackColor = System.Drawing.Color.Yellow; //變為黃色
}

參考資料

MSDN

focus焦點於textbox在IE中失效之問題

這算是一個小記錄,起因是在Page Load的時候有的textbox要用JavaScript來做focus,但發現IE只要點選頁面其他元素時,在按F5(重新整理),則focus就會失效:

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js "></script>
</head>
<body>
<input id="txtName" type="text" />
</body>
<script type="text/javascript">
$('#txtName').focus();
</script>
</html>


以上程式在Firefox和Chome都沒問題,但在IE Reflash就會失效,看起來好像IE載入元素、JavaScirpt的順序跟其他瀏覽器不太一樣(待確認),導致focus()事件在html document完成之前就先載入了,所以發現主控台會有以下錯誤


image


最後解決的方式是加個timeout,延遲執行focus

<script type="text/javascript">
setTimeout(function () {
$('#txtName').focus();
}, 500);
</script>

2014年1月27日 星期一

如何使用C#將DataTable轉為自訂物件List<class>

前言

早期.Net開發者習慣使用ADO.NET來時做資料儲存,故像DataReader or DataTable來儲存資料其實還蠻常見的,但這種都屬於弱型別,個人覺得在維護上其實還蠻困難的,故Entity Freamwork出來後改變了很多開發模式,將資料物件化也變成一件很正常的事情,現在在維護舊的WebForm系統,即使使用ADO.NET Fill一個DataTable,我還是會將這些資料轉換成自定義的Class,也許多了一道工,但我覺得差這一點點時間,讓維護上更直覺是很重要的事,畢竟程式不是永遠都你一個人在維護而已阿 ! 故此篇文章將會將實務使用的function來做分享。

實作

自定義的class

image

而這是取得DataTable資料的function,為求Demo而塞一些假資料

image

而實際轉換的function如下,而通常我會新增一個class,讓其他程式能共用

public static class DataTableExtensions
{
public static IList<T> ToList<T>(this DataTable table) where T : new()
{
IList<PropertyInfo> properties = typeof(T).GetProperties().ToList();
IList<T> result = new List<T>();

//取得DataTable所有的row data
foreach (var row in table.Rows)
{
var item = MappingItem<T>((DataRow)row, properties);
result.Add(item);
}

return result;
}

private static T MappingItem<T>(DataRow row, IList<PropertyInfo> properties) where T : new()
{
T item = new T();
foreach (var property in properties)
{
if (row.Table.Columns.Contains(property.Name))
{
//針對欄位的型態去轉換
if (property.PropertyType == typeof(DateTime))
{
DateTime dt = new DateTime();
if (DateTime.TryParse(row[property.Name].ToString(), out dt))
{
property.SetValue(item, dt, null);
}
else
{
property.SetValue(item, null, null);
}
}
else if (property.PropertyType == typeof(decimal))
{
decimal val = new decimal();
decimal.TryParse(row[property.Name].ToString(), out val);
property.SetValue(item, val, null);
}
else if(property.PropertyType == typeof(double))
{
double val = new double();
double.TryParse(row[property.Name].ToString(), out val);
property.SetValue(item, val, null);
}
else if (property.PropertyType == typeof(int))
{
int val = new int();
int.TryParse(row[property.Name].ToString(), out val);
property.SetValue(item, val, null);
}
else
{
if (row[property.Name] != DBNull.Value)
{
property.SetValue(item, row[property.Name], null);
}
}
}
}
return item;
}
}


使用方式:

List<UserInfo> list = new List<UserInfo>(); 
DataTable dt = GetDataTable();
var result = DataTableExtensions.ToList<UserInfo>(dt).ToList();
list = result.OrderBy(c => c.UpdateDate).ToList();

此.cs檔可至此連結下載 (如有Bug請見諒,或自行擴充~)

2014年1月25日 星期六

Html5 Storage使用心得與應用

前言

大概半年前,開始接觸到Html5相關技術,但其實沒有太深入在實務上使用過,因為html5常常需要新的瀏覽器支援,故舊版IE支援度就差,瀏覽器的支援度可以到html5 Test網站去測試,而如果用IE8執行,除了看到46分被當掉的分數外,也許你會好奇這46分是哪來的,那時就發現了Storage這個東西,並一直找機會想在實務上用看看,故此篇主要會將一些實務範例做分享。

image
(圖為IE8 html的考試卷)



Html5 Storage的基本介紹

我試著用最簡化的方式來介紹html Storage,當然你想更了解html的機制,可以再延伸去Google或者去參考下面的延伸閱讀。
以往我們要暫存資料可能會選擇Session或者是Cookie,而這兩者其實都跟伺服器端有關聯,Storage是一個純客戶端的新機制,他能儲存的資料大小比Cookie還要大(試瀏覽器而定,Cookie大約4KB,而html5 Storage能到5MB)
Storage又分為兩種:Session Storage和Local Storage,主要差別在生命週期的不同
  • Session Storage : 只要該頁面關閉,則Session Storage的生命週期即結束
  • Local Storage : 相反的,Local Storage在使用者清除瀏覽器資料生命週期才會消失

 

一些範例與應用

以下就介紹我的實務上的應用,也許不是使用的很恰當,或者是有更好的解法,但這篇的目的是讓大家在想Solutions時能想到有html5 Storage能應用。

紀錄div顯示隱藏的狀態

有時表單程式在使用者點選上一頁後,會因為瀏覽器的特性將某些欄位回到初始值狀態,例如下面的例子,我們在下拉式選單選擇其他,會顯示出一個textarea讓他輸入,這時我們就可以寫入Storage來儲存這個div目前應該是隱藏還是顯示。
http://jsfiddle.net/kyleshen/H2pse/
$('#ddlSkills').change(function(){
    if($(this).val() == 'Others') {
        sessionStorage.setItem('ShowOthers', "Y");
        $('#divOthers').show();
    }
    else {
        sessionStorage.setItem('ShowOthers', "N");
        $('#divOthers').hide();
    }
});

$(function(){ 
    //如果SessionStorage為Y時,秀出textarea
    if (sessionStorage.getItem("ShowOthers") == "Y") {
        $('#divOthers').show();
    }
});

會這樣做的原因是之前公司的複雜表單,會針對不同的條件狀態下,顯示不同的區塊及帶入不同的下拉選項或Radio選項,在Submit過後,會顯示出再一次確認表單資訊的訊息,如發現有錯則點選上一頁,這時要保存他所輸入的資訊不讓他重新輸入,那時候就用Session Storage來解決了 !

將Json資料儲存於Session Storage


現在前端技術越來越火紅,有時我們常常會使用一些前端的Gird框架來實作,如JQueryUI、EasyUI、KendoUI…等等,而這些框架多半都使用JSON來接收及傳遞資料。

假設如果Grid我們要獲取目前所勾選的Row資料,這些框架也能很輕鬆的獲取這些項目的JSON string,但如果要將這些項目傳遞到另一頁做處理呢 ? 你也許可以用QueryString將JSON字串當參數傳遞過去,但QueryString是有長度限制的,或者你可以將這些Row的PK,用QueryString傳遞,到該頁時再去DataBase撈取資料也是一個方法,但這樣又多一個Connection。故之前我是將這串JSON String存到Session Storage,即使在操作上換頁也可將這筆資料擷取出來繼續使用。

http://jsfiddle.net/kyleshen/72Qkm/
$(function(){ 
    //新增資料到陣列
    var Skills = new Array();
    Skills.push('C#');
    Skills.push('ASP.NET');
    Skills.push('JQuery');
    
    var Json = JSON.stringify(Skills);
    sessionStorage.setItem('JsonStr', Json);
    $('#DivJson').html(Json); //秀出Json字串的Div
    
});

後記


基本上有了這個儲存機制,可以解決的事情還蠻多的,這邊只是簡單舉例一些小小的應用方式,特別要注意的是,儲存的資料勢必要考慮是不是敏感性資料,畢竟是儲存於客戶端,其實用瀏覽器工具就能看到值並且做竄改,以Chome為例,就是案F12,使用開發者工具視窗,到Resources就能看到key跟Value,點兩下就能改變他的值。Storage已經被很多網站所使用,下次逛網站時,不如打開開發者工具看看那些大網站怎麼應用,並儲存那些資訊吧!

image

延伸閱讀

2014年1月23日 星期四

Chome瀏覽器開發工具分享(不定期更新)

工欲善其事,必先利其器,自從Chome出現之後已經取代我用firefox的習慣,當做主要開發的瀏覽器,而Chome其實不只是只有案F12開啟開發人員工具那麼簡單,還能下載很多的應用程式來搭配使用,以下就分享一些我常用的應用程式,文章會不定期更新!

安裝方式很簡單,點選連結後安裝即可。(如連結失效,請到Google商店輸入關鍵字)

  • Chrome 遠端桌面 - 你是IT fire man嗎 ? 需要遠端回公司救火嗎 ? 試試TeamViewer外的救火工具吧
  • IE Tab - 讓Chome也能執行IE瀏覽器的環境,並可預設開啟的IE模式
  • Eye dropper(拾色器) - 想查看網頁的色碼,或在配色時需要尋找相似顏色,這個調色盤工具非常方便
  • One Tab - Google 尋找問題時不知不覺開啟一堆頁籤,每個頁籤分頁變得跟螞蟻一樣小時就點這個按鈕吧,會幫你整理成群組
  • PostMan - 這不用多說了開發必備,撰寫REST介面的Web Service時搭配的好工具,可模擬表單POST
  • JSON View - 除了Json online viewer網站,你有另外一個選擇能查看json字串節點
  • Window Resizer - 想測試網站在各解析度下是否正常無跑版? 不要傻傻的切換電腦解析度阿,此外掛一鍵就能變更
  • Feedly - 忙碌之餘,別忘了訂閱RSS來吸收新知阿,一個Google RSS Reader的替代方案

以上,隨著更新越來越多我會在分門別類的整理,也歡迎留言告知我。

2014年1月16日 星期四

T-SQL如何join到函數(function)回傳的Table資料

回答論壇問題順便做個紀錄,「SQL字串找尋問題

如何將下列資料用select語法取出B開頭的資料呢?

ID Data
001 A000,B000,C000
002 B000,D000,E000

希望結果:

001 B000

002 B000

最主要先切割字串來分析,首先搭配之前寫的備忘錄,通常我會在SQL建立一個切割字串的函數「在T-SQL裡面切割字串(Spilt String)

接著就能將這個函數回傳的table join起來,再進行篩選

Declare @table Table
(
ID VARCHAR(3),
data NVARCHAR(15)
)

Insert INTO @table values ('001','A000,B000,C000')
Insert INTO @table values ('002','B000,D000,E000')


select tb.id,tb2.data from @table tb
CROSS APPLY Split(data,',') AS tb2
where tb2.data like 'B%'

特別APPLY是SQL 2005之後才提供的語法,所以要注意版本相容性


APPLY又分為CROSS APPLY和OUTER APPLY,


CROSS APPLY 可以把發成我們常用的inner join ,會查詢有交集的結果


OUTER APPLY就相當於left join,會以左邊的資料表為主


詳細的範例可以以上面的MSDN連結延伸閱讀。


執行結果:


image

2014年1月15日 星期三

在T-SQL裡面切割字串(Spilt String)

這是一篇小備忘錄,在DB我通常會用一些自訂函數來解決一些事情,例如分割字串,在程式裡都有內建函式可以用,但SQL就沒有,所以建一個起來再寫T-SQL時會蠻方便的

image

Code :

USE [lenton]
GO
/****** Object: UserDefinedFunction [dbo].[Split] Script Date: 2014/1/16 下午 02:42:09 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[Split]
(
@RowData varchar(8000),
@SplitOn nvarchar(1)
)
RETURNS @RtnValue table
(
Id int identity(1,1),
Data nvarchar(100)
)
AS
BEGIN
Declare @Cnt int
Set @Cnt = 1

While (Charindex(@SplitOn,@RowData)>0)
Begin
Insert Into @RtnValue (data)
Select
Data = ltrim(rtrim(Substring(@RowData,1,Charindex(@SplitOn,@RowData)-1)))

Set @RowData = Substring(@RowData,Charindex(@SplitOn,@RowData)+1,len(@RowData))
Set @Cnt = @Cnt + 1
End

Insert Into @RtnValue (data)
Select Data = ltrim(rtrim(@RowData))

Return
END



2014年1月12日 星期日

在SQL Server 2012 or LocalDB 附加安裝北風資料庫

微軟在以往SQL 2000時代就有提供北風資料庫(Northwind)供下載測試,安裝方式就不再多說,Google一下就有很多教學,例如此篇文章,而在SQL 2012後安裝後會發現無法附加,微軟又提供另一個範例資料庫叫Adventure Works 範例資料庫,雖然這個資料庫關聯很多,資料表命名也更整齊,但通常會用到範例資料庫應該都只是撰寫些Demo,不希望有太複雜關聯的資料庫吧,故本文章主要教學如何在SQL Server 2012安裝北風資料庫,以LocalDB為例。

以傳統附加方式會發生以下錯誤:

image

 

這主要是因為一些相容性問題導致附加失敗,而我們可以用另外一種方式來建立,首先先到從此下載的北風資料庫安裝檔,而預設安裝資料夾為C:\SQL Server 2000 Sample Databases,打開後會有以下檔案,打開instnwnd檔案

 

image

將以下兩行程式碼註解並執行

exec sp_dboption 'Northwind','trunc. log on chkpt.','true'

exec sp_dboption 'Northwind','select into/bulkcopy','true'

 

image

 

這樣就會發現建立完成了 : )

 

image


參考資料

http://buli.waw.pl/sql-server-2012-northwind-database/