2013年10月22日 星期二

[ASP.NET]合併兩張DataTable資料

有時我們會有多個結構一樣但來源不同的資料,需要顯示在一個Grid裡面,這時我們就能用DataTable的Merge() 函數來實現,以我實務遇到的情況,大概就是一個DataTable資料來源為某個XML檔,而另外一個來源為DB(當然如果都是存在於DB,就可以直接用Join的方式來實現),以下就示範這兩種資料來源怎麼合併:

XML來源:

/// <summary>
/// 模擬XML資料
/// </summary>
/// <returns></returns>
private DataTable GetDataTableXml()
{
    string Xmlstring = @"<Datas>
<Data>
<ID>5</ID>
<來源>XML</來源>
</Data>
<Data>
<ID>6</ID>
<來源>XML</來源>
</Data>
<Data>
<ID>7</ID>
<來源>XML</來源>
</Data>
<Data>
<ID>8</ID>
<來源>XML</來源>
</Data>
</Datas>";
    XmlDocument Xmldoc = new XmlDocument();
    Xmldoc.LoadXml(Xmlstring);
    XmlReader Xmlreader = XmlReader.Create(new System.IO.StringReader(Xmldoc.OuterXml));
    DataSet ds = new DataSet();
    ds.ReadXml(Xmlreader);
    DataTable dt = ds.Tables[0];
    return dt;

}

image



SQL來源

/// <summary>
/// 模擬SQL來源,建立假資料
/// </summary>
/// <returns></returns>
private DataTable GetDataTable()
{
    DataTable dt = new DataTable();
    dt.Columns.Add("ID");
    dt.Columns.Add("來源");

    for (int i = 0; i < 6; i++)
    {
        DataRow dr = dt.NewRow();
        dr["ID"] = i;
        dr["來源"] = "SQL Server";
        dt.Rows.Add(dr);
    }

    return dt;
}

image







 


Merge使用方法

dt1 = GetDataTable();
gv_sql.DataSource = dt1;
gv_sql.DataBind();


dt2 = GetDataTableXml();
gv_xml.DataSource = dt2;
gv_xml.DataBind();

//如果不設Key的話,即使ID重複也會顯示兩筆
dt1.PrimaryKey = new DataColumn[] { dt1.Columns["ID"] };
dt2.PrimaryKey = new DataColumn[] { dt2.Columns["ID"] };

//如果有設Key,設true則保留dt1的資料;設false則保留dt2的資料
dt1.Merge(dt2, true);

gv_merge.DataSource = dt1;
gv_merge.DataBind();

Merge有幾個多載,我故意將兩個資料來源都存在ID為 5 的資料,如果不設Key則就會顯示兩筆ID為5的資料,如設定為true則會保留主表的資料(dt1),false則反之。

 


結果:


image



--

Reference
http://msdn.microsoft.com/zh-tw/library/system.data.datatable.merge.aspx
http://haoxiaoittoo.blogspot.tw/2011/07/datatable.html

2013年10月12日 星期六

[ASP.NET]一個輕鬆取得Facebook讚數的套件

SocialCounter.NET是一個極小的library能抓取一些熱門的社群網站資料,如Facebook、Twitter…如果你只是想抓一些統計資料,又不想去研究JavaScript API,可以嘗試看看此套件,我想對某些公司,會有大量的行銷頁面,抓取一些報表分析還蠻方便的:) 台灣比較多人用Facebook,故以下做個小實驗:

首先用Nuget安裝
image

此範例用MVC展示,並新增一個Controller,並using SocailConter.NET
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using SocialCounter.NET;

namespace MyMVC.Controllers
{
    public class SocialCounterController : Controller
    {
        //
        // GET: /SocialCounter/

        public ActionResult Index()
        {
            string Article = "http://blogs.msdn.com/b/msdntaiwan/archive/2013/09/23/visual-studio-2013.aspx"; //MSDN某文章
            TempData["Gplikes"] = Counter.GetFacebookLikes("https://www.facebook.com/msdn.taiwan");//抓取MSDN粉絲團讚
            TempData["likes"] = Counter.GetFacebookLikes(Article); //文章讚數
            TempData["share"] = Counter.GetLinkedInShareCount(Article); //分享數
            TempData["Article"] = Article;
            return View();
        }

    }
}



非常簡易的方式,接著我們在View顯示出來,並來做個核對
<fieldset>
    <legend>MSDN粉絲團</legend>
    <div>粉絲團讚:@TempData["Gplikes"]</div>
    <div>文章:<a href="@TempData["Article"]">前端工程師的百寶盒 - Visual Studio 2013 開發工具</a></div>
    <div>讚:@TempData["likes"]</div>
    <div>分享數:@TempData["share"]</div>
</fieldset>



粉絲團讚數正確

image



但是文章這篇文章的讚數不一致

image



Anyway,分享給各位做個參考 :)

--

Reference
http://www.nuget.org/packages/SocialCounter.NET/
http://gunnarpeipman.com/2012/07/using-socialcounter-net-with-asp-net-mvc/

2013年10月9日 星期三

[ASP.NET]C#清掉所有控制項的值

分享一個小技巧,今天在維護舊系統發現一段程式,主要邏輯是處理完一些事後,要將某區塊的表單欄位清掉,程式很直覺但寫起來會很煩:

.aspx

<!-- 拉一些常用的Controll -->
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
<asp:DropDownList ID="DropDownList1" runat="server">
<asp:ListItem>1</asp:ListItem>
<asp:ListItem>2</asp:ListItem>
</asp:DropDownList>
<asp:HiddenField ID="HiddenField1" runat="server" />
<asp:CheckBox ID="CheckBox1" runat="server" />
<asp:CheckBoxList ID="CheckBoxList1" runat="server"></asp:CheckBoxList>
<asp:Button ID="btn_Clear" runat="server" Text="Button" OnClick="btn_Clear_Click" />

.aspx.cs

TextBox1.Text = "";
Label1.Text = "";
DropDownList1.Items.Clear();
CheckBox1.Checked = false;

因為實際上控制項很多,所以就一拖拉庫以上的程式Orz,所以花了一點時間重構此塊,寫成一個function:

/// <summary>清掉控制項的值</summary>
/// <param name="ctols">控制項ID</param>
private void ClearControlValue(params Control[] ctols)
{
foreach (Control ctol in ctols)
{
string cType = ctols.GetType().Name;
if (typeof(TextBox).Name == cType)
{
(ctol as TextBox).Text = string.Empty;
}
else if (typeof(DropDownList).Name == cType)
{
(ctol as DropDownList).Items.Clear();
}
else if (typeof(CheckBox).Name == cType)
{
(ctol as CheckBox).Checked = false;
}
else if (typeof(CheckBoxList).Name == cType)
{
(ctol as CheckBoxList).SelectedIndex = -1;
}
else if (typeof(RadioButton).Name == cType)
{
(ctol as RadioButton).Checked = false;
}
else if (typeof(RadioButtonList).Name == cType)
{
(ctol as RadioButtonList).SelectedIndex = -1;
}
else if (typeof(Label).Name == cType)
{
(ctol as Label).Text = string.Empty;
}
}
}

使用方法:

//把要清掉值的控制項ID傳入
ClearControlValue(TextBox1, CheckBoxList1, Label1);

2013年10月2日 星期三

[CSS]表單Textbox與Lable調整對齊

常常做一些表單欄位,如果欄位多又不調整版面看起來就會很亂,當然可以用table很方便的定位,但這樣又變成程式碼很亂,以下是我調整畫面&程式碼都看起來很簡潔的CSS程式碼,紀錄一下,每次都要重調還蠻惱人的!

改造前

<label for="txt_name">姓名:</label>
<input type="text" id="txt_name" /><br />
<label for="txt_birth">生日:</label>
<input type="text" id="txt_birth" /><br />
<label for="txt_phone">電話:</label>
<input type="text" id="txt_phone" /><br />
<label for="txt_id">身分證字號:</label>
<input type="text" id="txt_id" /><br />
image


改造後

<div class="Data-Content">
<div class="Data-Title">
<div class="AlignRight">
<label for="txt_name">姓名:</label><br />
<label for="txt_birth">生日:</label><br />
<label for="txt_phone">電話:</label><br />
<label for="txt_id">身分證字號:</label><br />
</div>
</div>
<div class="Data-Items">
<input type="text" id="txt_name" /><br />
<input type="text" id="txt_birth" /><br />
<input type="text" id="txt_phone" /><br />
<input type="text" id="txt_id" /><br />
</div>
</div>
<style type="text/css">
.Data-Content {
width: 100%; /* 表單寬度 */
line-height: 40px;
}

.Data-Title {
float: left;
width: 25%; /* Label寬度,視情況調整 */
margin-right: 20px;
}

.Data-Items {
float: left;
width: 25%;
}

.AlignRight {
text-align: right;
}
</style>
image

2013年9月27日 星期五

[ASP.NET]GridView小計欄跟總計欄的解決方案-使用SQL語法

ASP.NET的GridView是我覺得最方便的Server控制項,在公司內部有很多的報表,主要邏輯都寫在SQL裡面,而在GridView裡就能變得比較單純去繫結資料,並修改一些顯示樣式即可,而小計欄和總計欄又是報表常常會遇到的欄位,本篇文章將Step by Step來實做如何建置這樣的報表。
1.新增一個WebForm,並拉一個GridView控制項至畫面
1
2.移至設計畫面,選擇GridView屬性,修改ID以便程式好閱讀
2 3
3.再來看一下本範例的資料表設計,基本上不會太複雜,分為員工編號、部門、年薪三個欄位
4
4.撰寫SQL語句,也是本文的重點,使用SQL的Grouping語法
NoteGROUPING (Transact-SQL)指出是否彙總 GROUP BY 清單中指定的資料行運算式。 GROUPING 傳回 1 時,表示會在結果集中彙總,傳回 0 則不會。 當指定 GROUP BY 時,GROUPING 只能在 SELECT <select> 清單、HAVING 和 ORDER BY 子句中使用。From MSDN
使用方式如下:
select 
case when grouping(Dept)=1 then N'合計' else isnull(StaffNumber,'') end '員工編號',
case when grouping(StaffNumber)=1 and grouping(Dept)=0 then N'小計' else isnull(Dept,'') end '部門',
sum(pay) as '年薪'
from GirdTest group by Dept,StaffNumber with rollup

如此就能很方便的完成小計欄跟合計欄了:

5

5.接著回到.aspx.cs開始撰寫程式,於Page_Load的時候Binding資料,GetData()是處理資料的自定義function

6
private DataTable GetData()
{
    DataTable dt = new DataTable();
    string Sql = @"
                select 
                case when grouping(Dept)=1 then N'合計' else isnull(StaffNumber,'') end '員工編號',
                case when grouping(StaffNumber)=1 and grouping(Dept)=0 then N'小計' else isnull(Dept,'') end '部門',
                sum(pay) as '年薪'
                from GirdTest group by Dept,StaffNumber with rollup";

    using (SqlConnection connection =
    new SqlConnection(connectionString))
    {
        SqlCommand command = new SqlCommand(Sql, connection);
        try
        {
            connection.Open();
            SqlDataReader reader = command.ExecuteReader();
            dt.Load(reader);
            reader.Close();
            return dt;
        }
        catch (Exception ex)
        {
            //Error logging...
        }
    }
    return dt;
}

6.回到設計頁面,選擇編輯資料行

7


7.加入三個BoundField,並修改HeaderText

8

8.修改DataField,這裡對應的為SQL Select出來的欄位

image

9.接著因為預設的GridView都為白色,我們選擇自動格式化來調整一下版型

image

10.Done!!

image

結論

很多人的做法也會選擇在GirdView的RowDataBind事件做欄位的處理,可參考這篇文章,此篇文章比較囉嗦一點,實際上開發GridView報表其實是很快的一件事,因為希望能幫助到正在學習ASP.NET的初心者,筆者好像幾年前真的遇到卡這個問題卡到快瘋掉的同事XD,當然除了GridView外,還有很多的選擇,如Reporting Service、Crystal Report…等等,可依照自己喜好及好維護的方式去完成囉。

2013年9月26日 星期四

[HTML]網頁音效播放相容性整理

客戶要求千奇百怪,之前做的線上客服系統,希望收到訊息時加上音效提示,希望把它當作MSN(翻桌),基本上這樣還蠻吵的,但在這吵雜聲中,順便把各種撥放音效的方式做個瀏覽器相容性的整理。

 

1.Hyperlink

IE7+(會跳出下載視窗)、Chome、Firefox、Opera

<a href="msg.wav">Play Sound</a>

 


2.embed


IE7、Chome、Firefox、Opera

<embed src="msg.wav" autostart="false" loop="false">

 


3.Javascirpt(舊方法)


IE7+、Chome、Firefox、Opera(除IE外,剛進入頁面的時候接會撥放一次)

<script>
function PlaySound(soundobj) {
var thissound = eval("document." + soundobj);
thissound.Play();
}
</script>
<input type="button" value="Play Sound" onClick="PlaySound('sound1')">
<embed src="msg.wav" autostart=false width=0 height=0 name="sound1" enablejavascript="true">

 


4.Javascript(新方法)


IE7+、Chome、Firefox、Opera(除IE外,剛進入頁面的時候接會撥放一次)

<script>
function EvalSound(soundobj) {
var thissound = document.getElementById(soundobj);
thissound.Play();
}
</script>

<embed src="msg.wav" autostart="false" width="1" height="1" id="sound1"
enablejavascript="true">
<input type="button" value="Play Sound" onClick="EvalSound('sound1')">

 


5.Background標籤


IE Only

<bgsound id="sound">
<script>
function PlaySound(url) {
document.all.sound.src = url;
}
</script>
<input type="button" value="Play Sound" onClick="PlaySound('msg.wav')">

 


6.Dynamic HTML


IE7+、Chome、Firefox、Opera

<script>
function DHTMLSound(surl) {
document.getElementById("dummyspan").innerHTML =
"<embed src='" + surl + "' hidden=true autostart=true loop=false>";
}
</script>
<span id=dummyspan></span>
<input type="button" value="Play Sound" onClick="DHTMLSound('msg.wav')">

 


7.HTML5


IE9+(只支援mp3)、Chome、Firefox、Opera

<script>
function EvalSound(soundobj) {
var thissound = document.getElementById(soundobj);
thissound.play();
}
</script>
<audio id="audio1" src="msg.wav" controls preload="auto" autobuffer >
</audio>
<input type="button" value="Play Sound" onClick="EvalSound('audio1')">

 


結論


如果要再某個事件觸發(如Click)又要兼顧相容性,方法6是比較好的做法


--


Reference
http://www.phon.ucl.ac.uk/home/mark/audio/play.htm
http://www.w3schools.com/html/html5_audio.asp

[ASP.NET]C#發送XML Request至PHP頁面

需求概述
專案上常常有與公司夥伴的系統做一些資料的交換,在以往我遇過的都是使用.NET 的Web Service走SOAP協定來做,但這次拿到的規格書是要走HTTP POST的方式,並義好XML架構,在加上一些加解密來做異質系統的交換,而對方的系統是用PHP撰寫的,試了好久終於將傳遞與接收完成,趕快紀錄一下 :(

WebRequest XmlRequest = WebRequest.Create("http://xxxxxxx/Service.php");
XmlRequest.Method = "POST";
//XML範例
string XML = @"
    <XML>
        <TEST>
            <eventTime>2013-08-24 08:00:00</eventTime>
        </TEST>
    </XML>";
byte[] byteArray = Encoding.UTF8.GetBytes("temp=" + XML); //temp為參數的名稱
XmlRequest.ContentLength = byteArray.Length;
XmlRequest.ContentType = "application/x-www-form-urlencoded";
Stream RequestStream = XmlRequest.GetRequestStream();
RequestStream.Write(byteArray, 0, byteArray.Length);
RequestStream.Close();
WebResponse response = XmlRequest.GetResponse(); //開始實做傳遞
Console.WriteLine(((HttpWebResponse)response).StatusDescription);
RequestStream = response.GetResponseStream();
StreamReader reader = new StreamReader(RequestStream);
string responseFromServer = reader.ReadToEnd(); //解析對方回傳的XML

Reference
http://stackoverflow.com/questions/6995314/how-to-send-an-xml-from-a-c-sharp-desktop-application-to-a-php-server-script-and PHP Receiver http://docs.php.net/wrappers.php.php