為什麼需要寫 finally那段
try
{
}
catch (Exception e)
{
}
finally
{
DoSomeClose();
}
如果寫成
try
{
}
catch (Exception e)
{
}
DoSomeClose();
不也一樣嗎?我就是要在try catch之後去執行DoSomeClose();
事實上確實不同,finally確實有其特別之處
少了他,如果try或catch之中,有直接寫了return
那就不會執行DoSomeClose();
finally則會強制在你即便要return跳離開這段程式碼之前,也會先執行finally裡面的程式的
我喜歡設計,我喜歡創造,我喜歡美 不論軟體設計,不論介面設計,不論產品規劃設計,我都很有興趣 一直希望能能用這份專長,好好發揮在職場上。讓我做的快樂。 不論寫程式,或是做美工,我都很喜歡,希望我可以有機會雙線。兩種都很擅長。
2015年7月29日 星期三
2015年5月19日 星期二
ref 與 out 修飾詞的比較
1.方法參數宣告為ref與out時,在編譯時視為相同。(同樣的方法,用ref ,另外一個用out並不會被視為多型)
4.out參數在方法結束之前,要先初始化完畢。(當呼叫宣告為out參數的方法時,不管變數有沒有初始化,都可以傳入方法中執行,只要在方法結束前,方法內參數有初始化,就不會出現編譯錯誤。)
5.ref 不會強制要求函式內的程式,一定要修改傳入的參數,但 out 會。
2.ref與out,都是將參數以ByRef方式傳遞。
3.ref參數在傳入方法之前,要先初始化完畢。
4.out參數在方法結束之前,要先初始化完畢。(當呼叫宣告為out參數的方法時,不管變數有沒有初始化,都可以傳入方法中執行,只要在方法結束前,方法內參數有初始化,就不會出現編譯錯誤。)
5.ref 不會強制要求函式內的程式,一定要修改傳入的參數,但 out 會。
2015年5月14日 星期四
C# 中如何將控制項陣列化
C# 如果要做到類似VB那種一大堆控制項陣列的方式來使用控制項
做法如下
先在Form視窗元件上面拉出要使用的控制項
假設要用4個元件,就拉4個出來
然後撰寫以下的程式碼(假設拉出來四個Label。名稱分別是label1 ~ label4)
Label[] Lbl_Shade = new Label[] { label1, label2, label3, label4 };
之後就可以如下的方式來使用
Lbl_Shade[0].Text = "001";
Lbl_Shade[1].Text = "002";
Lbl_Shade[2].Text = "003";
Lbl_Shade[3].Text = "004";
這樣比一個一個名稱來控制方便多了。
做法如下
先在Form視窗元件上面拉出要使用的控制項
假設要用4個元件,就拉4個出來
然後撰寫以下的程式碼(假設拉出來四個Label。名稱分別是label1 ~ label4)
Label[] Lbl_Shade = new Label[] { label1, label2, label3, label4 };
之後就可以如下的方式來使用
Lbl_Shade[0].Text = "001";
Lbl_Shade[1].Text = "002";
Lbl_Shade[2].Text = "003";
Lbl_Shade[3].Text = "004";
這樣比一個一個名稱來控制方便多了。
2014年5月19日 星期一
C# 取得程式路徑的幾個方法
1.獲取和設置當前目錄的完全限定路徑。
string str = System.Environment.CurrentDirectory;
Result: C:\xxx\xxx
2.獲取啟動了應用程序的可執行文件的路徑,不包括可執行文件的名稱。
string str = System.Windows.Forms.Application.StartupPath;
Result: C:\xxx\xxx
3.獲取新的 Process 組件並將其與當前活動的進程關聯的主模塊的完整路徑,包含文件名。
string str = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
Result: C:\xxx\xxx\xxx.exe
4.獲取當前 Thread 的當前應用程序域的基目錄,它由程序集衝突解決程序用來探測程序集。
string str = System.AppDomain.CurrentDomain.BaseDirectory;
Result: C:\xxx\xxx\
5.獲取應用程序的當前工作目錄。
string str = System.IO.Directory.GetCurrentDirectory();
Result: C:\xxx\xxx
6.獲取和設置包含該應用程序的目錄的名稱。
string str = System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
Result: C:\xxx\xxx\
7.獲取當前進程的完整路徑,包含文件名。
string str = this.GetType().Assembly.Location;
Result: C:\xxx\xxx\xxx.exe
8.獲取啟動了應用程序的可執行文件的路徑,包括可執行文件的名稱。string str = System.Windows.Forms.Application.ExecutablePath;
Result: C:\xxx\xxx\xxx.exe
string str = System.Environment.CurrentDirectory;
Result: C:\xxx\xxx
2.獲取啟動了應用程序的可執行文件的路徑,不包括可執行文件的名稱。
string str = System.Windows.Forms.Application.StartupPath;
Result: C:\xxx\xxx
3.獲取新的 Process 組件並將其與當前活動的進程關聯的主模塊的完整路徑,包含文件名。
string str = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
Result: C:\xxx\xxx\xxx.exe
4.獲取當前 Thread 的當前應用程序域的基目錄,它由程序集衝突解決程序用來探測程序集。
string str = System.AppDomain.CurrentDomain.BaseDirectory;
Result: C:\xxx\xxx\
5.獲取應用程序的當前工作目錄。
string str = System.IO.Directory.GetCurrentDirectory();
Result: C:\xxx\xxx
6.獲取和設置包含該應用程序的目錄的名稱。
string str = System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase;
Result: C:\xxx\xxx\
7.獲取當前進程的完整路徑,包含文件名。
string str = this.GetType().Assembly.Location;
Result: C:\xxx\xxx\xxx.exe
8.獲取啟動了應用程序的可執行文件的路徑,包括可執行文件的名稱。string str = System.Windows.Forms.Application.ExecutablePath;
Result: C:\xxx\xxx\xxx.exe
2012年12月25日 星期二
WPF DataBinding 資料繫結簡介
我想有兩種狀況會有這個需求。
1.如果你需要資料跟UI元件能即時隨時的互動,隨著資料改變,UI的顯示就跟著變(或者反向),這時候,你就需要他。
2.如果你需要在Thread或Task中顯示目前進行的狀況或是任何資訊在某種UI元件上,比方Label, TextBlock,為了避免跨執行緒UI操作這種神秘又討厭的Exception,而你又不想為此作Delegate,這時候,你也可以靠他幫助。
在WPF上的作法有兩種,一種是把Bnding寫在 XML 裡,一種是寫在C#程式裡,差異不大,因為最後資料的顯示也都用程式在控制居多。
首先,建立一個WPF 應用程式專案,然後在視窗上放一個按鈕、一個TextBlock、一個TextBox。名稱Name分別取為Btn_Bind、TxtBlk_Bind、TxtBx_Bind。位置隨便你放,能看得到就好了。
接下來,在程式當中,新增一個繼承INotifyPropertyChanged的Class,並且給他一個Member(當然,如果你有多個元件要跟多組數值作Binding,這裡就可以有多個Member),固定寫法如下,當Member要寫入新值,在set當中呼叫OnPropertyChanged(),他會產生PropertyChangedEventHandler 的事件,因此可讓UI可以知道該更新顯示了。
public class MyData : INotifyPropertyChanged
{
private string m_TextMsg;
public string TextMsg
{
set
{
if ( m_TextMsg != value )
{
m_TextMsg = value;
OnPropertyChanged( "TextMsg" );
}
}
get
{
return m_TextMsg;
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged( string propertyName )
{
if ( PropertyChanged != null )
{
PropertyChanged( this, new PropertyChangedEventArgs( propertyName ) );
}
}
}
另外準備好按鈕的事件內容
private void Bind_Click( object sender, RoutedEventArgs e )
{
m_MyData.TextMsg = "New Value";
}
然後在CS檔中宣告一個全域變數,把你剛剛的INotifyPropertyChanged類型的Class宣告好
private MyData m_MyData ;
以上都準備好之後,開始進行Binding
XML會變成類似底下這樣:
<TextBlock x:Name="TxtBlk_Bind" HorizontalAlignment="Center" Margin="134,130,136,140" TextWrapping="Wrap" VerticalAlignment="Center" Height="50" Width="247" FontSize="20" Text="{Binding Path=TextMsg }" TextAlignment="Center"/>
<TextBox x:Name="TxtBx_Bind" HorizontalAlignment="Left" Height="44" Margin="134,210,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="248" FontSize="20" Text="{Binding Path=TextMsg }"/>
<Button x:Name="Btn_Bind" Content="改變數值" HorizontalAlignment="Left" Height="37" Margin="134,62,0,0" VerticalAlignment="Top" Width="99" Click="Bind_Click"/>
最後用程式告訴系統,你的Binding是哪一個
TxtBlk_Bind.DataContext = m_BindData;
TxtBx_Bind.DataContext = m_BindData;
(能不能把上面兩段寫成XAML呢?其實是可以的,可是,寫來頗複雜,而且還不知道要怎麼讓CS引用這個變數)
如此,你的TxtBlk_Bind跟TxtBx_Bind兩個元件就跟m_BindData 內的TextMsg 有了互動
不相信?你可以按下按鈕,就會看到TxtBlk_Bind跟TxtBx_Bind元件都變成了"New Value",而如果你在TxtBx_Bind輸入任何文字,然後按下[Tab]鍵,就可以看到TxtBlk_Bind也會跟著變成你輸入的東西了。(這是因為TxtBx_Bind輸入的數值會同步變更BindData內的TextMsg 數值,然後在同步更新到TxtBlk_Bind元件。
XML不用改,只要在程式當中加上底下四行:
Binding BindingTxtBlk = new Binding() { Source = m_MyData , Path = new PropertyPath( "TextMsg" ) };
TxtBlk_Bind.SetBinding( TextBlock.TextProperty, BindingTxtBlk );
Binding BindingTxtBx = new Binding() { Source = m_MyData , Path = new PropertyPath( "TextMsg" ) };
TxtBx_Bind.SetBinding( TextBox.TextProperty, BindingTxtBx );
太棒了,對吧!
我喜歡第二種,因為不用動到XML,感覺也挺直覺的。
1.如果你需要資料跟UI元件能即時隨時的互動,隨著資料改變,UI的顯示就跟著變(或者反向),這時候,你就需要他。
2.如果你需要在Thread或Task中顯示目前進行的狀況或是任何資訊在某種UI元件上,比方Label, TextBlock,為了避免跨執行緒UI操作這種神秘又討厭的Exception,而你又不想為此作Delegate,這時候,你也可以靠他幫助。
在WPF上的作法有兩種,一種是把Bnding寫在 XML 裡,一種是寫在C#程式裡,差異不大,因為最後資料的顯示也都用程式在控制居多。
首先,建立一個WPF 應用程式專案,然後在視窗上放一個按鈕、一個TextBlock、一個TextBox。名稱Name分別取為Btn_Bind、TxtBlk_Bind、TxtBx_Bind。位置隨便你放,能看得到就好了。
接下來,在程式當中,新增一個繼承INotifyPropertyChanged的Class,並且給他一個Member(當然,如果你有多個元件要跟多組數值作Binding,這裡就可以有多個Member),固定寫法如下,當Member要寫入新值,在set當中呼叫OnPropertyChanged(),他會產生PropertyChangedEventHandler 的事件,因此可讓UI可以知道該更新顯示了。
public class MyData : INotifyPropertyChanged
{
private string m_TextMsg;
public string TextMsg
{
set
{
if ( m_TextMsg != value )
{
m_TextMsg = value;
OnPropertyChanged( "TextMsg" );
}
}
get
{
return m_TextMsg;
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged( string propertyName )
{
if ( PropertyChanged != null )
{
PropertyChanged( this, new PropertyChangedEventArgs( propertyName ) );
}
}
}
另外準備好按鈕的事件內容
private void Bind_Click( object sender, RoutedEventArgs e )
{
m_MyData.TextMsg = "New Value";
}
然後在CS檔中宣告一個全域變數,把你剛剛的INotifyPropertyChanged類型的Class宣告好
private MyData m_MyData ;
然後在程式進入點函式中加入底下,產生物件實體與給予初始值
m_MyData = new MyData();
m_MyData .TextMsg = "Origin";
以上都準備好之後,開始進行Binding
第一種方法:在XML加入Binding 片段
<TextBlock x:Name="TxtBlk_Bind" HorizontalAlignment="Center" Margin="134,130,136,140" TextWrapping="Wrap" VerticalAlignment="Center" Height="50" Width="247" FontSize="20" Text="{Binding Path=TextMsg }" TextAlignment="Center"/>
<TextBox x:Name="TxtBx_Bind" HorizontalAlignment="Left" Height="44" Margin="134,210,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="248" FontSize="20" Text="{Binding Path=TextMsg }"/>
<Button x:Name="Btn_Bind" Content="改變數值" HorizontalAlignment="Left" Height="37" Margin="134,62,0,0" VerticalAlignment="Top" Width="99" Click="Bind_Click"/>
最後用程式告訴系統,你的Binding是哪一個
TxtBlk_Bind.DataContext = m_BindData;
TxtBx_Bind.DataContext = m_BindData;
(能不能把上面兩段寫成XAML呢?其實是可以的,可是,寫來頗複雜,而且還不知道要怎麼讓CS引用這個變數)
如此,你的TxtBlk_Bind跟TxtBx_Bind兩個元件就跟m_BindData 內的TextMsg 有了互動
不相信?你可以按下按鈕,就會看到TxtBlk_Bind跟TxtBx_Bind元件都變成了"New Value",而如果你在TxtBx_Bind輸入任何文字,然後按下[Tab]鍵,就可以看到TxtBlk_Bind也會跟著變成你輸入的東西了。(這是因為TxtBx_Bind輸入的數值會同步變更BindData內的TextMsg 數值,然後在同步更新到TxtBlk_Bind元件。
第二種方法:完全在程式中完成Binding
XML不用改,只要在程式當中加上底下四行:
Binding BindingTxtBlk = new Binding() { Source = m_MyData , Path = new PropertyPath( "TextMsg" ) };
TxtBlk_Bind.SetBinding( TextBlock.TextProperty, BindingTxtBlk );
Binding BindingTxtBx = new Binding() { Source = m_MyData , Path = new PropertyPath( "TextMsg" ) };
TxtBx_Bind.SetBinding( TextBox.TextProperty, BindingTxtBx );
太棒了,對吧!
我喜歡第二種,因為不用動到XML,感覺也挺直覺的。
2012年1月12日 星期四
C# Dictionary的用法,以及查字典的用途
什麼是Dictionary?他是個很簡單的東西,概念跟字典有點類似沒錯,如果我有10組鑰匙,跟10組物品,且滿足兩個條件,一、每個鑰匙不重複,二、每個鑰匙配一個物品。(物品可以長的一樣,比方第一個物品跟第六個物品都是一樣的杯子,只要能夠不會讓鑰匙沒有搭配的物品,或兩把鑰匙搭配到同一個物品就行了。)那接下來,你問Dictionary,某一把鑰匙,他就會告訴你對應的物品是什麼。我們看一下範例程式片段:
Dictionary<string, string> MyDic = new Dictionary<string, string>( );
// 建立字典
private void CreateDictionary( )
{
MyDic.Add( "Name", "Jack" );
MyDic.Add( "Blog", "Jack’s Blog" );
MyDic.Add( "Group", "KTV Group" );
}
// 查字典
private String FindInDictionary( String FindMe )
{
if ( true == ( MyDic.ContainsKey( FindMe ) ) )
{
return MyDic[ FindMe ];
}
else
{
return "Not Found";
}
}
// 巡整個字典
private void ShowAllInDictionary( )
{
foreach ( var OneItem in MyDic )
{
Console.WriteLine( "Key = " + OneItem.Key + ", Value = " + OneItem.Value );
}
}
除了上面那種先宣告再Add的方式之外,也可以用底下的方式來直接宣告並產生內容
Dictionary<string, string> dctNewWay =
new Dictionary<string, string>()
{
{"Key1", "AAAA"}, {"Key2", "BBBB"},
{"Key3", "CCCC"}, {"Key4", "DDDD"}
};
另外,值得一提的是,Key跟Value並不限定只能用String,什麼型別都可以,所以你也可以把Class塞到Value,然後其中一個屬性拿出來當作Key,就可以方便的確認有沒有重複的Key,不用塞到SQL才知道。
2012年1月10日 星期二
C# 嵌入檔案,包在EXE裡
圖檔可以透過加入Resource的方式來使用,那其他檔案呢?有一種方便的嵌入方式可以把想要的檔案夾在你產生的EXE中,從專案中選擇「加入」、「現有項目」、然後從檔案對話框當中更改檔案類型為*.*,點選你想要的檔案,可加入專案中。
接下來,在方案總管中選擇該檔案,在屬性視窗將「建置動作」改為「內嵌資源」,這樣就可以讓程式碼引用,程式碼如下。
// 從專案組件讀入檔案到磁碟
Assembly Asmb = Assembly.GetExecutingAssembly( );
Stream ManifestStream = Asmb.GetManifestResourceStream( Asmb.GetName( ).Name + ".Update_Downloader.exe" );
// 讀入檔案
byte[] StreamData = new byte[ ManifestStream.Length ];
ManifestStream.Read( StreamData, 0, (int)ManifestStream.Length );
// 存到磁碟
FileStream FileStm = new FileStream( ExeFileName, FileMode.Create );
FileStm.Write( StreamData, 0, (int)ManifestStream.Length );
FileStm.Close( );
2012年1月9日 星期一
C#角度看XML格式讀取
XML以程式語言的角度來看的目的是什麼?就是為了知道怎麼讀寫,怎麼解析內容
讀寫的方式有很多種,XmlReader, XmlDocument......能控制的角度,能使用的函式也有不同
在此先介紹 XmlDocument
先將 XmlDocument 產生物件之後,可呼叫 Load() 來載入 XML 檔,如果用 LoadXml() 則可以由字串來讀入,也就是一個傳入路徑,一個傳入String,之後便透過節點的方式,指定要讀取哪一個階層的節點們,然後用迴圈逐一的將內容讀取出來,以下為簡單的範例程式
XmlDocument XmlDoc = new XmlDocument( );
XmlDoc.Load( @"C:\XmlFileName.XML" );
XmlNodeList NodeLists = XmlDoc.SelectNodes( "Root/MyLevel1" );
foreach ( XmlNode OneNode in NodeLists )
{
String StrAttrName = OneNode.Attributes.Name;
String StrAttrValue = OneNode.Attributes[ " MyAttr1 " ].Value;
String StrAttrValue = OneNode.InnerText;
}
如此便可將 <MyLevel1> 這一層的節點都抓出來,下面這個XML範例來抓應該會抓到五個,然後讀取每一個的 MyAttr1 屬性的內容以及Node的InnerText。(備註:但是這樣的作法,是固定的沒有彈性的,必須每個<MyLevel1>節點都要具備MyAttr1,否則就會有Exception,而某個Node如果有多個Attribute則不會讀取到)。同樣的,如果用XmlNodeList NodeLists = XmlDoc.SelectNodes( "Root/MyLevel1/MyLevel2" );就可以讀取這層的四個節點了。 接下來,我們看看XML的格式
<?xml version="1.0" encoding="utf-8"?>
<Root>
<MyLevel1 MyAttr1 = "aaaaa" > WXYZ
<MyLevel2 MyAttr10 = "UUUUUUUUU" />
<MyLevel2 MyAttr10 = "KKKKKKKKK" >QWER</MyLevel2>
</MyLevel1>
<MyLevel1 MyAttr1 = "aaaaa" > WXYZ
<MyLevel2 MyAttr10 = "VVVVVVVVV" />
<MyLevel2 MyAttr10 = "PPPPPPPPP" >QWER</MyLevel2>
</MyLevel1>
<MyLevel1 MyAttr1 = "bbbbb" MyAttr2 = "bbbbb"/>
<MyLevel1 MyAttr1 = "UUUUUUUUU" />
</Root>
Root是根節點,一個檔案只能有一個,接下來,每個<>所括住的都是一個節點,並且分層次存在,層次的分法,是相同的標記如果用<>與</>來分兩行來包住其他的<>節點,那這些被包起來的,就會是下一層。而每個節點可以有Attributes,每個屬性可以存放一個數值(或字串),而如果節點的表示法用 用<>與</>來表示,且中間夾了數值(或字串),則這個稱為InnerText。(備註:另外還有InnerXml,這個是包含子節點都算進去,有點複雜,也可先不理會),所以用程式來讀取其Attributes的Value,或是讀取InnerText,在轉成需要的格式,就是XML的讀取應用方式了,
接下來,挑戰一下有難度的格式吧!!
<?xml version="1.0" encoding="utf-8"?>
<Root>
<MyLevel1 MyAttr1 = "aaaaa" > WXYZ
<MyLevel2 MyAttr100 = "第二層01" />
<MyLevel2>IN_002</MyLevel2>
</MyLevel1>
<MyLevel1 MyAttr1 = "bbbbb" > WXYZ
<MyLevel2 MyAttr100 = "第二層02" MyAttr101 = "第二層002" />
<MyLevel2>IN_003</MyLevel2>
</MyLevel1>
<MyLevel1 MyAttr1 = "ccccc" > WXYZ
<MyLevel3 MyAttr100 = "第二層03" />
<MyLevel3>IN_004</MyLevel3>
</MyLevel1>
<MyLevel1 MyAttr1 = "ddddd" > WXYZ
<MyLevel2 MyAttr100 = "第二層04" />
<MyLevel2>IN_005</MyLevel2>
</MyLevel1>
<YouLevel1 MyAttr1 = "ddddd" > WXYZ
<MyLevel2 MyAttr100 = "第二層05" />
<MyLevel2>IN_006</MyLevel2>
</YouLevel1>
<MyLevel1 MyAttr1 = "bbbbb" MyAttr2 = "bbbbb"/>
<MyLevel1 MyAttr10 = "UUUUUUUUU" />
<MyLevel1>IN_007</MyLevel1>
</Root>
不管他格式多複雜,用以下的方式,就可以讀取節點的每個Attribute,以及InnerText了,且,不會去嘗試讀取不存在的Attribute,所以不會發生Exception。
foreach ( XmlNode OneNode in NodeLists )
{
String StrNodeName = OneNode.Name.ToString();
foreach ( XmlAttribute Attr in OneNode.Attributes )
{
String StrAttr = Attr.Name.ToString( );
String StrValue = OneNode.Attributes[ Attr.Name.ToString( ) ].Value;
String StrInnerText = OneNode.InnerText;
}
}
再來,就是怎麼選擇要讀取哪一層,如果用以下的方式會讀取在Root底下的MyLevel1底下的MyLevel2,對,MyLevel3就不會被讀取了。還有YouLevel1底下的MyLevel2也不會被讀取,
所以會讀取到6個節點。
XmlNodeList NodeLists = XmlDoc.SelectNodes( "Root/MyLevel1/MyLevel2" );
如果用以下的方式會讀取在Root底下的MyLevel1 ,則會讀取到7個節點
XmlNodeList NodeLists = XmlDoc.SelectNodes( "Root/MyLevel1" );
讀寫的方式有很多種,XmlReader, XmlDocument......能控制的角度,能使用的函式也有不同
在此先介紹 XmlDocument
先將 XmlDocument 產生物件之後,可呼叫 Load() 來載入 XML 檔,如果用 LoadXml() 則可以由字串來讀入,也就是一個傳入路徑,一個傳入String,之後便透過節點的方式,指定要讀取哪一個階層的節點們,然後用迴圈逐一的將內容讀取出來,以下為簡單的範例程式
XmlDocument XmlDoc = new XmlDocument( );
XmlDoc.Load( @"C:\XmlFileName.XML" );
XmlNodeList NodeLists = XmlDoc.SelectNodes( "Root/MyLevel1" );
foreach ( XmlNode OneNode in NodeLists )
{
String StrAttrName = OneNode.Attributes.Name;
String StrAttrValue = OneNode.Attributes[ " MyAttr1 " ].Value;
String StrAttrValue = OneNode.InnerText;
}
如此便可將 <MyLevel1> 這一層的節點都抓出來,下面這個XML範例來抓應該會抓到五個,然後讀取每一個的 MyAttr1 屬性的內容以及Node的InnerText。(備註:但是這樣的作法,是固定的沒有彈性的,必須每個<MyLevel1>節點都要具備MyAttr1,否則就會有Exception,而某個Node如果有多個Attribute則不會讀取到)。同樣的,如果用XmlNodeList NodeLists = XmlDoc.SelectNodes( "Root/MyLevel1/MyLevel2" );就可以讀取這層的四個節點了。 接下來,我們看看XML的格式
<?xml version="1.0" encoding="utf-8"?>
<Root>
<MyLevel1 MyAttr1 = "aaaaa" > WXYZ
<MyLevel2 MyAttr10 = "UUUUUUUUU" />
<MyLevel2 MyAttr10 = "KKKKKKKKK" >QWER</MyLevel2>
</MyLevel1>
<MyLevel1 MyAttr1 = "aaaaa" > WXYZ
<MyLevel2 MyAttr10 = "VVVVVVVVV" />
<MyLevel2 MyAttr10 = "PPPPPPPPP" >QWER</MyLevel2>
</MyLevel1>
<MyLevel1 MyAttr1 = "bbbbb" MyAttr2 = "bbbbb"/>
<MyLevel1 MyAttr1 = "UUUUUUUUU" />
</Root>
Root是根節點,一個檔案只能有一個,接下來,每個<>所括住的都是一個節點,並且分層次存在,層次的分法,是相同的標記如果用<>與</>來分兩行來包住其他的<>節點,那這些被包起來的,就會是下一層。而每個節點可以有Attributes,每個屬性可以存放一個數值(或字串),而如果節點的表示法用 用<>與</>來表示,且中間夾了數值(或字串),則這個稱為InnerText。(備註:另外還有InnerXml,這個是包含子節點都算進去,有點複雜,也可先不理會),所以用程式來讀取其Attributes的Value,或是讀取InnerText,在轉成需要的格式,就是XML的讀取應用方式了,
接下來,挑戰一下有難度的格式吧!!
<?xml version="1.0" encoding="utf-8"?>
<Root>
<MyLevel1 MyAttr1 = "aaaaa" > WXYZ
<MyLevel2 MyAttr100 = "第二層01" />
<MyLevel2>IN_002</MyLevel2>
</MyLevel1>
<MyLevel1 MyAttr1 = "bbbbb" > WXYZ
<MyLevel2 MyAttr100 = "第二層02" MyAttr101 = "第二層002" />
<MyLevel2>IN_003</MyLevel2>
</MyLevel1>
<MyLevel1 MyAttr1 = "ccccc" > WXYZ
<MyLevel3 MyAttr100 = "第二層03" />
<MyLevel3>IN_004</MyLevel3>
</MyLevel1>
<MyLevel1 MyAttr1 = "ddddd" > WXYZ
<MyLevel2 MyAttr100 = "第二層04" />
<MyLevel2>IN_005</MyLevel2>
</MyLevel1>
<YouLevel1 MyAttr1 = "ddddd" > WXYZ
<MyLevel2 MyAttr100 = "第二層05" />
<MyLevel2>IN_006</MyLevel2>
</YouLevel1>
<MyLevel1 MyAttr1 = "bbbbb" MyAttr2 = "bbbbb"/>
<MyLevel1 MyAttr10 = "UUUUUUUUU" />
<MyLevel1>IN_007</MyLevel1>
</Root>
不管他格式多複雜,用以下的方式,就可以讀取節點的每個Attribute,以及InnerText了,且,不會去嘗試讀取不存在的Attribute,所以不會發生Exception。
foreach ( XmlNode OneNode in NodeLists )
{
String StrNodeName = OneNode.Name.ToString();
foreach ( XmlAttribute Attr in OneNode.Attributes )
{
String StrAttr = Attr.Name.ToString( );
String StrValue = OneNode.Attributes[ Attr.Name.ToString( ) ].Value;
String StrInnerText = OneNode.InnerText;
}
}
再來,就是怎麼選擇要讀取哪一層,如果用以下的方式會讀取在Root底下的MyLevel1底下的MyLevel2,對,MyLevel3就不會被讀取了。還有YouLevel1底下的MyLevel2也不會被讀取,
所以會讀取到6個節點。
XmlNodeList NodeLists = XmlDoc.SelectNodes( "Root/MyLevel1/MyLevel2" );
如果用以下的方式會讀取在Root底下的MyLevel1 ,則會讀取到7個節點
XmlNodeList NodeLists = XmlDoc.SelectNodes( "Root/MyLevel1" );
2012年1月6日 星期五
C# 透過HTTP抓檔案回來
在Window視窗上放一個Button,一個ProgressBar,一個TextBlock(用來顯示ProgressBar的數值)
利用以下的函式,可以完成
private void Btn_http_Click( object sender, RoutedEventArgs e )
{
// 非同步
WebClient MyWebClient = new WebClient( );
MyWebClient.DownloadFileCompleted += new AsyncCompletedEventHandler( Http_Completed );
MyWebClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler( Http_ProgressChanged );
MyWebClient.DownloadFileAsync( new Uri( "http://www.joyplux.net/xplayer/download/JoyeDM/JoyeDMDownload_Setup.exe" ), @"c:\temp\JoyeDM.exe" );
}
private void Http_ProgressChanged( object sender, DownloadProgressChangedEventArgs e )
{
PgBar_Http.Value = e.ProgressPercentage; //控制ProcessBar顯示進度
TxtBk_Percent.Text = e.ProgressPercentage + "%";
}
private void Http_Completed( object sender, AsyncCompletedEventArgs e )
{
MessageBox.Show( "Download completed!" );
}
利用以下的函式,可以完成
private void Btn_http_Click( object sender, RoutedEventArgs e )
{
// 非同步
WebClient MyWebClient = new WebClient( );
MyWebClient.DownloadFileCompleted += new AsyncCompletedEventHandler( Http_Completed );
MyWebClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler( Http_ProgressChanged );
MyWebClient.DownloadFileAsync( new Uri( "http://www.joyplux.net/xplayer/download/JoyeDM/JoyeDMDownload_Setup.exe" ), @"c:\temp\JoyeDM.exe" );
}
private void Http_ProgressChanged( object sender, DownloadProgressChangedEventArgs e )
{
PgBar_Http.Value = e.ProgressPercentage; //控制ProcessBar顯示進度
TxtBk_Percent.Text = e.ProgressPercentage + "%";
}
private void Http_Completed( object sender, AsyncCompletedEventArgs e )
{
MessageBox.Show( "Download completed!" );
}
2011年12月20日 星期二
C#的委派與事件的使用
委派跟事件,一直是蠻難真正搞懂的一個概念,但是對UI寫作的人或是開發控制項的人來說,卻又經常用到,我想寫系統的人或許也有機會碰到吧,過去一段時間,我一直沒辦法完全搞懂,甚至只是很皮毛的瞭解就拿來用了。為了讓自己更有概念一點,這次花了些時間學習,記錄如下。
◆什麼時候會用到委派?
有兩種狀況:
1.你要寫一個Class或Interface,其中有個函式,會讓別的Class呼叫(注意,是Class,不是Instance喔)。也就是在撰寫類別的時候,就能夠呼叫非實體的函式。
2.你要寫一個Class或Interface,其中有個函式,會達成某種特別功能,但是,寫的時候,你並不知道這個功能會怎麼完成,好比說,你這個Class是個登入的介面或Model,但是密碼驗證的部分,是你提供方法出來,給要使用你這個Class的人,到時候要實作函式內容的(將委派綁定函式)。
當你撰寫一個Class裡面需要呼叫該Class無法呼叫到的函式(當然,就不是這個Class宣告的函式囉)的時候,就會需要用到委派,而什麼情況下Class無法呼叫某個函式呢?我們先看看,什麼情況下,Class可以呼叫非Class自己的函式呢?比方有兩個Class,一個是ClassA一個是ClassB,如果在ClassA中宣告產生了ClassB,那麼ClassB的函式就可以被ClassA呼叫(如果宣告成Public或是有封裝出來),這是物件導向的基本概念,相信大家都懂,但是,如果ClassB想呼叫ClassA的函式呢?那就做不到了。程式如下:
Class ClassA
{
public void RunClassA()
{
ClassB MyClassB = new ClassB();
MyClassB.MethodB();
}
public void MethodA()
{
Console.WriteLine( "MethodA被呼叫了" );
}
}
Class ClassB
{
public void RunClassB()
{
ClassA.MethodA();
}
public void MethodB()
{
Console.WriteLine( "MethodB被呼叫了" );
}
}
上述紅底的那一行,就是無法做到的,因為ClassB沒有宣告ClassA,對ClassB來說,他不曉得ClassA是什麼,那麼,如果在ClassB也宣告一個ClassA呢?那麼A中有B,B中又有A,A中又有B,無限循環下去記憶體會吃光光,這種怪程式應該無法跑不下去,有解決方法嗎?有啊,除了用Static來做,或是把ClassA傳進來給ClassB......但是,有時候ClassA不是你寫的,你沒辦法預期人家怎麼做,但是卻又有這種需求,這時候就需要委派了。
◆委派怎麼做呢?
先不要講程式,免得把人搞昏了,概念上,就是ClassB這邊,宣告一個叫做「委派」的東西,這個委派,可以讓ClassB被別人宣告使用的時候,也同時可以使用這個委派,透過特殊的語法,在ClassA把委派跟某個函式綁在一起,這樣只要有人(不論ClassB或ClassA都可以)叫這個委派做事,這個委派就會去找到這個函式,然後執行,這樣ClassB就可以呼叫到ClassA了,聽起來似乎落落長,實際上不難,我們來看看怎麼做。
再稍微細節一點來看,這個作法,就很像是把ClassA的函式的記憶體位址告訴ClassB的委派,而委派大概這麼使用的,這個程式語法跟C#原本語法概念不太相同,不好理解,當成公式吧,要用的時候查就好了。
在ClassB裡頭,先宣告委派
public delegate int DelegateDefine( String MyPara );
好複雜難懂得一行,不急,這邊指示先宣告委派型別,目的是定義好你這個委派會呼叫什麼樣的函式,那個函式有怎樣的參數,又是怎樣的回傳型態。比方說,這裡是宣告說,我有一個委派叫做DelegateDefine,他到時候要呼叫一個「會傳入一個String的函式,然後這函式的回傳值,是int,就這樣而已。
接下來,把這個委派產生成物件
public DelegateDefine DelegateObj;
接下來ClassA就可以開始把委派跟函式綁在一起,當然,先決條件就是這個委派宣告的函式型態,可得跟ClassA要綁定的函式一樣喔,比方,函式如下
public int ClassA_Method( String Paras )
{
return 1;
}
然後開始綁定,可以把綁定寫在ClassA的建構子,也可以寫在某個函式裡面,只要能寫在某件事情之前,什麼事情?就是要叫用那個ClassB的委派之前就行了。綁定的語法也是比較特殊,就是把委派物件跟函式綁在一起就是了。
My_ClassB.DelegateObj = new ClassB.DelegateDefine( ClassA_Method );
看起來有點複雜,有沒有簡化的寫法?有,有,有,經過簡化過後你只需要這樣寫就行了:
My_ClassB.DelegateObj = ClassA_Method;
之後,不論ClassA或ClassB都可以用DelegateObj.Invoke( "xxx" );來呼叫函式ClassA_Method 了(xxx就是看你到時候要傳什麼當參數囉),就這樣,很簡單吧?
我寫了一個實際的小範例,大概是這樣的,有一個Class是使用者控制項,用來設計UI放元件的,叫做UC_Child,另外,有兩個Class是Form,也是用來設計UI的,分別叫做Form_Mother與Form_Father,UC_Child設計好了之後,會被Form宣告使用,很顯然的,Form就可以呼叫並使用UC_Child寫好的函式。但,這裡我需要讓UC_Child反向來呼叫Form這邊的函式呢?比方UC_Child這邊按下某個按鈕,或是完成收送之後,要通知Form來更新畫面呢?這個更新畫面,當然是只能寫在Form這邊,而無法寫在UC_Child,這時候,就要透過委派了。
這個範例,除了很簡單的做出委派之外,也包含了幾個委派的特性
1.委派可以同時綁兩個以上的函式
2.委派可以讓很多Parent宣告使用
3.委派綁定了函式之後,當呼叫函式時,並不會在遇到Return的時候就走回去,而是會把整個函式跑完的。
4.委派產生之後,不但Child自己可以Invoke,連Parent也可以呼叫Invoke,只不過,Parent用起來就沒什麼太大的實質意義了。
5.委派同時綁兩個以上的函式之後,會每個函式都跑過了,才會回到委派的下一行來。所以在Child裡面的Btn_Delegate_Click()裡,呼叫了DelegateObj.Invoke()之後,即便他綁了兩個函式,也不會回到這邊兩次,只會最後回到這邊來,然後帶著最後一個回傳值喔。
範例放在這邊 跟這邊
那麼,什麼是事件呢?其實大家對事件的接觸跟瞭解應該反而比委派多,就我目前瞭解,委派跟事件幾乎一樣,用法差不多,反而事件還比較複雜一點,據說,事件有多一些保護機制,但是在我瞭解之前,我也不亂多說,在上面的Link當中有Delegate跟Event兩個範例,差異實在很小。
1.原本在Child要把委派產生個實體出來,要用 事件 的方式的話,就不用,變成用以下的特殊語法,產生一個符合那個委派的事件,然後在Father跟Mother改成用事件跟函式綁定
public event DelegateDefine On_Env_Obj;
2.在Father跟Mother原本也可以叫用的Child的委派,現在改用事件的話,無法叫用Child的 事件 喔,也就是程式裡遮掉的那行
//My_Child.On_Env_Obj.Invoke 不可以
◆什麼時候會用到委派?
有兩種狀況:
1.你要寫一個Class或Interface,其中有個函式,會讓別的Class呼叫(注意,是Class,不是Instance喔)。也就是在撰寫類別的時候,就能夠呼叫非實體的函式。
2.你要寫一個Class或Interface,其中有個函式,會達成某種特別功能,但是,寫的時候,你並不知道這個功能會怎麼完成,好比說,你這個Class是個登入的介面或Model,但是密碼驗證的部分,是你提供方法出來,給要使用你這個Class的人,到時候要實作函式內容的(將委派綁定函式)。
當你撰寫一個Class裡面需要呼叫該Class無法呼叫到的函式(當然,就不是這個Class宣告的函式囉)的時候,就會需要用到委派,而什麼情況下Class無法呼叫某個函式呢?我們先看看,什麼情況下,Class可以呼叫非Class自己的函式呢?比方有兩個Class,一個是ClassA一個是ClassB,如果在ClassA中宣告產生了ClassB,那麼ClassB的函式就可以被ClassA呼叫(如果宣告成Public或是有封裝出來),這是物件導向的基本概念,相信大家都懂,但是,如果ClassB想呼叫ClassA的函式呢?那就做不到了。程式如下:
Class ClassA
{
public void RunClassA()
{
ClassB MyClassB = new ClassB();
MyClassB.MethodB();
}
public void MethodA()
{
Console.WriteLine( "MethodA被呼叫了" );
}
}
Class ClassB
{
public void RunClassB()
{
ClassA.MethodA();
}
public void MethodB()
{
Console.WriteLine( "MethodB被呼叫了" );
}
}
上述紅底的那一行,就是無法做到的,因為ClassB沒有宣告ClassA,對ClassB來說,他不曉得ClassA是什麼,那麼,如果在ClassB也宣告一個ClassA呢?那麼A中有B,B中又有A,A中又有B,無限循環下去記憶體會吃光光,這種怪程式應該無法跑不下去,有解決方法嗎?有啊,除了用Static來做,或是把ClassA傳進來給ClassB......但是,有時候ClassA不是你寫的,你沒辦法預期人家怎麼做,但是卻又有這種需求,這時候就需要委派了。
◆委派怎麼做呢?
先不要講程式,免得把人搞昏了,概念上,就是ClassB這邊,宣告一個叫做「委派」的東西,這個委派,可以讓ClassB被別人宣告使用的時候,也同時可以使用這個委派,透過特殊的語法,在ClassA把委派跟某個函式綁在一起,這樣只要有人(不論ClassB或ClassA都可以)叫這個委派做事,這個委派就會去找到這個函式,然後執行,這樣ClassB就可以呼叫到ClassA了,聽起來似乎落落長,實際上不難,我們來看看怎麼做。
再稍微細節一點來看,這個作法,就很像是把ClassA的函式的記憶體位址告訴ClassB的委派,而委派大概這麼使用的,這個程式語法跟C#原本語法概念不太相同,不好理解,當成公式吧,要用的時候查就好了。
在ClassB裡頭,先宣告委派
public delegate int DelegateDefine( String MyPara );
好複雜難懂得一行,不急,這邊指示先宣告委派型別,目的是定義好你這個委派會呼叫什麼樣的函式,那個函式有怎樣的參數,又是怎樣的回傳型態。比方說,這裡是宣告說,我有一個委派叫做DelegateDefine,他到時候要呼叫一個「會傳入一個String的函式,然後這函式的回傳值,是int,就這樣而已。
接下來,把這個委派產生成物件
public DelegateDefine DelegateObj;
接下來ClassA就可以開始把委派跟函式綁在一起,當然,先決條件就是這個委派宣告的函式型態,可得跟ClassA要綁定的函式一樣喔,比方,函式如下
public int ClassA_Method( String Paras )
{
return 1;
}
然後開始綁定,可以把綁定寫在ClassA的建構子,也可以寫在某個函式裡面,只要能寫在某件事情之前,什麼事情?就是要叫用那個ClassB的委派之前就行了。綁定的語法也是比較特殊,就是把委派物件跟函式綁在一起就是了。
My_ClassB.DelegateObj = new ClassB.DelegateDefine( ClassA_Method );
看起來有點複雜,有沒有簡化的寫法?有,有,有,經過簡化過後你只需要這樣寫就行了:
My_ClassB.DelegateObj = ClassA_Method;
之後,不論ClassA或ClassB都可以用DelegateObj.Invoke( "xxx" );來呼叫函式ClassA_Method 了(xxx就是看你到時候要傳什麼當參數囉),就這樣,很簡單吧?
我寫了一個實際的小範例,大概是這樣的,有一個Class是使用者控制項,用來設計UI放元件的,叫做UC_Child,另外,有兩個Class是Form,也是用來設計UI的,分別叫做Form_Mother與Form_Father,UC_Child設計好了之後,會被Form宣告使用,很顯然的,Form就可以呼叫並使用UC_Child寫好的函式。但,這裡我需要讓UC_Child反向來呼叫Form這邊的函式呢?比方UC_Child這邊按下某個按鈕,或是完成收送之後,要通知Form來更新畫面呢?這個更新畫面,當然是只能寫在Form這邊,而無法寫在UC_Child,這時候,就要透過委派了。
這個範例,除了很簡單的做出委派之外,也包含了幾個委派的特性
1.委派可以同時綁兩個以上的函式
2.委派可以讓很多Parent宣告使用
3.委派綁定了函式之後,當呼叫函式時,並不會在遇到Return的時候就走回去,而是會把整個函式跑完的。
4.委派產生之後,不但Child自己可以Invoke,連Parent也可以呼叫Invoke,只不過,Parent用起來就沒什麼太大的實質意義了。
5.委派同時綁兩個以上的函式之後,會每個函式都跑過了,才會回到委派的下一行來。所以在Child裡面的Btn_Delegate_Click()裡,呼叫了DelegateObj.Invoke()之後,即便他綁了兩個函式,也不會回到這邊兩次,只會最後回到這邊來,然後帶著最後一個回傳值喔。
範例放在這邊 跟這邊
那麼,什麼是事件呢?其實大家對事件的接觸跟瞭解應該反而比委派多,就我目前瞭解,委派跟事件幾乎一樣,用法差不多,反而事件還比較複雜一點,據說,事件有多一些保護機制,但是在我瞭解之前,我也不亂多說,在上面的Link當中有Delegate跟Event兩個範例,差異實在很小。
1.原本在Child要把委派產生個實體出來,要用 事件 的方式的話,就不用,變成用以下的特殊語法,產生一個符合那個委派的事件,然後在Father跟Mother改成用事件跟函式綁定
public event DelegateDefine On_Env_Obj;
2.在Father跟Mother原本也可以叫用的Child的委派,現在改用事件的話,無法叫用Child的 事件 喔,也就是程式裡遮掉的那行
//My_Child.On_Env_Obj.Invoke 不可以
2011年9月8日 星期四
ListView 的使用教學
- ListView的屬性View有五種設定值,分別是LargeIcon、Details、SmallIcon、List、Tile,代表著五種不同的資料檢視模式
- Item屬性可以編輯項目,這些項目,就是會呈現在ListView上的所有項目,當你以Details以外的模式查看資料就可以看到這些項目了。但是,此時在檢視模式「Details」看則是空白。
- 如何在Detail模式下可以看到資料呢?你必須編輯Columns屬性,只要新增一個Column,就能顯示出這些項目了。
- 如果再新增Columns,會發現,不會顯示多的資料出來,後面幾欄都會是空的,必須編輯Items的SubItems屬性,這個項目會對於剛剛的Items屬性增加細節資訊,這些細節資訊,會對應到兩種顯示模式,分別是Details跟Tile,對於Details,則是看Columns的數量,如果Columns的數量夠多才能將細節資訊顯示出來,而對於Tile,增加的資訊,會列在主資訊旁邊,有點像是註解般的,但是要注意的是,Columns屬性還會影響檢視模式「Tile」的顯示,Columns有幾個,這邊才會把每個Items的第幾個SubItems顯示出來的。
- 而群組屬性則是可以將所有的Items分成幾個不同的群組來顯示資料,編輯Groups屬性時會發現你無論新增幾個Groups,對畫面的影響僅有畫面多了一個Default的標題,所有項目都被放在Default標題之下。接下來要做的動作是到Items的屬性設定畫面,將Group屬性選擇成剛剛建立的Group,凡是沒有指定的都會放在Default那個區塊底下的。
- 還可以放入ImageList元件,將圖片設定好,就可以在ListView的LargeImageList與SmallImageList屬性設定到ImageList元件,這樣在檢視模式:「LargeIcon」就可以看到大圖示,而其他的模式則可以看到指定小圖。
字串格式與對齊解說(三)數值篇
String.Format( String, Object )的使用方式有點類似之前C的printf()
例如:
舉例來看:
ResultStr = String.Format( "謝謝您在{1:##}分鐘內閱讀本文章第 {0:00###} 次了.",123,60);
或
ReadAmount = 123;
ResultStr = String.Format( "謝謝您在{1:##}分鐘內閱讀本文章第 {0:00###} 次了.",ReadAmount,60 );
這樣的語法,就能得到 ResultStr = "謝謝您在60分鐘內閱讀本文章第00123次了。也就是說,可以傳入由字串與格式項目與參數的組合來達到串出所需字串的目的,而在 { } 兩個大括弧中間的,就是控制格式化的部分,而大刮號之間的第一個數字,是表示要用後面所給的第幾個參數,通常會是需要被格式化的「數字、時間、.....等等格式」,比方,以第二個例子來說,就會拿後面的參數60代到前面的{1}那邊,而參數ReadAmount則是會被代到前面的{0}的地方而 : 符號後面的部分,則是可以用很複雜的控制代碼,控制代碼,分成很多種。
我們先看常用的標準的格式代碼(格式碼通常不用在意大小寫,都適用)
----------------------------------------------------------------------------------------------
C 表示貨幣,並且可接著一個數字,來表示要的精度到小數第幾位,不接數字則會使用目前NumberFormatInfo物件所提供的預設貨幣精確度。
例如:String.Format( "{0:C5}", 12345.678901234 )則會得到NT$12,345.67890
D 表示十進位(只支援整數型別),並且可接著一個數字,來表示要顯示多少位數,不夠的部分會於左邊補零
D 表示十進位(只支援整數型別),並且可接著一個數字,來表示要顯示多少位數,不夠的部分會於左邊補零
例如:String.Format( "{0:D8}", 12345 )則會得到00012345
E 表示科學符號,並且可接著一個數字,來表示要的精度到小數第幾位,不接數字則預設六位小數
E 表示科學符號,並且可接著一個數字,來表示要的精度到小數第幾位,不接數字則預設六位小數
例如:String.Format( "{0:E}", 12345.678901234 )則會得到1.234568E+004
F 表示浮點數,並且可接著一個數字,來表示要的精度到小數第幾位,不接數字則會使用目前 NumberFormatInfo 物件的 NumberDecimalDigits 屬性所提供的預設數值精確度。
F 表示浮點數,並且可接著一個數字,來表示要的精度到小數第幾位,不接數字則會使用目前 NumberFormatInfo 物件的 NumberDecimalDigits 屬性所提供的預設數值精確度。
例如:String.Format( "{0:F3}", 12345.678901234 )則會得到12345.679
G 表示一般,並且可接著一個數字,來並且可接著一個數字,來表示要顯示多少位數(包含整數與小數的部分),而可能轉為科學記號,也可能轉出浮點數,(說明文件說會挑以最精簡顯示方式來顯示,但很難懂),直接看範例
例如:String.Format( "{0:G3}", 12345.678901234 )則會得到123e+04 G 表示一般,並且可接著一個數字,來並且可接著一個數字,來表示要顯示多少位數(包含整數與小數的部分),而可能轉為科學記號,也可能轉出浮點數,(說明文件說會挑以最精簡顯示方式來顯示,但很難懂),直接看範例
例如:String.Format( "{0:G4}", 12345.678901234 )則會得到1235e+04
例如:String.Format( "{0:G5}", 12345.678901234 )則會得到12346
例如:String.Format( "{0:G6}", 12345.678901234 )則會得到12345.7
N 表示數字,並且可接著一個數字,表示要的精度到小數第幾位,不接數字則會使用目前 NumberFormatInfo 物件的 NumberDecimalDigits 屬性所提供的預設數值精確度。
N 表示數字,並且可接著一個數字,表示要的精度到小數第幾位,不接數字則會使用目前 NumberFormatInfo 物件的 NumberDecimalDigits 屬性所提供的預設數值精確度。
例如:String.Format( "{0:N3}", 12345.678901234 )則會得到12345.679
P 表示百分比,並且可接著一個數字,來表示要的精度到小數第幾位,不接數字則預設六位小數
P 表示百分比,並且可接著一個數字,來表示要的精度到小數第幾位,不接數字則預設六位小數
例如:String.Format( "{0:E}", 12345.678901234 )則會得到1.234568E+004
X 表示16進位,並且可接著一個數字,來表示要顯示多少位數,不夠的部分會於左邊補零。這個X的大小寫,有意義,會指定輸出的16進位的英文部分要大寫還是小寫。
X 表示16進位,並且可接著一個數字,來表示要顯示多少位數,不夠的部分會於左邊補零。這個X的大小寫,有意義,會指定輸出的16進位的英文部分要大寫還是小寫。
例如:String.Format( "{0:X8}", 123456 )則會得到0001E240
我們再看常用的自訂的格式代碼
----------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------
0 的用法是會讓轉出來的字串被數字取代,但是如果沒數字的地方,會補零。
# 的用法是會讓轉出來的字串被數字取代,但是如果沒數字的地方,不會有數字。
. 的用法是決定轉出的字串的小數點對齊位置。
\ 的用法是讓這些保留控制碼也可以被顯示出來。
其他符號都會直接被顯示在轉出的字串裡。
例如:
String.Format( "{0:000000}", 1234 )則會得到001234
String.Format( "{0:000.000}", 1234.56 )則會得到1234.560
String.Format( "{0:######}", 1234.56 )則會得到1234
String.Format( "{0:###.###}", 1234.56 )則會得到1234.56
String.Format( "{0:###.000}", 1234.56 )則會得到1234.560
補充PadLft與PadRight
補充PadLft與PadRight
訂閱:
文章 (Atom)