[SilverLight 2.0] 事件 Declaring Event Handlers

在Silverlight宣告事件的方式有兩種:

  • 直接在XAML內部宣告 (優點:簡單明瞭, 缺點: 只能使用預設的參數, 不能再加參數)
  • 在.cs裡面作宣告 (優點: 彈性大, 可以做變化; 缺點: 比較困難(吧~) )

第一種方式:

在XAML直接作宣告(eg. 在Page.xaml):

<Canvas Loaded=”Canvas_Loaded”>

<Button x:Name=”myButton” Content=”Hello”

Canvas.Left=”10″ Canvas.Top=”10″ />

</Canvas>

在Page.xaml.cs作處理:

private void Canvas_Loaded(object sender, RoutedEventArgs e)

{

theButton.Content = “Please Click Me”;

}

第二種方式

不需在XAML裡面宣告事件

<!– <Canvas  Loaded=”Canvas_Loaded”> –>

<Canvas >

<Button x:Name=”theButton” Content=”I’m Indented!”

Canvas.Left=”150″ Canvas.Top=”20″ />

<CheckBox x:Name=”RushOrder” Content=”Rush”

Canvas.Left=”50″ Canvas.Top=”20″ FontSize=”18″ />

</Canvas>

而是直接在Page.xaml.cs的Page( ) Constructor動手腳~

public Page()

{

InitializeComponent();

Loaded += new RoutedEventHandler(Page_Loaded);

}

void Page_Loaded(object sender, RoutedEventArgs e)

{

/*throw new NotImplementedException(); 去掉這行 */

theButton.Click +=new RoutedEventHandler(theButton_Click); //事件1

RushOrder.Checked += new RoutedEventHandler(RushOrder_Changed); //事件2

RushOrder.Unchecked +=new RoutedEventHandler(RushOrder_Change); //事件3

}

void RushOrder_Changed(object sender, RoutedEventArgs e)

{

if (RushOrder.IsChecked == true)

{

RushOrder.Content = “RUSH”;

}

else

{

RushOrder.Content = “Rush”;

}

}

[SilverLight2] Layout Control介紹

在SilverLight中用來規劃整個版面Layout的Control主要有三種:

  • Grid: 就像Table一樣, 將物件以行列的方式對齊
  • StackPanel: 讓物件之間相對對齊, 如相鄰對齊或向上對齊
  • Canvas: 用絕對對齊(absolute positioning) 的方式放置物件(與SilverLight 1.0相符)

Grid

Grid 在使用VS2008開啟新檔案的時候就已經存在XAML裡面了, 格式會長這個樣子:

<UserControl x:Class=”EasyGrid.Page”

xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation”

xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”

Width=”400″ Height=”300″>

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

</Grid>

你可以先規劃整個SilverLight App的框線, 以便之後的對齊作業, 定義的方式如下:

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

<Grid.RowDefinitions>

<RowDefinition Height=”50″ />

<RowDefinition Height=”30*” MaxHeight=”70″ />

<RowDefinition Height=”40*” MaxHeight=”70″ />

<RowDefinition Height=”*” MinHeight=”30″ MaxHeight=”50″ />

<RowDefinition Height=”Auto” MinHeight=”5″ MaxHeight=”30″ />

</Grid.RowDefinitions>

</Grid>

Height: 每一列的高度

MaxHeight: 能夠拉伸的最大高度 (* 表示以比例的方式定義高度, 兩倍高就是 2*)

MinHeight: 能夠拉伸的最小高度

StackPanel

Stack就是堆疊的意思, 使用StackPanel你可以將你的物件以左右堆疊或者上下堆疊的方式排列, 就像書本在書架上一樣. 它也是在SilverLight2.0經常使用的對齊工具. 下面以放置TextBlock, TextBox, CheckBox及Button 為例:

<StackPanel Background=”Beige” Orientation=”Vertical” >

<TextBlock Text=”Your name?”

HorizontalAlignment=”Left” Margin=”10,2,0,1″/>

<TextBox Width=”150″ Height=”30″

HorizontalAlignment=”Left” Margin=”10,2,0,1″/>

<Button Content=”Submit this information”

HorizontalAlignment=”Left”

Margin=”10,2,0,1″ Height=”30″ Width=”150″ />

<CheckBox Content=”With Zing!” HorizontalAlignment=”Left”

Margin=”10,2,0,1″ />

</StackPanel>

屬性:

Background: Stack背景的顏色

Orientation: 排列方向, Vertical是垂直
在StackPanel內部的物件Margin=”10,2,0,1″ 的Margin順序是左, 上, 右, 下.

[SilverLight2] TextBlock的屬性

SilverLight的Control有很多, 以後會逐一介紹其用法, 首先介紹TextBlock的屬性:

<TextBlock x:Name=”TestName” Grid.Row=”0″ Grid.Column=”0″ Text=”Testing Name: ”  Margin=”5″ />

應用: TextBlock的使用方法跟.NET的Label Control很像, 就是專門顯示文字用的.

屬性:

Grid.Row, Grid.Column叫做Extended Properties, 功能是對齊週邊的Grid格線, 讓App看起來較整齊.
Text 功能就是顯示內部的文字.

Margin很有趣, 輸入不同數目的值就有不同的Margin效果.
Margin=”5″ : 表示 左, 右, 上, 下 都是空出5px.
Margin=”5,6″ : 表示 左右空出5px, 上下空出6px.
Margin=”5,6,7,8″: 表示 左5px, 上6px, 右7px, 下8px.

安裝SilverLight 2 BETA 2 Tools for Visual Studio 2008 的錯誤

如果您的安裝順序是:

1. Visual Studio 2008
2. SilverLight 2 BETA 2 Tools for Visual Studio 2008

應該可以安裝成功,

但如果安裝的順序是:

1. Visual Studio 2008
2. SilverLight 1.0 Runtime
3. SilverLight 2.0 Runtime
4. SilverLight 2 BETA 2 Tools for Visual Studio 2008

則會在安裝的時候出現ERROR. 經過測試, 要解決這個問題方法如下:

1. 控制台 > 新增與移除程式 > 將SilverLight 1.0, 2.0 的RUNTIME都徹底移除
2. 將Program Files 的 SilverLight, SilverLight SDK都移除乾淨.
3. 再安裝SilverLight 2 BETA 2 Tools for Visual Studio 2008 就可以成功了.

建議的安裝順序為:

1. Visual Studio 2008
2. Silverlight 2.0 Run time.
3. Expression Blend 2.5
4. Visual Studio 2008 SP1
5. silverlight_chainer.exe

[Visual C#]Params的應用: Method傳入參數同時可以是陣列與Integer?

當我們在撰寫物件導向程式的時候, 難免會需要將參數傳入Method裡面, 若傳入的參數是陣列, 格式如下:

static void Main(string[] args)
{

int[] a = new int[2]{5,7};

Util util = new Util();

Console.WriteLine(util.Min(a));

}

class Util
{

public int Min(int[] param)
{
if (param == null || param.Length == 0)
{
throw new ArgumentException(“Util.Min: not enough arguments”);
}

int currentmin = param[0];

foreach (int i in param)
{
if (i < currentmin)
{
currentmin = i;
}
}

return currentmin;
}

}

這種寫法應該很直觀吧, 但如果傳入的參數是Integer豈不是出現Error? 要怎麼解決呢? 其實要解決這個問題非常簡單, 就是在Method的參數部分加入 “params”這個關鍵字, 寫法如下:

class Util
{

public int Min(params int[] param)
{
if (param == null || param.Length == 0)
{
throw new ArgumentException(“Util.Min: not enough arguments”);
}

int currentmin = param[0];

foreach (int i in param)
{
if (i < currentmin)
{
currentmin = i;
}
}

return currentmin;
}

}

這樣一來傳入的參數會經過compiler做以下的動作:

int min = Util.Min(first, second);
int[] array = new int[2];
array[0] = first;
array[1] = second;
int min = Util.Min(array);

你的主程式就可以彈性傳入參數, 夠方便吧?

static void Main(string[] args)
{

int[] a = new int[2]{5,7};

Util util = new Util();

Console.WriteLine(util.Min(a));//可以傳入陣列型態的變數

int b = util.Min(2, 10); //同時可以傳入多個Integer

Console.WriteLine(b);

}

使用params有幾個注意事項:

  • 陣列不能是multidimensional
  • 使用params的method不能Overloading (多載)
  • 使用params的method不能是ref 或這 out
  • method傳入的參數只能有一個params array
  • Javascript的navigator.userAgent判斷使用者的瀏覽器版本是好方法嗎?

    我們先把話說在前頭, Javascript的所有函數並不適用在所有的瀏覽器, 這個大家都贊同吧?

    所以你一定會跟我一樣想先擷取使用者的瀏覽器版本, 看看它是用IE, MOZILLA還是Opera等等的, 但這樣的方法真的好用嗎? 老實說這是相當難維護的, 因為瀏覽器會一直更新, 如果你都用IF ELSE來判斷它的版本應該會要一直更新吧, 而且你又要怎麼判斷你的使用者會不會比你更快更新它的瀏覽器呢?

    舊的方法如下:

    javascript:alert(navigator.userAgent);

    如果你使用IE7, 它會回傳給你: Mozilla 4.0/ …..

    這樣的方法真的不是很好, 在這裡有個不錯的方式來判斷:

    if (typeof featureName != “undefined”) {
    // 程式碼
    }

    舉例如下:

    if (typeof document.getElementById != “undefined”) {
    alert(“getelembyid is supported”);

    } else {
    alert(“no getelembyid support”);
    }

    我們要判斷瀏覽器是否支援getElementById 就可以直接用typeof document.xx != “undefined” 來判斷 如果使用者不支援這個函數你就可以再另外想辦法. 另外一種寫法如下:

    var getElem = (typeof document.getElementById == “function”) ? true : false;
    if (getElem) {
    // 我們知道GetElementbyId是支援的,
    // 所以我們就可以用它.
    }

    這樣是不是比較實際且容易維護呢?

    Javascript 的addEventListener()及attachEvent()

    大家都知道事件的用法就是當某個事件(狀況)被觸發了之後就會去執行某個Function, 尤其是Javascript, 在當紅AJAX的催化下, 了解Javascript的Event用法更加重要, 在這裡就大概介紹一下Javascript的Event用法.

    從W3C的發展時間軸來看, DOM(Document Object Model)的模型可以分為兩種, DOM 0 及 DOM 2. 從數字來看就可以知道DOM 0 當然是比較舊的協定, 我們可以從以下的表格來看:

    DOM1 協定:

     

    Event Name

    Description

    onblur()

    The element has lost focus (that is, it is not selected by the user).

    onchange0

    The element has either changed (such as by typing into a text field) or the element has lost focus.

    onclick0

    The mouse has been clicked on an element.

    ondblclick()

    The mouse has been double-clicked on an element.

    onfocus()

    The element has gotten focus.

    onkeydown()

    A keyboard key has been pressed down (as opposed to released) while the element has focus.

    onkeypress()

    A keyboard key has been pressed while the element has focus.

    onkeyup()

    A keyboard key has been released while the element has focus.

    onload()

    The element has loaded (document, frameset, or image).

    onmousedown()

    A mouse button has been pressed.

    onmousemove()

    The mouse has been moved.

    onmouseout()

    The mouse has been moved off of or away from an element.

    onmouseover()

    The mouse has moved over an element.

    onmouseup()

    A mouse button has been released.

    onreset()

    The form element has been reset, such as when a form reset button is pressed.

    onresize()

    The window’s size has been changed.

    onselect()

    The text of a form element has been selected.

    onsubmit()

    The form has been submitted.

    onunload()

    The document or frameset has been unloaded.

     
    DOM2 的進化:

    DOM 0 Event

    DOM 2 Event

    onblur()

    blur

    onfocus()

    focus

    onchange()

    change

    onmouseover()

    mouseover

    onmouseout()

    mouseout

    onmousemove()

    mousemove

    onmousedown()

    mousedown

    onmouseup()

    mouseup

    onclick()

    click

    ondblclick()

    dblclick

    onkeydown()

    keydown

    onkeyup()

    keyup

    onkeypress()

    keypress

    onsubmit()

    submit

    onload()

    load

    onunload()

    unload

     新的DOM2 用法可以addEventListener()這個函數來觀察到:

    addEventListener(event,function,capture/bubble);

    參數event如上表所示, function是要執行的函數, capture與bubble分別是W3C制定得兩種時間模式,簡單來說capture就是從document的開始讀到最後一行, 再執行事件, 而bubble則是先尋找指定的位置再執行事件.
    capture/bubble的參數是布林值, True表示用capture, False則是bubble.Windows Internet Explorer也有制定一種EventHandler, 是 attachEvent(), 格式如下:

    window.attachEvent(“submit”,myFunction());

    比較特別的是attachEvent不需要指定capture/bubble的參數, 因為在windows IE環境下都是使用Bubble的模式.這裡用圖像的Rollover例子來表現事件的用法:

    <!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01//EN”
    http://www.w3.org/TR/html4/strict.dtd“>
    <html>
    <head>
    <title>Rollover</title>
    <script type=”text/javascript”>function moveOver(imgObj) {
      if (typeof window.addEventListener != “undefined”) {
      imgObj.addEventListener(“mouseover”,function(){imgObj.src = imgObj.id +
    “_over.png”;}, false);
      imgObj.addEventListener(“mouseout”, function(){imgObj.src = imgObj.id +
    “_default.png”;}, false);
      } else {
      imgObj.attachEvent(“onmouseover”,function(){imgObj.src = imgObj.id +
    “_over.png”;});
      imgObj.attachEvent(“onmouseout”, function(){imgObj.src = imgObj.id +
    “_default.png”;});
      }
    }

    function rollover() {
    var images = document.getElementsByTagName(“img”);
    var roll = new RegExp (“rollover”);
    var preload = [];
    for (var i = 0; i < images.length; i++) {
      if (images[i].id.match(roll)) {
      preload[i] = new Image();
      preload[i].src = images[i].id + “_over.png”;

      moveOver(images[i]);
      }
    }
    }
    if (typeof window.addEventListener != “undefined”) {
      window.addEventListener(“load”,rollover,false);
    } else {
      window.attachEvent(“onload”,rollover)
    }
    </script>
    </head>
    <body>
    <p><img id=”rollover_home” name=”img_home” src=”rollover_home_default.png”
    alt=”Home”></p>
    <p><img id=”rollover_about” name=”img_about” src=”rollover_about_default.png”
    alt=”About”></p>
    <p><img id=”rollover_blog” name=”img_blog” src=”rollover_blog_default.png”
    alt=”Blog”></p>
    <p><img id=”logo” name=”img_logo” src=”logo.png” alt=”Braingia Logo”></p>
    </body>
    </html>

    上述的 typeof window.addEventListener != “undefined” 程式碼可以判斷使用者的瀏覽器是否支援AddEventListener這個事件模型, 如果不支援就使用attachEvent.

    W3C 及 IE 同時支援移除指定的事件, 用途是移除設定的事件, 格式分別如下:

    W3C格式:

    removeEventListener(event,function,capture/bubble);

    Windows IE的格式如下:

    detachEvent(event,function);

    資料參考: Chapter 14 – Browsers and JavaScript, JavaScript Step by Step, by Steve Suehring

    很棒的Javascript除錯程式

    一直以來Javascript的除錯都是非常煩人的步驟, 最近發現有個很棒的程式, 在這裡跟大家分享,

    FireBug

    這是Open Source軟體, 且完全免費, 是個搭配Firefox的Plugin, 它可以圖像化您的程式碼, 包括了HTML, CSS, 及javascript, 您可以通過它來觀看所有網頁, 不干擾您的瀏覽, 您也可以隨時把它關掉. 最棒的是它直接幫你把程式碼劃分好, 再除錯方面非常方便. 它佔的空間也很小喔~

    更過詳情可參考: http://getfirebug.com/

    [Outlook Express] 郵件太大, 出現對話框要求你壓縮郵件, 但你又不想把郵件壓縮怎麼辦?

    最近在處理用戶電腦時候遇到了以下的問題, 後來找到方法解決了, 在這裡做個紀錄:

    處理錯誤碼: 0x800C0133

    發生原因可參考: http://www.binbin.net/messages/qa_win_oe/0104.htm

    我的解決方式:

    Outlook Express有個天生的缺點, 就是當某個資料夾超過2G時便會在收件時出現錯誤訊息, 要求你先壓縮郵件, 以釋放空間, 但我個人是相當不建議把郵件壓縮起來, 因為往往會造成日後開不到, 那你2G的信就不見了(哭~)

    可是, 如果你不壓縮, “收件匣”又沒有辦法再接收新的郵件, 怎麼辦呢?

    我的作法如下:

    1.關閉Outlook Express.

    2. 到以下路徑:

    C:\Documents and Settings\Administrator\Local Settings\Application Data\Identities\{1936D57C-EA58-4C14-9A09-D10B5B2BFCF5}\Microsoft\Outlook Express

    3. 你就看到跟你的Outlook Express裡資料夾相同的.dbx檔, 包括了收件匣.dbx, 刪除的郵件.dbx, 寄件備份.dbx等等. 我們現在要做的事情就是把超過2G的”收件匣.dbx” 命名成其他的名字, 如: “收件匣1.dbx”.

    4.再度打開Outlook Express, 你就會發現可以收信了! 而且收件匣這個資料夾裡面是空的. (囧….之前的信都去哪裡了?)

    5. 不用擔心, 因為Outlook Express就是因為找不到原本的”收件匣.dbx”, 就自作主張幫你建立了一個新的 “收件匣.dbx”. 新的”收件匣.dbx”當然就是空的囉~

    那我要怎麼拿回以前的信件?

    6. 首先, 先在OutlookExpress的本機資料夾按右鍵, 選擇新增資料夾, 資料夾的名稱看你個人的喜好, 方便您辨識, 這裡舉例就叫做”2008″好了.

    7. 新增 “2008” 資料夾後, 因為裡面是空的, 在剛剛的目錄底下不會幫你產生 “2008.dbx”, 所以我們隨便將”收件匣”裡面的一封信複製到”2008″資料夾裡面. 在檢查看看, 目錄底下出現了新的 “2008.dbx” 了! 酷吧~

    8. 現在我們再把Outlook Express關掉.

    9. 到

    C:\Documents and Settings\Administrator\Local Settings\Application Data\Identities\{1936D57C-EA58-4C14-9A09-D10B5B2BFCF5}\Microsoft\Outlook Express

    10. 我們現在要騙系統說2008.dbx就是我們之前命名的”收件匣1.dbx”, 所以就把”2008.dbx”先刪掉, 再把”收件匣1.dbx”命名成 “2008.dbx”.

    11. 打開OutlookExpress, 你就會發現”2008″資料夾裡面多了很多信囉~這些信就是你之前2G爆掉的信啦~ 但值得提醒的是, Outlook Express 的資料夾極限大小是2G,所已表示這個2008資料夾很難在塞入更多的郵件, 建議您還是把它儘量分類出去, 保持在2G以下.

    維持良好的刪信, 信件分類的習慣才是最好的解決方法喔 ^_^

    希望可以幫助到大家.