原文作者:MSDN

原文地址: http://blogs.msdn.com/brada/archive/2009/07/29/business-apps-example-for-silverlight-3-rtm-and-net-ria-services-july-update-part-xx-visual-basic-vb-and-wpf-support.aspx

翻译发布: http://www.clubof.net/Translation/Article.aspx?ArticleId=1182

翻译内容:

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

为了完成这个示例,需要以下相关内容或软件(长期100%免费):

  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)

   4:

   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

11:

12:

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

在这里,我们定义了查询、更新以及插入的方法。

然后,为了展示我们的POCO帮助,我创建了一个方法用于返回来源的总数

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

        Get

            Return _Name

        End Get

        Set(ByVal value As String)

            _Name = value

        End Set

    End Property

    Private _Count As Integer

    Public Property Count() As Integer

        Get

            Return _Count

        End Get

        Set(ByVal value As Integer)

            _Count = value

        End Set

    End Property

End Class



image

在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

image

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

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


为了SEO(搜索引擎优化)的考虑,我们通过处理两个事件以实现深链接。
分别是:

'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

image_thumb[100]

以及

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

image_thumb[98]
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


导出数据到Excel的代码也非常的容易。

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


image

为了一些多样性变化,我创建了一个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

image

   
About author
Disclaimer
The opinions and comments expressed herein are my own personal opinions and do not represent my employer's view in any way.
Comments
No comments.
Add comment
Title
Title is required.
Name
Name is required.
Email
Please input your personal email with valid format.
Comments
Please input comment content.
Captcha Refresh
Input captcha:

Subscription

Statistics

Locations of visitors to this page