2009年10月30日 星期五

取得物件的私有欄位、呼叫已經綁定在物件上的事件

要 using System.Reflection、System.ComponentModel、System.Text 三個命名空間
public string ListFields(Type type)
{
  StringBuilder sb = new StringBuilder();
  FieldInfo[] fieldInfos = type.GetFields(BindingFlags.Static | BindingFlags.NonPublic);
  sb.Append(@"<table border='1' cellpadding='3' cellspacing='0'><tr><th>Field Name</th>
              <th>Type</th><th>Static</th></tr>");
  foreach (FieldInfo fInfo in fieldInfos)
  {
    sb.AppendFormat("<tr><td>{0:s}</td><td>{1:s}</td><td>{2:s}</td></tr>",
      fInfo.Name, fInfo.FieldType.FullName, fInfo.IsStatic ? "Yes" : "No");
  }
  sb.Append("</table>");
  return sb.ToString();
}
這樣就可以把 type 裡面定義的私有欄位,用 Table 的方式顯示出來
如果私有欄位定義在 base class 中,則傳入 obj.GetType().BaseType
執行範例一: 
System.Web.UI.WebControls.FormView() FormView1 = new System.Web.UI.WebControls.FormView();
ListFields(FormView1.GetType());
Field Name Type Static
EventPageIndexChanged System.Object Yes
EventPageIndexChanging System.Object Yes
EventItemCommand System.Object Yes
EventItemCreated System.Object Yes
EventItemDeleted System.Object Yes
EventItemDeleting System.Object Yes
EventItemInserting System.Object Yes
EventItemInserted System.Object Yes
EventItemUpdating System.Object Yes
EventItemUpdated System.Object Yes
EventModeChanged System.Object Yes
EventModeChanging System.Object Yes
執行範例二: 
System.Web.UI.WebControls.DropDownList DopDownList1 = new System.Web.UI.WebControls.DropDownList();
ListFields(DropDownList1.GetType());
Field Name Type Static

??怎麼沒有東西??
那麼改用 ListFields(dropDownList1.GetType().BaseType) 試看看
Field Name Type Static
EventSelectedIndexChanged System.Object Yes
EventTextChanged System.Object Yes
果然有了!
拿到這些私有欄位的名稱有什麼用?各位發覺到了嗎,這些私有欄位都是以 Event 開頭的,也就是說這些是用來儲存 Delegate 的私有變數
接下來,就可以利用以下的程式,來呼叫「已經綁定在物件上的事件處理函式」
public void InvokeEvent(object obj, Type type, string eventName, EventArgs e)
{  
  PropertyInfo propertyInfo = (type.GetProperty("Events", BindingFlags.Instance | BindingFlags.NonPublic));
  EventHandlerList eventHandlerList = (EventHandlerList)propertyInfo.GetValue(obj, null);
  FieldInfo fieldInfo = type.GetField(eventName, BindingFlags.Static | BindingFlags.NonPublic);
  Delegate[] dels = eventHandlerList[fieldInfo.GetValue(null)].GetInvocationList();
  foreach (Delegate d in dels)
  {  
    d.Method.Invoke(d.Target, new object[] { obj, e });
  }
}
呼叫範例:
InvokeEvent(DropDownList1, DropDownList1.GetType().BaseType, "EventSelectedIndexChanged", e);

2009年6月17日 星期三

UpdatePanel 與 ValidationSummary 合併使用的注意事項

  1. Validator 以及由 Validator 驗證的控制項必須放在同一個 UpdatePanel 中
  2. ValidationSummary 也必須放在 UpdatePanel 中,可以跟 1 的不同

2009年4月17日 星期五

網路收音機 Ver0.61 更新事項

Ver 0.61 更新事項

  1. 因 HiChannel 修改了網路廣播的收聽方式,故作此更新
  2. 頻道下拉清單字體改小,以便更完整的顯示頻道名稱

WebRadio.xml 中修改的項目有:
  1. <URL ID="hinet"> 標籤的 URL 部份
  2. <CHANNEL> 標籤中,是由 HiChannel 提供服務的 SUBID 部份

老問題:用滑鼠點擊 Button 與按快速鍵行為不一致的解決方法

我們常常會將 Button.Caption 設定為像「&F. 檔案」這樣的內容,以便於將 Alt-F 快速鍵與 Button 連在一起
也常常會將一些輸入 Edit 的檢查,寫在 Edit.OnExit 事件處理函式中
假如這兩個碰在一起,就會發生用滑鼠點擊 Button 與按下快速鍵行為不一致的問題
因為按下快速鍵時,並不會轉移 Focus,會直接觸發事件處理函式,使得 Edit.OnExit 事件無法被觸發

解決方法如下:
於 Button.OnClick 事件處理函式的開頭加入以下兩行:

if (Sender as TWinControl).CanFocus then
  (Sender as TWinControl).SetFocus;

這樣強迫轉移 Focus,就可以解決這個問題了

2009年3月10日 星期二

Crystal Report 的民國100年問題

Crystal Report (8、9、11) 的日期物件,若選用「中華民國曆」格式的話,「年」只會出現兩位
使得民國 100 年變成了「00」
可以使用以下的公式來處理 (Crystal 語法)
Trim(CStr(Year(日期) - 1911, '#00')) + '/' + CStr(Month(日期), '00') + '/' + CStr(Day(日期), '00')

2012/03/06 更新:原先的版本沒有考慮到 null 的問題,改成以下這樣
if (aDate >= CDate('1899/12/31')) then
  Trim(CStr(Year(aDate) - 1911, '#00')) + '/' + CStr(Month(aDate), '00') + '/' +  CStr(Day(aDate), '00')
else
  ''

2009年3月4日 星期三

Delphi 2009 的函式說明自動完成模板

選擇 File -> New -> Other -> Code Template
將以下內容貼進去然後存檔
就可以按 Ctrl-J 選擇 summary,或是輸入 summary 之後按 Ctrl-J 自動出現函式說明的標籤了

<?xml version="1.0" encoding="utf-8" ?>
<codetemplate    xmlns="http://schemas.borland.com/Delphi/2005/codetemplates"
                version="1.0.0">
    <template name="summary" invoke="auto">
        <point name="comment">
            <hint>
                函數的說明文字
            </hint>
            <text/>
        </point>
        <description>
            Help Insight XML Documentation comment with "summary" element
        </description>
        <author>
            CodeGear
        </author>
        <code language="Delphi" context="methodbody" delimiter="|"><![CDATA[
/// <summary>
///   |comment|
/// </summary>
///   <param name="">
///   </param>
///   <param name="">
///   </param>
///   <param name="">
///   </param>
/// <returns>
/// </returns>
/// <remarks>
/// </remarks>]]>
        </code>
    </template>
</codetemplate>

2008年11月14日 星期五

網路收音機 Ver 0.6

愛用 Hinet 網路收音機聽廣播的朋友們,請試試這個小程式

主視窗
01
主視窗的工具列由左而右是:
頻道選擇、透明度滑桿、關於此程式、切換顯示媒體播放器介面、隱藏主視窗

隱藏收音機介面之後,是這樣的
02

工具列圖示
03

工具列選單
04

關於此程式
05

要換頻道,可以從主視窗選擇,也可以從工具列選單的「頻道」去選擇 要結束,請從工具列選單選擇「離開」 程式關閉時,會記住:

  1. 上次聽的頻道
  2. 收音機介面是否隱藏
  3. 主視窗是否隱藏
  4. 透明度
  5. 視窗位置
手動增加頻道方法:
  1. 增加頻道供應者
    這部份存放在 WebRadio.xml 的 <URLS> 與 </URLS> 之間,每一個頻道供應者是一個 <URL> 標籤,裡面有兩個屬性:ID 與 URL
    附上的檔案,除了 Hinet 之外,還有 difm 與 skyfm 兩家網路頻道供應者 如果要自行增加其他頻道供應者的話,請依照以下原則
    ● ID 是這個頻道供應者的 ID,你可以自己取名字,但不可以重複
    ● URL 是收聽連結的固定部份,要依照實際狀況而定
    以 difm 為例,difm 的收聽連結是這樣的:http://www.di.fm/wma/xxxxx.asx 變動的部份只有 xxxxx.asx ,而 http://www.di.fm/wma/ 是不變的,所以 URL 屬性的值就是 http://www.di.fm/wma/
  2. 增加頻道資料
    這部份存放在 WebRadio.xml 的 <CHANNELS> 與 </CHANNELS> 之間,每一個頻道是一個 <CHANNEL> 標籤,裡面有四個屬性:ID、TEXT、URLID、SUBID
    ● ID 是這個頻道的編號,不可以重複
    ● TEXT 是這個頻道的名字
    ● URLID 是這個頻道的供應者 ID
    ● SUBID 是收聽連結的變動部份
    以 <CHANNEL ID="difm.electro" TEXT="Electro House" URLID="difm" SUBID="electro.asx"/> 這一行為例
    ● ID="difm.electro" 這是自己取的 ID
    ● TEXT="Electro House" 這是頻道的名字
    ● URLID="difm" 這是頻道供應者的ID,用這個ID取得收聽連結的固定部份
    ● SUBID="electro.asx" 這是收聽連結的變動部份

歡迎給予本人意見。謝謝指教! 下載連結