Business Apps Example for Silverlight 3 RTM and .NET RIA Services July Update

155 views 0 comments last modified about 9 years ago Raymond Tang

In this page





一些人在我的博客中评论到,他们希望看到在我的系列中能够对我在 Mix09 上演讲的话题 “building business applications with Silverlight 3” 有Visual Basic的阐释更新。由于 VB在业务应用领域是非常重要的, 因此我完全能够接受这个请求。与此同时由于我从事这个领域,我还想展示一个通过我们支持的非常棒的ADO.NET Data Services来构建的RIA Services 类型的WPF客户端程序。这个跟我之前展示的Winforms的例子比较相似。


  1. VS2008 SP1 (包含 Sql Express 2008)
  2. Silverlight 3 RTM
  3. .NET RIA Services July '09 Preview

此外,还可以在 这里下载完整的示例文档 ,当然,可以在这里查看 正在运行的程序


Part 1: Navigation Basics 部分中没有任何代码,所以VB版本和之前发布内容一致。

Part 2: Rich Data Query 部分有一些更有趣的代码片段。首先让我们看一下 DomainService类

   1: <EnableClientAccess()> _

   2: Public Class SuperEmployeeDomainService

   3:     Inherits LinqToEntitiesDomainService(Of NORTHWNDEntities)


   5:     Public Function GetSuperEmployees() As IQueryable(Of SuperEmployee)

   6:         Dim q = From emp In Me.Context.SuperEmployeeSet _

   7:                 Where emp.Issues > 100 _

   8:                 Order By emp.EmployeeID

   9:         Return q

10:     End Function



13:     Public Sub UpdateSuperEmployee(ByVal currentSuperEmployee As SuperEmployee)

14:         Me.Context.AttachAsModified(currentSuperEmployee, Me.ChangeSet.GetOriginal(currentSuperEmployee))

15:     End Sub

16:     Public Sub InsertSuperEmployee(ByVal superEmployee As SuperEmployee)

17:         Me.Context.AddToSuperEmployeeSet(superEmployee)

18:     End Sub



Public Function GetOrigins() As IQueryable(Of Origin) Dim q = (From emp In Context.SuperEmployeeSet _ Select emp.Origin).Distinct().Select(Function(name) New Origin With {.Name = name, .Count = Context.SuperEmployeeSet.Count(Function(emp) emp.Origin.Trim() = name.Trim())}) q = q.Where(Function(emp) emp.Name IsNot Nothing) Return q End Function

并且还定义了一个POCO类用于返回来源总数的数据给客户端的AutoComplete 输入框控件
Public Class Origin

    Public Sub New()

    End Sub

    Private _Name As String

    <Key()> _

    Public Property Name() As String


            Return _Name

        End Get

        Set(ByVal value As String)

            _Name = value

        End Set

    End Property

    Private _Count As Integer

    Public Property Count() As Integer


            Return _Count

        End Get

        Set(ByVal value As Integer)

            _Count = value

        End Set

    End Property

End Class


在Silverlight项目的客户端程序中,我基本所有数据均是通过直接在Xaml中绑定,因此这部分的代码在VB中是一样的。不过我创新了一个名为 AddNewEmployee的 子窗体(ChildWindow),代码如下。

Partial Public Class AddNewWindow Inherits ChildWindow Private _NewEmployee As SuperEmployee Public Property NewEmployee() As SuperEmployee Get Return _NewEmployee End Get Set(ByVal value As SuperEmployee) _NewEmployee = value End Set End Property Public Sub New() InitializeComponent() NewEmployee = New SuperEmployee() NewEmployee.LastEdit = DateTime.Now.[Date] Me.newEmployeeForm.CurrentItem = NewEmployee End Sub Private Sub OKButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) newEmployeeForm.CommitEdit() Me.DialogResult = True End Sub Private Sub CancelButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) Me.DialogResult = False End Sub End Class


Private Sub AddNew_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Dim w = New AddNewWindow() AddHandler w.Closed, AddressOf addNewWindow_Closed w.Show() End Sub Private Sub addNewWindow_Closed(ByVal sender As Object, ByVal e As EventArgs) Dim win = TryCast(sender, AddNewWindow) Dim context = TryCast(dds.DomainContext, SuperEmployeeDomainContext) If win.DialogResult = True Then context.SuperEmployees.Add(win.NewEmployee) End If End Sub


Part 3: Authentication –这部分也没有任何代码,因此C#和VB版本是一致的。

Part 4: SEO, Export to Excel and Out of Browser


'Executes when the user navigates to this page. Protected Overrides Sub OnNavigatedTo(ByVal e As System.Windows.Navigation.NavigationEventArgs) Dim qs = NavigationContext.QueryString If qs.ContainsKey("EmpId") Then dds.FilterDescriptors.Add(New FilterDescriptor("EmployeeID", FilterOperator.IsEqualTo, qs("EmpId"))) End If End Sub



Private Sub dataGrid1_SelectionChanged(ByVal sender As System.Object, ByVal e As System.Windows.Controls.SelectionChangedEventArgs) Dim emp = TryCast(dataGrid1.SelectedItem, SuperEmployee) If emp IsNot Nothing Then PermalinkTextBox.Text = (Application.Current.Host.Source.ToString().Replace("ClientBin/MyApp.xap", "") & "#/Home?EmpId=") & emp.EmployeeID End If End Sub

Sitemap.aspx 的服务器端代码以及default.aspx中的替换内容是不相同的--为了在default.aspx中加入一些URL重写的代码,使得服务端和客户端都有权限访问深级的链接。

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load Dim empId As String = Request.QueryString("EmpId") Dim deepLink = "/Home?EmpId=" & empId If empId IsNot Nothing Then Response.Write("< script type=text/javascript>window.location.hash='#" & deepLink & "';< /script>") End If End Sub


Private Sub ExportToExcel_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Dim context = TryCast(dds.DomainContext, SuperEmployeeDomainContext) Dim s = Application.GetResourceStream(New Uri("excelTemplate.txt", UriKind.Relative)) Dim dialog = New SaveFileDialog() dialog.DefaultExt = "*.xml" dialog.Filter = "Excel Xml (*.xml)|*.xml|All files (*.*)|*.*" If dialog.ShowDialog() = False Then Exit Sub End If Using sw = New StreamWriter(dialog.OpenFile()) Dim sr = New StreamReader(s.Stream) While Not sr.EndOfStream Dim line = sr.ReadLine() If line = "***" Then Exit While End If sw.WriteLine(line) End While For Each emp In context.SuperEmployees sw.WriteLine("") sw.WriteLine(""String"">{0}< /Data>< /Cell>", emp.Name) sw.WriteLine(""String"">{0}< /Data>< /Cell>", emp.Origin) sw.WriteLine(""String"">{0}< /Data>", emp.Publishers) sw.WriteLine(""Number"">{0}< /Data>< /Cell>", emp.Issues) sw.WriteLine("") Next While Not sr.EndOfStream sw.WriteLine(sr.ReadLine()) End While End Using End Sub


在后,在 Part 5: Astoria, Add Service Reference and WinForms 部分中,在web项目中定义ADO.NET Data Services如下所示:

Public Class SuperEmployeeWebDataService Inherits DataService(Of [SuperEmployeeDomainService]) Implements IServiceProvider ' This method is called only once to initialize service-wide policies. Public Shared Sub InitializeService(ByVal config As IDataServiceConfiguration) ' TODO: set rules to indicate which entity sets and service operations are visible, updatable, etc. ' Examples: config.SetEntitySetAccessRule("*", EntitySetRights.All) config.SetServiceOperationAccessRule("*", ServiceOperationRights.All) End Sub


为了一些多样性变化,我创建了一个WPF客户端程序用于这个服务。我还是用了 WPF Control Toollit中的非常酷的 DataGrid控件。


Private Sub LoadButton_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs) Handles LoadButton.Click Context = New SuperEmployeeDomainService( _ New Uri("http://localhost:4558/SuperEmployeeWebDataService.svc/")) Context.MergeOption = MergeOption.AppendOnly Dim q = From emp In Context.SuperEmployee _ Where emp.Issues > 10 _ Order By emp.Name _ Select emp Dim savedCursor = Cursor Cursor = Cursors.Wait Me.DataGrid1.ItemsSource = q.ToList() Cursor = savedCursor End Sub


Private Sub DataGrid1_CurrentCellChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Dim selectedItem As SuperEmployee = Me.DataGrid1.CurrentItem If selectedItem Is Nothing Then Return End If Dim q = From emp In Context.SuperEmployee _ Where emp.EmployeeID = selectedItem.EmployeeID _ Select emp Dim employee = q.FirstOrDefault() employee.Gender = selectedItem.Gender employee.Issues = selectedItem.Issues employee.LastEdit = selectedItem.LastEdit employee.Name = selectedItem.Name employee.Origin = selectedItem.Origin employee.Publishers = selectedItem.Publishers employee.Sites = selectedItem.Sites Context.UpdateObject(employee) Dim savedCursor = Cursor Cursor = Cursors.Wait Context.SaveChanges() Cursor = savedCursor End Sub



Add comment

Comments (0)

No comments yet.