《C#程序設(shè)計基礎(chǔ)教程》課件第10章_第1頁
《C#程序設(shè)計基礎(chǔ)教程》課件第10章_第2頁
《C#程序設(shè)計基礎(chǔ)教程》課件第10章_第3頁
《C#程序設(shè)計基礎(chǔ)教程》課件第10章_第4頁
《C#程序設(shè)計基礎(chǔ)教程》課件第10章_第5頁
已閱讀5頁,還剩62頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

第10章ADO.NET(三)10.1DataSet10.2架構(gòu)的生成10.3List<T>泛型集合10.4數(shù)據(jù)展示10.5查看電影信息

10.1DataSet

數(shù)據(jù)集(DataSet)是ADO.NET的一個重要組成部分,它是數(shù)據(jù)的脫機容器,承擔著數(shù)據(jù)的中間存儲工作。DataSet并不直接和數(shù)據(jù)庫連接,因此它的數(shù)據(jù)不一定來源于數(shù)據(jù)庫,而是可以有很多種不同的來源,甚至可以直接從測量設(shè)備中讀取。一個DataSet是由一組數(shù)據(jù)表(DataTable)對象組成的,而每個DataTable對象又是由若干個DataColumn對象和DataRow對象組成的,如圖10-1所示。我們可以看到其結(jié)構(gòu)和數(shù)據(jù)庫中的數(shù)據(jù)表非常相似。除了定義數(shù)據(jù)外,還可以在DataSet中定義表之間的鏈接,即我們在數(shù)據(jù)庫中常用的到主/從表。DataSet及其常用對象的說明如表10-1所示。我們可以直接通過構(gòu)造來創(chuàng)建DataSet對象:DataSetds=newDataSet();DataSetds=newDataSet("myds");上面我們分別采用DataSet的兩個構(gòu)造來創(chuàng)建對象,兩種方式?jīng)]有太大的區(qū)別,只不過第二種方式DataSet對象多了一個“myds”的別稱而已。和數(shù)據(jù)庫一樣,DataSet對象本身并不能夠存儲數(shù)據(jù),真正承擔這個工作的是DataTable對象,接下來我們來了解DataTable對象。數(shù)據(jù)表(DataTable)非常類似于SQLServer2008中的數(shù)據(jù)庫表,它是由一組包含特定屬性的列組成的,可能包含0行或多行數(shù)據(jù)。和數(shù)據(jù)庫表一樣,DataTable也可以定義由一個列或者多個列組成的主鍵,列上也可以包含約束。這些信息對應(yīng)的通用術(shù)語稱為DataTable的“架構(gòu)”。整個DataTable可以訪問的對象如圖10-2所示。在C#中,創(chuàng)建DataTable對象可以有兩種方式:DataTabledt1=newDataTable();DataTabledt2=newDataTable("myTab");兩種方式?jīng)]有本質(zhì)上的區(qū)別,只不過dt2對象在具體使用時會更加方便一些。當然現(xiàn)在DataTable對象依然無法存儲數(shù)據(jù),因為它還沒有結(jié)構(gòu),要設(shè)定DataTable的結(jié)構(gòu),我們需要用到DataColumn對象。

10.2架構(gòu)的生成

在ADO.NET中,DataAdapter(數(shù)據(jù)適配器)的作用是檢索和保存數(shù)據(jù),在使用的過程中它一般都是與Connection對象和Command對象一起使用,以便連接到相應(yīng)的數(shù)據(jù)庫并完成指定的操作。另一方面,DataAdapter對象本身并不具備保存數(shù)據(jù)的能力,因此它又需要和DataSet對象配合使用,才能夠臨時存儲數(shù)據(jù),并提供操作數(shù)據(jù)的接口。DataAdapter無疑是ADO.NET中一個非常特殊的對象,它就像一座橋梁,一頭連接著存儲數(shù)據(jù)的數(shù)據(jù)庫,另一頭則連接著作為臨時數(shù)據(jù)存儲對象的DataSet。它能夠根據(jù)SQL語句從數(shù)據(jù)庫中提取數(shù)據(jù),也能夠?qū)⒏暮蟮臄?shù)據(jù)更新到數(shù)據(jù)庫中。DataAdapter對象屬于.NETFramework數(shù)據(jù)提供程序,不同的數(shù)據(jù)提供程序有自己的DataAdapter對象,用于OLEDB的是OleDbDataAdapter對象,而用于SQLServer的是SqlDataAdapter對象,這里我們以SqlDataAdapter對象為例來認識DataAdapter對象。我們可通過四種方式來創(chuàng)建SqlDataAdapter對象,如表10-4所示。一般來說第三種方式使用得比較多:stringconn=ConfigurationManager.ConnectionStrings["SQL"].ConnectionString;SqlConnectioncn=newSqlConnection(conn);stringsql="select*fromFilm";SqlDataAdapterda=newSqlDataAdapter(sql,cn);在上面的代碼中我們首先還是要創(chuàng)建一個SqlConnection對象,因為在ADO.NET中一切操作都是以連接為基礎(chǔ),然后創(chuàng)建一個SqlDataReader對象,并且將一個Select查詢語句和已經(jīng)創(chuàng)建好的SqlConnection對象作為參數(shù)傳遞到它的構(gòu)造函數(shù)中。創(chuàng)建了SqlDataAdapter對象后,我們就可以使用其提供的屬性和方法來完成需要的操作。我們常用到的方法有兩個:Fill():使用SELECT語句從數(shù)據(jù)源中檢索數(shù)據(jù)。Update():使用SQL語句將數(shù)據(jù)集中的數(shù)據(jù)更新到數(shù)據(jù)源。當我們需要從數(shù)據(jù)庫中檢索數(shù)據(jù)時,可以使用Fill()方法,這時與Select命令關(guān)聯(lián)的SqlConnection對象必須有效,但不需要將其打開。如果調(diào)用Fill()方法之前SqlConnection已關(guān)閉,則將其打開以檢索數(shù)據(jù),然后再將其關(guān)閉。如果調(diào)用Fill()方法之前連接已打開,則它將保持打開狀態(tài):stringsql="select*from[User]";SqlDataAdapterda=newSqlDataAdapter(sql,cn);DataSetds=newDataSet();da.Fill(ds);在上面的代碼中我們創(chuàng)建了一個SqlDataAdapter對象,并且通過一條查詢語句從數(shù)據(jù)庫中查詢數(shù)據(jù),然后將結(jié)果使用Fill()方法填充到一個數(shù)據(jù)集對象中。如果在填充數(shù)據(jù)時遇到錯誤或異常,則錯誤發(fā)生之前添加的行將保留在數(shù)據(jù)集中,操作的剩余部分被中止。如果命令不返回任何行,則不向數(shù)據(jù)集中添加表,也不引發(fā)異常。在實際應(yīng)用中,DataAdapter對象多用于查詢類型的操作,雖然它也具有其他類型數(shù)據(jù)操作的能力,但是由于其本身缺乏對數(shù)據(jù)完整性的驗證能力,因此其他類型的操作我們多是借助于Command對象來完成的。在大部分程序中,數(shù)據(jù)集在使用的時候都是通過DataAdapter對象來填充的。通過DataAdapter對象的Fill()方法,我們可以將數(shù)據(jù)源中的數(shù)據(jù)一次性地填充到數(shù)據(jù)集中,這個時候數(shù)據(jù)集的結(jié)構(gòu)和內(nèi)容都由系統(tǒng)幫助我們自動生成。填充數(shù)據(jù)集有多種不同的方式,最直接的方式是不做任何設(shè)定,一切由系統(tǒng)來決定:stringconn=ConfigurationManager.ConnectionStrings["SQL"].ConnectionString;SqlConnectioncn=newSqlConnection(conn);stringsql="select*fromFilm";SqlDataAdapterda=newSqlDataAdapter(sql,cn);DataSetds=newDataSet();da.Fill(ds);上面的代碼我們沒有做任何其他的設(shè)置,僅僅是連接數(shù)據(jù)庫后讀取Film數(shù)據(jù)表中的所有數(shù)據(jù),然后通過DataAdapter對象的Fill()方法將讀取的數(shù)據(jù)填充到一個數(shù)據(jù)集中。因為我們只提供了一些對象,所以這個時候數(shù)據(jù)集中將由系統(tǒng)自動創(chuàng)建一個名為“Table”的DataTable對象,而它的結(jié)構(gòu)則由我們的查詢語句來決定。例如,我們這里是查詢Film表中的所有信息,因此“Table”表的字段就是數(shù)據(jù)庫中Film數(shù)據(jù)表的所有字段,而“Table”表的數(shù)據(jù)則和Film數(shù)據(jù)表的數(shù)據(jù)一樣。后續(xù)我們使用這個數(shù)據(jù)集的時候就只能這樣訪問DataTable:ds.Table["Table"]或者通過索引訪問:ds.Table[0]很顯然,上面的代碼雖然能夠完成任務(wù),但是不確定和不安全的地方太多了,因此我們還需要將程序?qū)懙酶訙蚀_些:SqlDataAdapterda=newSqlDataAdapter(sql,cn);da.Fill(ds,"MyFilm");這一次我們將程序做了一點微調(diào),在調(diào)用DataAdapter對象的Fill()方法時,我們不但傳遞了數(shù)據(jù)集對象,同時還給了第二個字符串類型的參數(shù)“MyFilm”,這個參數(shù)的作用是在進行數(shù)據(jù)填充的時候,將系統(tǒng)自動創(chuàng)建的DataTable對象命名為“MyFilm”,這樣在后續(xù)使用時就可以這樣寫:ds.Table["MyFilm"]相對第一段代碼,這次的程序顯得更加精確,但是依然存在問題,主要是訪問起來比較麻煩,每次都要通過數(shù)據(jù)集定位到DataTable,然后才能夠訪問行和列,因此我們可以將程序再次進行修改:SqlDataAdapterda=newSqlDataAdapter(sql,cn);DataTabledt=newDataTable();da.Fill(dt);這次程序中找不到DataSet對象了,取而代之的是一個DataTable對象,這也是我們在實際開發(fā)中經(jīng)常會用到的一種方式,道理很簡單,既然數(shù)據(jù)集的數(shù)據(jù)是存放在DataTable對象中的,那我們就可以繞過數(shù)據(jù)集而直接使用DataTable對象來操作數(shù)據(jù),當然這樣一來我們就無法再通過數(shù)據(jù)集來管理DataTable之間的關(guān)系了。三種數(shù)據(jù)集填充方式在實際使用的過程中沒有太大的區(qū)別,具體采用哪種方式還是要根據(jù)實際開發(fā)的情況以及個人的使用習慣來定。

10.3List<T>泛型集合

10.3.1List定義集合的具體介紹詳見C#高級編程的有關(guān)教材,下面要介紹的是集合中用得非常廣泛的一種:List<T>。我們首先來看一下它的語法:List<T>list=newList<T>();這是一個泛型集合類,重點在于它里面的類型參數(shù):T。T本身沒有具體含義,它只是類似于占位符一般的存在。它可以是任何類,如果你想創(chuàng)建一個User實體對象的集合,那么,將T改成User就行了。在實際運用中,語法如下:List<User>list=newList<User>();10.3.2數(shù)據(jù)讀取光有對象是不夠的,List的作用是獲取數(shù)據(jù)庫中的數(shù)據(jù),作為數(shù)據(jù)源來使用。但是如何將數(shù)據(jù)表中的數(shù)據(jù)放到List對象中呢?下面的代碼是整個過程。首先,創(chuàng)建表的實體類,我們要將用戶表(User)的數(shù)據(jù)讀取出來,先創(chuàng)建User類:publicclassUser{//屬性定義publicintID{get;set;}publicstringName{get;set;}publicstringUserName{get;set;}publicintTypeID{get;set;}publicstringTypeName{get;set;}publicstringDesc{get;set;}publicintState{get;set;}}接下來,使用SqlDataReader對象讀取數(shù)據(jù):stringconStr="server=.;initialcatalog=MyFilm;integratedsecurity=SSPI;";stringsql="select*fromUser";SqlConnectionconn=newSqlConnection(conStr);conn.Open();SqlCommandcm=newSqlCommand(sql,conn);SqlDataReaderdr=cm.ExecuteReader();List<User>modelList=newList<User>(); //創(chuàng)建List泛型集合對象Usermodel=null; //在循環(huán)外部創(chuàng)建User對象,但不用實例化while(dr.Read()){model=newUser(); //每一次循環(huán)讀取數(shù)據(jù)時,實例化該對象model.ID=int.Parse(dr["ID"].ToString()); //將當前行的ID字段數(shù)據(jù)賦值給對象ID屬性model.Name=dr["Name"].ToString();model.UserName=dr["Name"].ToString();model.TypeID=int.Parse(dr["TypeID"].ToString());model.TypeName=dr["Name"].ToString();model.Desc=dr["Name"].ToString();model.State=int.Parse(dr["State"].ToString());modelList.Add(model); //最后一定要記得將實體對象添加到集合中}dr.Close(); //一定要記得在讀取完數(shù)據(jù)后關(guān)掉閱讀器conn.Close();當執(zhí)行完上述操作后,這個集合中就獲得了查詢語句所查詢出來的所有數(shù)據(jù)了。

10.4數(shù)據(jù)展示

10.4.1簡單控件對于DataSet來說,最直接的操作就是用簡單控件來顯示其中的數(shù)據(jù),當然在這之前我們要知道如何讀取它的值。最常見的就是讀取DataSet中數(shù)據(jù)表的某行或者某列的值,甚至可能會精確到某一個單元格的值。例如,用戶希望查看數(shù)據(jù)表中第二部電影的信息,那么我們的程序就可以這樣寫:stringname=(string)ds.Tables["Film"].Rows[1]["Name"];stringaddedBy=(string)ds.Tables["Film"].Rows[1]["AddedBy"];stringactor=(string)ds.Tables["Film"].Rows[1]["Actors"];stringdesc=(string)ds.Tables["Film"].Rows[1]["Desc"];MessageBox.Show("影片"+name+"是由"+actor+"主演!\ny影片簡介:"+desc);上面的代碼可以訪問表中的一行數(shù)據(jù),如果需要訪問表中所有行的數(shù)據(jù),則需要再增加一個循環(huán)結(jié)構(gòu):foreach(DataRowdrinds.Tables["myTab"].Rows){//讀取數(shù)據(jù)}事實上,如果是這種逐行讀取數(shù)據(jù)的操作則DataReader對象是更加合適的對象,因為它消耗的系統(tǒng)資源更少,速度也更快一些。DataSet的主要用途在于更全面地展示數(shù)據(jù)。知道了如何讀取數(shù)據(jù)后,接下來使用簡單控件呈現(xiàn)數(shù)據(jù)的工作就很簡單了:txtName.Text=(string)ds.Tables["Film"].Rows[0]["Name"];txtActors.Text=(string)ds.Tables["Film"].Rows[0]["Actors"];txtPrice.Text=ds.Tables["Film"].Rows[0]["Price"].ToString();txtDesc.Text=(string)ds.Tables["Film"].Rows[0]["Desc"];上面的代碼依然是從數(shù)據(jù)集中讀取數(shù)據(jù),只不過讀取的數(shù)據(jù)不再使用變量,而是直接使用三個TextBox控件和一個RichTextBox控件來呈現(xiàn)數(shù)據(jù)。只不過這種方式只能夠讀取一行數(shù)據(jù),如果需要一次性展示更多的信息則還需要借助于其他的控件。我們曾用DataSet來讀取數(shù)據(jù),那么List<T>是怎么讀取數(shù)據(jù)的呢?同樣的案例,我們用泛型集合來演示一次。假設(shè)讀取數(shù)據(jù)的泛型集合類為List<Film>,對象名稱為modelList,同樣讀取第二行數(shù)據(jù):stringname=modelList[1].Name;stringaddedBy=modelList[1].AddedBy;其余的值依此類推,可見相比較DataSet來講,List<Film>要簡單方便。想要讀取所有的數(shù)據(jù),也可以用循環(huán)遍歷來實現(xiàn):foreach(FilmmodelinmodelList){//依上例讀取數(shù)據(jù)stringname=model.Name;…}控件的數(shù)據(jù)讀取依上例所示即可。10.4.2列表控件列表類型的控件是系統(tǒng)開發(fā)過程中經(jīng)常會用到的控件,在之前我們用到這類控件的時候,其選擇項大多是直接設(shè)定好的固定內(nèi)容,是否可以讓它們從數(shù)據(jù)集中動態(tài)地獲取選擇內(nèi)容呢?要實現(xiàn)這個操作本身并不復(fù)雜,我們知道列表類型的控件其選擇項都是在Items屬性中保存的,因此只要能夠?qū)?shù)據(jù)集中的數(shù)據(jù)“放置”到Items屬性中就可以了。問題在于Items屬性中的每一個選擇項都是由Text和Value這兩個值構(gòu)成的,因此我們要做的工作就是將數(shù)據(jù)表的列和這兩個值對應(yīng)起來:comboBox1.DropDownStyle=ComboBoxStyle.DropDownList;comboBox1.DisplayMember="Name";comboBox1.ValueMember="ID";comboBox1.DataSource=ds.Tables["Film"];在上面的代碼中我們設(shè)定了ComboBox控件的四個屬性。DropDownStyle屬性用來設(shè)定其顯示方式,我們設(shè)定為ComboBoxStyle.DropDownList,這樣該組合框控件就只能夠選擇而不能夠輸入信息。DisplayMember屬性用來設(shè)定每一個Item選擇項的Text屬性所對應(yīng)的列名,這個列名必須是數(shù)據(jù)表中存在的列。ValueMember屬性則是用來設(shè)定每一個Item選擇項的Value屬性所對應(yīng)的列名,同樣該列必須是數(shù)據(jù)表中存在的列,如果在程序中沒有設(shè)定ValueMember屬性,則Item選擇項的Value屬性值就會和Text屬性值相同。最后我們設(shè)定了組合框控件的DataSource屬性,也就是數(shù)據(jù)源屬性,這樣系統(tǒng)就會自動在DataSource所指定的數(shù)據(jù)源中查找相應(yīng)的列,并將這些列的值一次性填充到組合框中,從而形成選擇項。同樣,上例也用的是DataSet數(shù)據(jù)源,如果是List集合,則只需要把最后一句代碼的數(shù)據(jù)源替換即可:comboBox1.DataSource=modelList; //記住,這里的值為整個泛型集合對象從這里開始,后面的數(shù)據(jù)源將直接使用泛型集合,而不再使用DataSet了。如何知道用戶所選擇的內(nèi)容呢?這里我們可以通過兩個簡單的屬性取得用戶選擇的信息:intid=(int)comboBox1.SelectedValue;stringname=comboBox1.Text;MessageBox.Show("電影《"+name+"》的編號是:"+id);組合框的SelectedValue屬性可以取得用戶選擇項的Value屬性值,而Text屬性則可以取得用戶選擇項的Text屬性的值。這里很容易產(chǎn)生一個疑問:為什么一個選擇項要設(shè)定Text和Value這兩個屬性值?這是因為在實際使用中,難免會出現(xiàn)重復(fù)的數(shù)據(jù)。例如,如果數(shù)據(jù)庫中存在兩部同名的電影,那么我們?nèi)绾沃烙脩暨x擇的究竟是哪一部電影呢?很顯然單憑Text屬性根本無法做判斷,這時候如果我們在Value屬性中保存了電影的編號,那么就可以很容易地知道用戶的選擇。因為之前的數(shù)據(jù)是通過屬性綁定到控件的,我們通過上面的內(nèi)容可以得到顯示和隱藏的值,但實際上我們可以通過它的SelectedItem屬性得到當前選定項所綁定的整個對象:Filmmodel=(Film)comboBox1.SelectedItem;MessageBox.Show("電影《"+model.Name+"》的編號是:"+model.Id);如果是多選我們該如何操作呢?對于像ListBox這樣的多選類型的控件,其數(shù)據(jù)顯示部分的操作和ComboBox控件一樣,也就是說我們將前面代碼中的ComboBox換成ListBox控件就可以了:listBox1.SelectionMode=SelectionMode.MultiExtended;listBox1.DisplayMember="Name";listBox1.ValueMember="ID";listBox1.DataSource=modelList;相對于ComboBox控件ListBox控件的讀取相對來說復(fù)雜一些,根據(jù)DataSource所設(shè)定的數(shù)據(jù)源類型不同,其讀取方式也會有一些細微的差別,其讀取方式為stringstr="選中的電影:";for(inti=0;i<listBox1.SelectedItems.Count;i++){Filmmodel=(Film)listBox1.SelectedItems[i];str+="\n電影名稱:"+model.Name; //如果能讀取到Name,則其他的屬性也能夠得到}MessageBox.Show(str);上面代碼的運行效果如圖10-5所示。10.4.3DataGridView列表類型的控件在使用的時候雖然能夠一次性呈現(xiàn)很多行數(shù)據(jù)的信息,但是只能夠顯示數(shù)據(jù)表中的某一列,如果要呈現(xiàn)數(shù)據(jù)的全貌,還是要借助于更加大型的控件,這其中最常用的就是DataGridView。DataGridView控件是WinForm中經(jīng)常使用到的一個用于呈現(xiàn)數(shù)據(jù)的大型控件,它能夠以表格的形式將數(shù)據(jù)集中的數(shù)據(jù)表完整地呈現(xiàn)出來,同時還支持根據(jù)用戶的需要進行各種不同的設(shè)置。使用DataGridView控件時,可以在工具箱的“數(shù)據(jù)”選項卡中找到它并將其放置到窗體中,如圖10-6所示。將DataGridView控件添加到窗體上后,我們只需要一行代碼就可以將剛才創(chuàng)建的泛型集合在該控件上呈現(xiàn)出來:dataGridView1.DataSource=modelList;DataGridView控件可以以表格的形式將數(shù)據(jù)集中的數(shù)據(jù)呈現(xiàn)出來,該控件在使用的時候最重要的屬性就是DataSource屬性,它主要用來設(shè)置DataGridView控件數(shù)據(jù)源,在上面的代碼中我們就將電影信息讀取出來后放置在DataSet對象中并作為數(shù)據(jù)源賦給了該屬性。其運行效果如圖10-7所示。當然,數(shù)據(jù)是出來了,但是和實際使用差別太大了,根本就不具備可用性。首先,我們并不需要將所有的字段都展示出來,像ID這樣的字段根本就不需要用戶知道它的存在。其次,列名用英文并沒有問題,但是這里卻使用的是字段名稱,從而將我們的數(shù)據(jù)結(jié)構(gòu)暴露了出來,這樣甚至會威脅到整個系統(tǒng)的安全。事實上,上面的問題總結(jié)起來就是一點,即需要DataGridView控件按照我們設(shè)定的方式顯示數(shù)據(jù),這就要設(shè)置DataGridView控件列,我們可以打開DataGridView控件的智能選項卡,然后點擊“編輯列”來完成。也可以在DataGridView控件的屬性列表中來完成。無論采用哪種方式,我們都可以打開DataGridView控件的列編輯器,如圖10-10所示。在列編輯器的左側(cè)是一個列表框,這里列出了當前DataGridView控件中已經(jīng)添加的列對象,我們可以看到這里有四個列。選中某一個列后,在窗體的右側(cè)可以看到一個屬性列表,這當中列出了當前選中列對象的一些常用屬性。在這些屬性中,常用的有以下幾個:Name:列對象的名稱,在程序中必須保證唯一。在命名時一般采用col作為前綴,例如colName。ColumnType:類對象的類型。WinForm中DataGridView控件的列共有六種類型:按鈕列樣式(DataGridViewButtonColumn)、復(fù)選框列樣式(DataGridViewCheckBoxColumn)、組合框列樣式(DataGridViewComboBoxColumn)、圖片列樣式(DataGridViewImageColumn)、鏈接列樣式(DataGridViewLinkColumn)和文本框列樣式(DataGridTextBoxColumn,默認樣式)。不同的列樣式會呈現(xiàn)出不同的外觀,同時使用方式也有細微的差別。DataPropertyName:設(shè)置列對象所對應(yīng)的數(shù)據(jù)源字段名稱。HeaderText:設(shè)置列對象的頁眉文本。不同的列樣式對應(yīng)著不同的使用環(huán)境,具體需要采用什么樣式還要根據(jù)實際情況來決定,一般情況下如果不能確定則都可以采用文本框樣式來呈現(xiàn)數(shù)據(jù),因為它基本上可以顯示任何類型的數(shù)據(jù)。如果要添加新的列對象,則點擊左側(cè)列表框下的“添加”按鈕,這樣就可以打開添加列窗體。在這個窗體上,我們可以設(shè)置三個值?!懊Q(N):”用來指定新添加列對象的Name屬性值?!邦愋?T):”下拉列表中可以選擇新添加列對象的樣式,也就是ColumnType屬性值?!绊撁嘉谋?H):”則是用來設(shè)定新添加列的HeaderText屬性值。需要注意的是,這里并沒有設(shè)置DataPropertyName屬性值,因此在完成列的添加后還需要在圖10-10中找到新添加的列并設(shè)置DataPropertyName屬性,否則是無法使用的。列設(shè)置完成再次運行我們的程序,會發(fā)現(xiàn)凡是數(shù)據(jù)表我們設(shè)置過的字段都按要求在DataGridView控件的指定列當中呈現(xiàn)出來了,但是我們沒有設(shè)置的字段卻依然按照先前的樣式顯示在DataGridView控件中,如圖10-12所示。這是因為默認情況下DataGridView控件會自動根據(jù)數(shù)據(jù)源中的表結(jié)構(gòu)來創(chuàng)建相應(yīng)的列,也就是說數(shù)據(jù)表中有多少個字段,DataGridView控件就會自動創(chuàng)建多少個列,并顯示數(shù)據(jù),而我們這里卻只需要它顯示我們設(shè)置的列,其他的列就不需要再自動創(chuàng)建了。要實現(xiàn)這一效果我們可以通過下面的代碼來實現(xiàn):dgdShowData.AutoGenerateColumns=false;AutoGenerateColumns屬性的作用是用來設(shè)置DataGridView控件是否需要根據(jù)數(shù)據(jù)源來自動創(chuàng)建列,將其設(shè)置為false后系統(tǒng)就不會再自動創(chuàng)建列,而只會根據(jù)我們設(shè)置的列來呈現(xiàn)數(shù)據(jù),如圖10-13所示。DataGridView是WinForm中最為復(fù)雜的大型控件之一,本章我們只是介紹了DataGridView控件的基本使用方式。10.4.4ListViewListView控件是另外一個數(shù)據(jù)展示控件,和DataGridView控件不同,ListView控件只是提供數(shù)據(jù)的顯示功能而并不提供對數(shù)據(jù)的操作功能,但是其顯示方式要比DataGridView控件豐富。下面我們同樣使用ListView控件來顯示電影信息。在工具箱中找到ListView控件并放置到窗體上,如圖10-14所示。和其他控件一樣,ListView控件也有很多屬性,限于篇幅我們不可能一次性將所有的屬性及其使用方式講解完畢,因此本章我們還是圍繞著數(shù)據(jù)呈現(xiàn)來學習相關(guān)的屬性。為了能夠完成這個任務(wù),我們會用到ListView控件的以下屬性:Name:ListView控件的名稱,在代碼中必須唯一。在命名的時候一般采用lsv作為前綴。Columns:設(shè)置ListView控件的列。FullRowSelect:指示是否可以一次性選擇整行數(shù)據(jù)。GridLines:指示ListView在顯示數(shù)據(jù)的時候是否顯示網(wǎng)格線。View:設(shè)置ListView的顯示方式。ListView控件中提供了五種不同的顯示方式,如表10-6所示。使用ListView控件顯示數(shù)據(jù)要比使用DataGridView控件復(fù)雜一些。首先我們需要設(shè)置ListView控件的Columns屬性,也就是設(shè)置數(shù)據(jù)顯示的列。在ListView控件的屬性窗口的行為部分找到Columns屬性。點擊右側(cè)的按鈕后打開ColumnHeader集合編輯器窗體。在窗體的左側(cè)“成員(M):”之下我們可以看到現(xiàn)在Columns屬性所有已經(jīng)存在的列成員。在成員列表的右側(cè)有上下兩個按鈕,選中某列后點擊向上或向下的按鈕就可以調(diào)整該列的排列順序,這個排列順序決定了最終數(shù)據(jù)顯示的時候該列的位置。如果未添加任何列,則該列表為空。點擊成員列表下方的“添加(A)”按鈕就可以添加一個新的列。在成員列表中選中某一列后,在窗體的右側(cè)可以看到當前選中列對象的相關(guān)屬性,在這些屬性中我們需要關(guān)注的是Name和Text。Name屬性是當前選中列對象的名稱,由于在實際操作過程中訪問這些列對象時我們都采用的是下標訪問,因此這里可以采用系統(tǒng)自動生成的名字,如果要命名,可以采用col作為前綴。Text屬性則是用來設(shè)定列對象的頁眉,也就是呈現(xiàn)在ListView控件中列標頭的文本。設(shè)定完成后,點擊“確定”按鈕后關(guān)閉ColumnHeader集合編輯器窗體,接下來需要完成具體的數(shù)據(jù)顯示工作。首先依然還是要將數(shù)據(jù)從數(shù)據(jù)庫中讀取出來,這個過程我們可以使用DataAdapter對象與DataSet對象配合起來實現(xiàn),因為前面我們已經(jīng)進行了講解,這里就不再重復(fù)說明。由于ListView控件沒有DataGridView控件那樣的自動數(shù)據(jù)填充功能,因此我們需要將數(shù)據(jù)集中的數(shù)據(jù)提取出來,然后放入ListView控件中的相應(yīng)位置:foreach(FilmmodelinmodelList){ListViewItemitem=newListViewItem();item.SubItems[0].Text=model.Name;item.SubItems.Add(model.Actors);item.SubItems.Add(string.Format("{0:C}",model.Price));lsvShowData.Items.Add(item);}在上面的代碼中,我們首先通過一個foreach循環(huán)結(jié)構(gòu)遍歷數(shù)據(jù)集合的所有行,在循環(huán)結(jié)構(gòu)體中我們需要創(chuàng)建一個ListViewItem對象,該對象代表ListView控件的Items屬性中的一個成員。接下來,我們就可以通過這個ListViewItem對象的SubItems屬性將數(shù)據(jù)行中的數(shù)據(jù)放置到該對象中。ListViewItem對象每調(diào)用一次Add()方法就可以向其中添加一個新的單元格,唯一需要注意的是其第一個單元格需要通過下標訪問,因為在創(chuàng)建該對象的時候系統(tǒng)會默認添加一個單元格。無論是設(shè)置哪一個單元格,傳遞的值都需要是字符串類型的。那么,ListViewItem對象又是怎么和ListView控件的列建立起關(guān)聯(lián)的呢?事實上,這個過程并不復(fù)雜,在最終將ListViewItem對象通過Add()方法添加到ListView控件的Items屬性中的時候,系統(tǒng)會按順序?qū)istViewItem對象的單元格和ListView控件的列對應(yīng)起來,也就是將ListViewItem對象第一個單元格的值放置到ListView控件的第一個列中,第二個單元格則放置到第二個列中,以此類推。正因為是這樣一個操作過程,所以我們在為ListViewItem對象添加單元格的時候一定要對ListView控件的列組成牢記在心,否則就會出現(xiàn)數(shù)據(jù)放置錯誤。另外,如果ListViewItem對象的單元格數(shù)量多于ListView控件的列數(shù)量,則多出來的數(shù)據(jù)就會被系統(tǒng)舍棄。上面的代碼中另外一個需要我們注意的地方是,在添加價格的時候我們并沒有直接將其轉(zhuǎn)換成為字符串,而是通過string類的Format()方法將其轉(zhuǎn)換成了貨幣的格式。Format()方法的作用是將指定的值按照要求轉(zhuǎn)換成為特定的格式。一般在使用該方法時我們需要提供兩個參數(shù):第一個為字符串類型,用來設(shè)定轉(zhuǎn)換的格式;第二個則是需要轉(zhuǎn)換的數(shù)據(jù)或數(shù)據(jù)集合。每個格式項都采用下面的形式并包含以下組件:{索引[,對齊][:格式字符串]}“索引”(也叫參數(shù)說明符)是一個從0開始的數(shù)字,用來標識需要轉(zhuǎn)換的數(shù)據(jù)對象。也就是說,當索引為0時,其對應(yīng)需要轉(zhuǎn)換的第一個數(shù)據(jù)對象,如果索引為1,則對應(yīng)第二個數(shù)據(jù)對象,依次類推,我們可以把它理解成為占位符。通過指定相同的索引,多個格式項可以引用轉(zhuǎn)換數(shù)據(jù)對象列表中的同一個元素。每個索引都可以引用要轉(zhuǎn)換數(shù)據(jù)對象列表中的任一對象。例如,如果有三個要轉(zhuǎn)換的數(shù)據(jù)對象,則可以通過指定類似于“{1}{0}{2}”的復(fù)合格式字符串來設(shè)置第二、第一和第三個對象的格式。格式項未引用的對象會被忽略。如果索引指定了超出數(shù)據(jù)對象列表范圍的項,將導(dǎo)致運行時異常:txtFormat.Text=string.Format("貨幣:{0:C};百分比:{1:P};十六進制:{0:X}",12,0.35);上面的代碼分別將數(shù)字12轉(zhuǎn)換成為貨幣格式和十六進制數(shù),而將0.35轉(zhuǎn)換成為百分比?!皩R”是可選的一個帶符號的整數(shù),指示設(shè)置了格式的字段寬度。如果“對齊”值小于設(shè)置了格式的字符串的長度,則“對齊”會被忽略,并且使用設(shè)置了格式的字符串的長度作為字段寬度。如果“對齊”為正數(shù),則字段中設(shè)置了格式的數(shù)據(jù)為右對齊;如果“對齊”為負數(shù),則字段中設(shè)置了格式的數(shù)據(jù)為左對齊。如果需要填充,則使用空白。如果指定“對齊”,就需要使用逗號:txtFormat.Text=string.Format("右對齊:[{0,10}];左對齊:[{0,-10}];對齊失效:[{0,2}]","Tom");同樣是將Tom進行格式化,當我們使用“{0,10}”這種格式的時候,轉(zhuǎn)換的結(jié)果就是在Tom的前面增加7個空格以補齊10位長度,而使用“{0,-10}”時,則會在其后面添加7個空格以補齊10位長度。但是在“{0,2}”中,對齊的數(shù)值小于“Tom”的長度,因此“對齊”就失效了。格式字符串則是用來設(shè)定需要設(shè)定的轉(zhuǎn)換格式,表10-7列出了常用的格式字符串。10.4.5TreeView在WinForm中TreeView控件用樹的方式展示層次節(jié)點,通過這些節(jié)點,我們可以清晰地查看數(shù)據(jù)及其它們之間的從屬關(guān)系。傳統(tǒng)上,節(jié)點對象包含值,可以引用其他節(jié)點,一個節(jié)點可以包含其他節(jié)點,這時該節(jié)點稱為父節(jié)點,它所包含的節(jié)點稱為子節(jié)點。只有子節(jié)點沒有父節(jié)點的節(jié)點稱為根節(jié)點,在WinForm中TreeView控件可以包含多個根節(jié)點,如圖10-21所示。作為所有節(jié)點的管理者,TreeView控件本身的常用屬性并不多,如表10-8所示。TreeNode是TreeView控件的重要組成部分,在WinForm中TreeView控件的每一個節(jié)點都是一個TreeNode類的實例,每一個TreeNode對象又都具有Nodes屬性來設(shè)置和管理它的子節(jié)點,TreeNode對象的常用屬性如表10-9所示。對于TreeView控件來說,最為重要的就是對其中包含的節(jié)點進行相關(guān)的操作和管理,因此對TreeView的應(yīng)用主要就集中在添加節(jié)點、取得選中的節(jié)點以及用戶選中節(jié)點后的操作等幾個方面。為TreeView控件添加節(jié)點的方式有兩種。首先,我們可以通過WinForm中的TreeNode編輯器在圖形界面中完成節(jié)點的設(shè)置,將TreeView控件添加到窗體中后找到其Nodes屬性,點擊后打開TreeNode編輯器。在打開的TreeNode編輯器左側(cè)的“選擇要編輯的節(jié)點(N):”下方,我們可以看到當前TreeView控件中已經(jīng)添加的所有節(jié)點及其層次結(jié)構(gòu),選中其中的某一個節(jié)點,可以在窗體右側(cè)“節(jié)點X的屬性(P):”下方看到當前選中節(jié)點的常用屬性,如圖10-23所示。在節(jié)點列表的下方,我們可以看到兩個按鈕。“添加根(R)”按鈕的作用是為TreeView控件添加一個根節(jié)點。而“添加子級(C)”按鈕則可以為當前選中節(jié)點添加子節(jié)點。在節(jié)點列表的右側(cè),自上而下分別是上移按鈕、下移按鈕和刪除按鈕。當我們選中某個節(jié)點后點擊上移按鈕,該節(jié)點就會向上移動;如果點擊下移按鈕,那么該節(jié)點就會向下移動;點擊刪除按鈕就可以刪除該節(jié)點及其子節(jié)點。通過這幾個按鈕我們就可以根據(jù)需要設(shè)計出完整的TreeView控件。使用代碼方式添加節(jié)點需要先創(chuàng)建TreeNode對象,然后通過調(diào)用Add()方法,將其添加到相應(yīng)節(jié)點的Nodes屬性中:TreeNodetn1=newTreeNode("根節(jié)點1");trvFilmType.Nodes.Add(tn1);trvFilmType.Nodes.Add(newTreeNode("根節(jié)點2"));trvFilmType.Nodes.Add("根節(jié)點3");在上面的代碼中我們采用三種方式向TreeView控件中添加了根節(jié)點。第一種方式首先創(chuàng)建了一個TreeNode對象,在實例化的時候我們通過其構(gòu)造向該對象傳遞了一個字符串類型的參數(shù)作為其Text屬性的值,然后調(diào)用TreeView控件Nodes屬性的Add()方法將其添加到TreeView控件中。第二種方式其實和第一種方式是一樣的,只不過我們沒有再顯式地創(chuàng)建TreeNode對象,而是在調(diào)用Add()方法的時候臨時創(chuàng)建了它,同時依然通過其構(gòu)造方法傳遞了字符串參數(shù)作為其文本值。第三種方式直接在調(diào)用Add()方法的時候傳遞字符串作為參數(shù),節(jié)點則是由系統(tǒng)幫助我們來創(chuàng)建。無論采用哪種方式,只要是通過TreeView控件的Nodes屬性添加的節(jié)點都將是樹控件的根節(jié)點,如果需要為某個節(jié)點添加子節(jié)點,就需要通過該節(jié)點的Nodes屬性來完成:tn1.Nodes.Add("子節(jié)點1");tn1.Nodes.Add(newTreeNode("子節(jié)點2"));trvFilmType.Nodes[1].Nodes.Add("子節(jié)點3");trvFilmType.Nodes[1].Nodes.Add(newTreeNode("子節(jié)點4"));添加子節(jié)點的方式我們也給出了兩種。如果我們明確知道當前節(jié)點的名稱,則可以通過第一種方式來為它添加子節(jié)點。如果不知道當前節(jié)點的名稱,我們就只能夠通過第二種方式,也就是當前節(jié)點在Nodes中的排列位置找到該節(jié)點,然后再為其添加子節(jié)點。一般來說,對樹控件進行各種操作的時候都會和循環(huán)結(jié)合在一起,例如將數(shù)據(jù)表中的數(shù)據(jù)填充到TreeView控件中等。樹控件的節(jié)點層級越多,所需要的循環(huán)結(jié)構(gòu)越復(fù)雜,因此在實際應(yīng)用過程中最好不要創(chuàng)建操作三級的樹控件,否則程序?qū)兊煤軓?fù)雜。

10.5查看電影信息

10.5.1問題在音像店管理系統(tǒng)中,當用戶成功登錄到系統(tǒng)中以后,接下來就需要根據(jù)用戶自己的喜好查找電影并查看電影的詳細信息。這里我們首先需要用一個列表的方式將電影的主要信息展示出來,同時要提供相應(yīng)的操作方式供用戶查找自己感興趣的電影,如圖10-26所示。該窗體的主要要求如下:(1)窗體運行時要求在屏幕中央,不能最大化和最小化,也不能夠改變大小。(2)顯示電影類型的下拉列表只能夠選擇不能輸入,同時為了方便用戶需要增加一個“選擇全部”選擇項用來查看所有電影。(3)頁面首次加載時需要以列表的形式顯示出所有電影的信息,包括電影名稱、主演、價格和類型。(4)當用戶選擇了某部類型的電影時,可實現(xiàn)對電影信息的查詢功能。雙擊列表中的某一部影片后,以模式窗體打開影片詳細信息窗體并顯示該影片的詳細信息。對于該窗體的要求如下:(1)窗體運行時要求在屏幕中央,不能最大化和最小化,也不能夠改變大小。(2)顯示電影類型的下拉列表只能夠選擇不能輸入,但是不需要添加“選擇全部”項。(3)根據(jù)由列表窗體傳遞過來的電影編號查詢電影詳細信息并顯示在窗體的相應(yīng)位置。(4)由于我們還沒有將整個程序整合,因此“保存”按鈕功能不需要實現(xiàn),但是“關(guān)閉”按鈕功能需要實現(xiàn)。10.5.2需求分析下面我們需要根據(jù)上面提出的要求做出詳細的需求分析。1.界面設(shè)計電影信息列表窗體的界面元素設(shè)計如表10-10所示。電影詳細信息窗體的界面元素設(shè)計如表10-11所示。2.添加“選擇全部”項在前面的章節(jié)中我們已經(jīng)學習了如何將數(shù)據(jù)表中的數(shù)據(jù)放置到下拉列表控件中,但是在進行操作的時候有一個很重要的限制,即數(shù)據(jù)一旦通過DataSource屬性綁定到控件上后,就不允許再修改控件中的數(shù)據(jù),那么我們該如何將“選擇全部”這樣一個新的選擇項添加到下拉列表中呢?方法當然有很多種,例如我們可以直接在數(shù)據(jù)庫中添加一條這樣的數(shù)據(jù),也可以循環(huán)遍歷數(shù)據(jù)表的Rows屬性,將其中的數(shù)據(jù)依次通過Add()方法添加到ComboBox控件中。但是本章我們將采用一種新的方式來解決這個問題。事實上,仔細分析一下ComboBox控件和數(shù)據(jù)表我們就會發(fā)現(xiàn),在使用DataSource屬性進行數(shù)據(jù)綁定的時候,控件中要顯示什么數(shù)據(jù)完全是由數(shù)據(jù)表來決定的,于是我們就有了一個新的思路:不能修改控件的數(shù)據(jù),那我們就直接修改數(shù)據(jù)表中的數(shù)據(jù),然后再進行數(shù)據(jù)綁定,這樣也可以解決問題。整個操作過程其實并不復(fù)雜:List<FilmType>types=newList<FilmType>();//在第一條顯示的是全部電影FilmTypet=newFilmType();t.ID=0;t.Name="全部電影";types.Add(t);using(SqlConnectionconn=newSqlConnection(strConn)){stringstrSql="select*fromFilmType";SqlCommandcomm=newSqlCommand(strSql,conn);conn.Open();SqlDataReaderdr=comm.ExecuteReader();FilmTypemodel=null;while(dr.Read()){model=newFilmType();model.ID=(int)dr["ID"];model.Name=dr["Name"].ToString();model.ParentID=(int)dr["ParentID"];model.Desc=dr["Desc"].ToString();model.State=(int)dr["State"];

types.Add(model);}dr.Close();}cboFilmType.DisplayMember="Name";cboFilmType.ValueMember="ID";cboFilmType.DataSource=types;上面的代碼大部分我們都已經(jīng)很熟悉了,首先依然是創(chuàng)建一個數(shù)據(jù)庫連接對象,然后通過閱讀器對象SqlDataReader讀取數(shù)據(jù),循環(huán)添加到List集合中。因為需要在下拉框中第一行出現(xiàn)“選擇全部”,所以,我們在添加數(shù)據(jù)到集合前,先添加進集合。最后我們用這個數(shù)據(jù)表對象完成了ComboBox控件的數(shù)據(jù)綁定,由于在數(shù)據(jù)表中“選擇全部”位于第一行,因此綁定后該選項就會出現(xiàn)在ComboBox控件的第一項。事實上,在實際開發(fā)過程中我們經(jīng)常會遇到無法修改控件的值,或者修改起來很困難,這個時候就可以通過直接修改控件數(shù)據(jù)源的方式來實現(xiàn)我們所需要的操作。3.數(shù)據(jù)查詢數(shù)據(jù)查詢是我們需要重點實現(xiàn)的功能,根據(jù)用戶給出的條件生成相應(yīng)的查詢語句,在數(shù)據(jù)庫中執(zhí)行后得到查詢結(jié)果。第一步提取數(shù)據(jù)的工作并不復(fù)雜,而且在前面我們已經(jīng)做過很多次了:stringconn=ConfigurationManager.ConnectionStrings["SQL"].ConnectionString;SqlConnectioncn=newSqlConnection(conn);stringstrSql="selectF.ID,F.Name,F.Actors,F.Price,T.NameTypeNamefromFilmF";strSql+="innerjoinFilmTypeTonF.TypeID=T.ID";這里要注意的是,有一個條件是“全部電影”,也就是說在組合查詢語句的時候,如果是全部電影則不需要加條件,而只有選中某一個類型的時候才需要加上查詢條件。if(id>0)strSql+="whereF.TypeID="+id.ToString();SqlCommandcomm=newSqlCommand(strSql,conn);conn.Open();SqlDataReaderdr=comm.ExecuteReader();4.顯示電影信息對電影信息的查看我們需要提供兩種方式。首先我們需要用列表的方式將查詢到的電影信息呈現(xiàn)出來,這一步操作我們可以使用ListView控件來實現(xiàn):lsvShowData.Items.Clear();while(dr.Read()){ListViewItemitem=newListViewItem();item.Tag=(int)dr["ID"]; //該屬性用來保存當前數(shù)據(jù)的ID值item.SubItems[0].Text=dr["Name"].ToString();item.SubItems.Add(dr["Actors"].ToString());item.SubItems.Add(string.Format("{0:C}",dr["Price"]));item.SubItems.Add(dr["TypeName"].ToString());lsvShowData.Items.Add(item);}dr.Close();操作和我們在前面學習到的方式是一樣的,只不過在循環(huán)開始之前我們調(diào)用了ListView控件Items屬性的Clear()方法,該方法的作用是將ListView控件中的數(shù)據(jù)行全部清除。這么做的原因是我們需要用這個控件反復(fù)顯示數(shù)據(jù),不過不做這個操作數(shù)據(jù)就會累加在一起。另外一個需要主意的地方是我們使用到了ListViewItem對象的Tag屬性,該屬性主要用來保存和對象相關(guān)的數(shù)據(jù),這里我們保存的是電影的編號。我們需要做的第二個顯示工作是在電影詳細信息窗體中顯示電影的詳細信息,要完成這個工作我們需要經(jīng)過幾個步驟。首先需要我們在電影信息列表窗體中獲得用戶選擇的電影的編號,然后將這個編號傳遞到電影詳細信息窗體,最后根據(jù)這個編號查詢電影信息并顯示。本次我們設(shè)定的操作方式是,用戶在電影信息列表中雙擊某條電影信息就可以打開詳細信息窗體,因此首先我們在ListView控件的事件列表中找到DoubleClick事件,雙擊后在系統(tǒng)自動生成的事件處理程序中完成后續(xù)的操作:privatevoidlsvShowData_DoubleClick(objectsender,EventArgse){if(lsvShowData.SelectedItems.Count>0){intid=(int)lsvShowData.SelectedItems[0].Tag;

frmFilmDetailsfd=newfrmFilmDetails(id);fd.ShowDialog();}}在這段處理程序中,我們首先添加了一個if結(jié)構(gòu),這么做的目的是確保在有電影被選中的情況下才執(zhí)行該操作,因為我們用的是ListView控件的雙擊事件,有可能會出現(xiàn)用戶在沒有選中任何行的情況下雙擊控件而觸發(fā)事件。在if結(jié)構(gòu)中,我們可以通過ListView控件的SelectedItems屬性取得所有選中項,ListView控件本身就支持多選,盡管我們設(shè)定了其MultiSelect屬性為false,但是在訪問用戶選中的行時依然需要通過SelectedItems屬性,當然因為只能夠選擇一行,因此下標就只能是零了。通過選中行的Tag屬性,就可以取得電影的編號。接下來的窗體間傳參我們在前面的章節(jié)中已經(jīng)學習過了,這里就不再重復(fù)說明。將電影的編號傳遞到詳細信息窗體后,我們就可以根據(jù)這個編號到數(shù)據(jù)庫中查找電影信息并顯示在窗體中,不過在這之前我們還需要首先將電影分類信息綁定到ComboBox控件上,具體做法可參考上一個窗體中電影類型的數(shù)據(jù)讀取和綁定,不過這一次我們不用加上“選擇全部”了。接下來就是具體的數(shù)據(jù)顯示了:using(SqlConnectionconn=newSqlConnection(strConn)){stringstrSql="select*fromFilmwhereID="+filmID.ToString();SqlCommandcomm=newSqlCommand(strSql,conn);conn.Open();SqlDataReaderdr=comm.ExecuteReader();while(dr.Read()){txtName.Text=dr["Name"].ToString();txtActors.Text=dr["Actors"].ToString();txtPrice.Text=string.Format("{0:C}",dr["Price"]);txtAmount.Text=dr["Amount"].ToString();txtDesc.Text=dr["Desc"].ToString();cboType.SelectedValue=dr["TypeID"];}dr.Close();}首先創(chuàng)建數(shù)據(jù)庫連接對象,然后使用SqlDataReader對象來提取數(shù)據(jù),當然我們這里的SQL語句添加了根據(jù)電影編號查詢的條件,在將數(shù)據(jù)填充到數(shù)據(jù)表中以后,我們通過一個if結(jié)構(gòu)對數(shù)據(jù)表中的數(shù)據(jù)行做了判斷,已確定成功讀取了數(shù)據(jù)。具體的數(shù)據(jù)顯示也沒有復(fù)雜之處,我們是根據(jù)電影的編號進行查詢的,如果存在數(shù)據(jù)那么肯定就只有一行數(shù)據(jù),因此在讀取數(shù)據(jù)的時候行下標就賦值為零。需要注意顯示數(shù)據(jù)的最后一行,ComboBox控件的數(shù)據(jù)是使用數(shù)據(jù)表綁定的,因此要通過其SelectedValue設(shè)定其選中行才行。10.5.3實現(xiàn)電影查看本章的案例是本書中我們所制作的最復(fù)雜的程序,frmFilmList窗體代碼如下:publicpartialclassfrmFilmList:Form{publicfrmFilmList(){InitializeComponent();}stringstrConn=ConfigurationManager.ConnectionStrings["SQL"].ConnectionString;privatevoidfrmFilmList_Load(objectsender,EventArgse){

BindList();}privatevoidBindList(){List<FilmType>types=newList<FilmType>();FilmTypet=newFilmType(); //在第一條顯示的是全部電影t.ID=0;t.Name="全部電影";types.Add(t);using(SqlConnectionconn=newSqlConnection(strConn)){stringstrSql="select*fromFilmType";SqlCommandcomm=newSqlCommand(strSql,conn);conn.Open();SqlDataReaderdr=comm.ExecuteReader();FilmTypemodel=null;while(dr.Read())

{model=newFilmType();model.ID=(int)dr["ID"];model.Name=dr["Name"].ToString();model.ParentID=(int)dr["ParentID"];model.Desc=dr["Desc"].ToString();model.State=(int)dr["State"];types.Add(model);}dr.Close();}cboFilmType.DisplayMember="Name";cboFilmType.ValueMember="ID";cboFilmType.DataSource=types;}privatevoidBindListView(intid){lsvShowData.Items.Clear();using(SqlConnectionconn=newSqlConnection(strConn)){stringstrSql="selectF.ID,F.Name,F.Actors,F.Price,T.NameTypeNamefromFilmF";strSql+="innerjoinFilmTypeTonF.TypeID=T.ID";if(id>0)strSql+="whereF.TypeID="+id.ToString();SqlCommandcomm=newSqlCommand(strSql,conn);conn.Open();SqlDataReaderdr=comm.ExecuteReader();while(dr.Read()){ListViewItemitem=newListViewItem();item.Tag=(int)dr["ID"];item.SubItems[0].Text=dr["Name"].ToString();item.SubItems.Add(dr["Actors"].ToString());

item.SubItems.Add(string.Format("{0:C}",dr["Price"]));item.SubItems.Add(dr["TypeName"].ToString());lsvShowData.Items.Add(item);}dr.Close();}}privatevoidcboFilmType_SelectedIndexChanged(objectsender,EventArgse){intid=(int)cboFilmType.SelectedValue;BindListView(id);}privatevoidlsvShowData_DoubleClick(objectsender,EventArgse){if(lsvShowData.SelectedItems.Count>0)

{intid=(int)lsvShowData.SelectedItems[0].T

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論