• 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 还有很多值得学习的地方,平时自己研究的并不是太深入。大家通过项目继续学习。

    请关注微信公众号“跟我学前端”,谢谢大家!
  • 相关阅读:
    SVN服务的配置与管理
    SVN配置多仓库与权限控制
    SVN使用详解
    这个问题他又来了,如何学编程!
    乘风破浪的程序员们
    Java 学习路线(史上最全 2020 版 ~ 持续更新中)
    P4782 【模板】2-SAT 问题
    HDU
    2020.8.3
    Interesting Computer Game
  • 原文地址:https://www.cnblogs.com/ggz19/p/3685840.html
Copyright © 2020-2023  润新知