Silverlight學習(三)


最近對WCFRIA+MVVM+Prism有了初步的認識,能夠簡單的實現一些數據庫的交互。這節主要講的是Silverlight通過domainservice和ado.net實體數據模型與數據庫的交互。本文的重點是與數據庫的交互,包括簡單的CURD,以下是實現的一些主要過程:

1.在Sql數據庫中新建userinfo表,包括的字段為id,name,age.數據庫創建的存儲過程為:

 1 USE [Test]
 2 GO
 3 
 4 /****** Object:  Table [dbo].[userinfo]    Script Date: 04/24/2014 15:31:56 ******/
 5 SET ANSI_NULLS ON
 6 GO
 7 
 8 SET QUOTED_IDENTIFIER ON
 9 GO
10 
11 SET ANSI_PADDING ON
12 GO
13 
14 CREATE TABLE [dbo].[userinfo](
15     [ID] [varchar](50) NOT NULL,
16     [name] [varchar](50) NULL,
17     [age] [varchar](50) NULL,
18  CONSTRAINT [PK_userinfo] PRIMARY KEY CLUSTERED 
19 (
20     [ID] ASC
21 )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
22 ) ON [PRIMARY]
23 
24 GO
25 
26 SET ANSI_PADDING OFF
27 GO
userinfo

 

2.新建silverlight了應用程序,並啟用WcfRIA。為了簡便,我沒有單獨興建其他的項目。在web項目中添加model和servers兩個文件夾,model文件下主要存放ado實體數據模型,services文件夾存放domainservice。在silverlight客戶端需要新建ViewModel和Views文件夾,解決方案的截圖如下。

這里需要注意的是,ado.net實體數據模型需要進行一定設置才能引用。一般需要刪除兩個后綴為.tt的文件,並在添加模型時需要啟用編輯。

3.在silverlight服務端添加表userinfo的實體數據模型,並建立基於此模型的domainservice類。

 1   [EnableClientAccess()]
 2     public class DomainService1 : LinqToEntitiesDomainService<TestEntities>
 3     {
 4 
 5         // TODO:
 6         // 考慮約束查詢方法的結果。如果需要其他輸入,
 7         //可向此方法添加參數或創建具有不同名稱的其他查詢方法。
 8         // 為支持分頁,需要向“userinfo”查詢添加順序。
 9         public IQueryable<userinfo> GetUserinfo()
10         {
11             return this.ObjectContext.userinfo;
12         }
13 
14         public void InsertUserinfo(userinfo userinfo)
15         {
16             if ((userinfo.EntityState != EntityState.Detached))
17             {
18                 this.ObjectContext.ObjectStateManager.ChangeObjectState(userinfo, EntityState.Added);
19             }
20             else
21             {
22                 this.ObjectContext.userinfo.AddObject(userinfo);
23             }
24         }
25         public IQueryable<userinfo> GetUserByName(string name)
26         {
27             return this.ObjectContext.userinfo.Where(r=>r.name.StartsWith(name));
28         }  
29         public void UpdateUserinfo(userinfo currentuserinfo)
30         {
31             this.ObjectContext.userinfo.AttachAsModified(currentuserinfo, this.ChangeSet.GetOriginal(currentuserinfo));
32         }
33 
34         public void DeleteUserinfo(userinfo userinfo)
35         {
36             if ((userinfo.EntityState != EntityState.Detached))
37             {
38                 this.ObjectContext.ObjectStateManager.ChangeObjectState(userinfo, EntityState.Deleted);
39             }
40             else
41             {
42                 this.ObjectContext.userinfo.Attach(userinfo);
43                 this.ObjectContext.userinfo.DeleteObject(userinfo);
44             }
45         }
46     }
DomainService

4.在服務端View文件夾中建立userview silverlight的用戶控件。前台代碼為:

 1 <UserControl
 2     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 5     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 6     xmlns:vm="clr-namespace:SilverlightFamework.ViewModel"
 7     xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" 
 8     xmlns:riaControls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.DomainServices"
 9     xmlns:Models="clr-namespace:SilverlightFamework.Web.Models"
10     xmlns:Services="clr-namespace:SilverlightFamework.Web.Services"
11     x:Class="SilverlightFamework.Views.UserView"
12     mc:Ignorable="d"
13     d:DesignHeight="300" d:DesignWidth="400">
14     <UserControl.DataContext>
15         <vm:UserViewModel/>
16     </UserControl.DataContext>
17     <Grid x:Name="LayoutRoot" Background="White">
18         <Grid.RowDefinitions>
19             <RowDefinition Height="50"/>
20             <RowDefinition Height="50"></RowDefinition>
21             <RowDefinition/>
22         </Grid.RowDefinitions>
23         <Button Content="添加" Width="50" Height="25" Command="{Binding OnInsert,Mode=OneWay}" CommandParameter="{Binding Text,ElementName=textbox1}" Margin="222,0,128,5"/>
24         <TextBox Text="{Binding UserInfo.age,Mode=TwoWay}" Width="100" HorizontalAlignment="Left" x:Name="txtage" Height="30"></TextBox>
25         <TextBox Text="{Binding UserInfo.name,Mode=TwoWay}" Width="100" Margin="105,0,195,0" x:Name="txtname" Height="30"></TextBox>
26             <sdk:DataGrid HorizontalAlignment="Left"  Grid.Row="2" VerticalAlignment="Top" 
27             AutoGenerateColumns="True"
28              ItemsSource="{Binding UserList,Mode=TwoWay}" SelectedItem="{Binding SelectItem,Mode=TwoWay}" />
29 
30         <TextBox Grid.Row="1" Width="50" Height="30" HorizontalAlignment="Left"  x:Name="txtSearch"></TextBox>
31         <Button Grid.Row="1" Width="50" Height="30" Content="查詢" Command="{Binding OnSearch,Mode=OneWay}"
32                 CommandParameter="{Binding Text,ElementName=txtSearch}"
33                 Margin="60,0,0,0" HorizontalAlignment="Left"></Button>
34         <Button Width="50" Height="30" Grid.Row="1" Margin="120,0,0,0" HorizontalAlignment="Left" 
35                 Content="刪除" Command="{Binding OnDelete,Mode=OneWay}"></Button>
36         <Button Grid.Row="1" Width="50" Height="30" Margin="200,0,0,0" HorizontalAlignment="Left" Content="更新"></Button>
37 
38     </Grid>
39 </UserControl>
userview

這里需要講的重點是,Silverlight的MVVM設計模式將前台代碼和后台的完全分離。前台的ui只負責控件的展示,一切的事件和數據源都在前台通過綁定來實現,不需要到后台賦值。控件的綁定有三種類型:OneTime,OneWay,TwoWay.OneTime顧名思義就是一次性的綁定,對控件只能影響一次。OneWay,不是一次綁定的意思哈,它指的是單向的綁定,控件值的改變不會影響數據源。比如DataGird中,我們改動了某一個數據,但是他的數據源並沒有變化,當我們再次加載的時候,它還是顯示原來的數據。TwoWay是指雙向綁定,控件的值發生改變,數據源也會隨之發生變化。

Button控件可以綁定Command命令,不需要實現click事件,同時可以通過CommandParameter傳遞參數,也就是當這個命令發生的時候傳遞的參數。本文傳遞了需要查詢的字段值,為控件綁定的CommandParameter="{Binding Text,ElementName=txtSearch}",也就是將txtSeatrch的值傳遞過去。

5.ViewModel是系統的核心部分,它連接着View以及Services,也就是連接着數據層和表現層。在ViewModel中,可以進行一些與數據庫有關的操作和其他的相關操作。在ViewModel中新建UserViewModel類,代碼如下:

這里,我們新建了4個命令,分別對應着數據庫的曾刪改查,DelegateCommand並不是自己封裝的類,它引用自prism。構造函數里面的初始化很重要,因為View中的DataContext的內容直接來自於構造函數。有時候,我們會發現已經為某個屬性賦值了,但是在前台並沒有綁定上,問題就是出在這里。這里建議需要綁定的屬性最好都能在構造函數中初始化。初始化之后,我們就可以在其他地方賦值,前台的綁定就能夠實現。下面具體說說數據的加載、增加、刪除、更新。

(1)數據的加載

silvertlight中Datagrid綁定的實體或者集合。我們通過domainservice提供的load方法能夠獲得數據表中的實體的集合。

 1    private IEnumerable<userinfo> userList;
 2         public IEnumerable<userinfo> UserList
 3         {
 4             get
 5             {
 6                 return userList;
 7             }
 8             set
 9             {
10                 if (value != userList)
11                 {
12                     userList = value;
13                     if (PropertyChanged != null)
14                     {
15                         PropertyChanged(this, new PropertyChangedEventArgs("UserList"));
16                     }
17                 }
18             }
19         }
View Code

(2)數據的查詢

數據的查詢和數據的加載有相似之處,查詢是有條件的加載。這里只實現單一條件的查詢,當然可以擴展成為多條件的查詢。需要對域服務類進行一定的擴展。

 1     public IEnumerable<userinfo> GetQueryList()
 2         {
 3              //domainservice = new DomainService1();
 4             if (!string.IsNullOrEmpty(searchText))
 5             {
 6            
 7                 LoadOperation<userinfo> loaduer = domainservice.Load(domainservice.GetUserByNameQuery(searchText));
 8                 return loaduer.Entities;
 9             }
10             else
11             {
12                 LoadOperation<userinfo> loaduers = domainservice.Load(domainservice.GetUserinfoQuery());
13                 return loaduers.Entities;
14             }
15         }
16         public ICommand OnSearch { get; set; }
17         public void SearchData(object obj)
18         {
19             searchText = obj.ToString();
20            UserList= GetQueryList();
21       
22         }
SearchData

值得注意的是,這里我們通過命令來調用查詢方法。

(3)數據的插入

數據的插入也是通過command來實現的。

 1     }
 2         public ICommand OnInsert { get; set; }
 3         public void AddData(object obj)
 4         {
 5          userinfo user= new userinfo();
 6          user.ID = Guid.NewGuid().ToString();
 7          user.name = userInfo.name;
 8          user.age = userInfo.age;
 9       //domainservice = new DomainService1();
10             domainservice.userinfos.Add(user);
11             domainservice.SubmitChanges(SubmitOperation => { RefreshData(); },null);
12         }
InsertData

這里在插入的時候,必須新建新的userinfo,因為我們的主鍵是自動生成的,而主鍵又是只讀的。若我們仍使用在構造函數中實例化的userinfo對象,則會跑出異常。一個新的對象可以解決這樣的問題。在插入成功后,通過lamda表達式來為屬性重新賦值,使我們添加的數據能夠及時的顯示。

(4)數據的更新

數據的更新比較簡單,它的要求是綁定的方式必須是twowa。通過domainservice.SubmitChanges()就能實現。

1    public ICommand OnUpdate { get; set; }
2         public void UpDateData(object obj)
3         {
4             userinfo user = this.SelectItem as userinfo;
5             domainservice.SubmitChanges(SubmitOperation => { RefreshData(); },null);
6         }
UpdateData

(5)數據的刪除

數據的刪除方法比較多,可以通過主鍵進行數據的刪除,也可以通過實現進行數據的刪除,本文是通過后者實現的。這里需要為DataGrid綁定selectitem,來獲取我們選擇行的值,在后台轉換為userinfo類型。通過domainservice.userinfos.Remove(userinfo)來實現刪除。

1   public ICommand OnDelete { get; set; }
2         public void DeleteData(object obj)
3         {
4             userinfo userinfos = this.SelectItem as userinfo;
5             domainservice.userinfos.Remove(userinfos);
6             domainservice.SubmitChanges(SubmitOperation => { RefreshData(); },null);
7         }
OnDelete

 

在進行調試的時候,發現數據的增刪改查並沒有及時的UI中顯示,后來通過重新加載的方法得意實現,不知道還有沒有更好的方法。

mvvm+prim 還有很多值得學習的地方,平時自己研究的並不是太深入。大家通過項目繼續學習。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM