饭饭TXT > 学习管理 > 《Visual Studio 2010 高级编程(英文出书版)》作者:Nick Randolph/等【完结】 > [Visual.Studio.2010.高级编程].Professional.Visual.Studio.2010.txt

第 107 页

作者:Nick Randolph/等 当前章节:15363 字 更新时间:2026-6-18 14:51

input argument values and asserting that the corresponding output argument values are as expected.

hostinG the workflow desiGner

One of the benefits in having a declarative configurable workflow is that it can be reconfigured at

will to support changing business requirements without the application needing to be recompiled.

This means (in theory) that an end user given the right tools (that is, the WF designer) should be

able to modify the workflow without requiring a developer to be involved (creating custom activities

is a different story, however). Of course it’s probably asking too much to have a casual end user use

the WF designer and modify a workflow without training — it really is a tool designed to be used

by developers. That said, with a little training, IT-savvy users (such as business analysts and so on)

could successfully take on this task.

If this is the case, it is quite easy to host the WF designer in your own application and expose it to

the end user for modification. The WF designer is a WPF component that you can host in your own

WPF applications, making it available to the users to modify a workflow as required. You can also

host the WF designer in Windows Forms using the WPF interoperability described in Chapter 18.

This chapter, however, will focus on hosting it natively in a WPF application.

The coverage of this topic assumes you have some experience working with WPF

and XAML. See Chapter 18 for more information on these topics.

720 .

chaPter 32 WindoWS WorkFloW FoundATion (WF)

Create a new WPF project, called WFDesignerHost. Add the following assembly references to the project:

.

System.Activities.dll

.

System.Activities.Core.Presentation.dll

.

System.Activities.Presentation.dll

You will also need to add a reference to any assemblies that contain custom activities that you want

to be used in the workflows through your application.

The designer has three main (separate) components: the Toolbox, the Properties window, and the

designer surface. Let’s create a user interface that instantiates and displays the three of these.

Open up the MainWindow.xaml file and set the name of the Grid control to WFLayoutGrid. Also

add three columns to this Grid (you will no doubt want to define some appropriate widths for these

columns at a later point in time). Host the Toolbox in the first column, the designer surface in the

second, and the Properties window in the third. The Toolbox can be created either declaratively in

XAML or in code, but the designer surface and Properties window can only be created in code. For

the purpose of this example, you’ll create all three of these controls in code.

Open up the code behind the MainWindow.xaml file. Import the following namespaces:

Vb

Imports System.Activities

Imports System.Activities.Core.Presentation

Imports System.Activities.Presentation

Imports System.Activities.Presentation.Toolbox

Imports System.Activities.Statements

Imports System.Linq

Imports System.Reflection

Imports System.Windows

Imports System.Windows.Controls

c#

using System;

using System.Activities;

using System.Activities.Core.Presentation;

using System.Activities.Presentation;

using System.Activities.Presentation.Toolbox;

using System.Activities.Statements;

using System.Linq;

using System.Reflection;

using System.Windows;

using System.Windows.Controls;

First, you need to register the designer metadata:

Vb

Private Sub RegisterMetadata()

Dim metaData As New DesignerMetadata()

metaData.Register()

End Sub

Hosting the Workflow Designer .

721

c#

private void RegisterMetadata()

{

DesignerMetadata metaData = new DesignerMetadata();

metaData.Register();

}

Now add the Toolbox to the page. You will find that the Toolbox is not automatically populated

with activities — instead you need to populate it yourself with the activities you want to make

available to the user. The following code handles this by creating an instance of the Toolbox and

adding all the activities in the same assembly as the Sequence activity to it.

Vb

Private Sub AddToolboxControl(ByVal parent As Grid, ByVal row As Integer,

ByVal column As Integer)

Dim toolbox As New ToolboxControl()

Dim category As New ToolboxCategory("Activities")

toolbox.Categories.Add(category)

Dim query = From type In Assembly.GetAssembly(GetType(Sequence)).GetTypes()

Where type.IsPublic AndAlso

Not type.IsNested AndAlso

Not type.IsAbstract AndAlso

Not type.ContainsGenericParameters AndAlso

(GetType(Activity).IsAssignableFrom(type) OrElse

GetType(IActivityTemplateFactory).IsAssignableFrom(type))

Order By type.Name

Select New ToolboxItemWrapper(type)

query.ToList().ForEach(Function(item)

category.Add(item)

Return Nothing

End Function)

Grid.SetRow(toolbox, row)

Grid.SetColumn(toolbox, column)

parent.Children.Add(toolbox)

End Sub

c#

private void AddToolboxControl(Grid parent, int row, int column)

{

ToolboxControl toolbox = new ToolboxControl();

ToolboxCategory category = new ToolboxCategory("Activities");

toolbox.Categories.Add(category);

var query = from type in Assembly.GetAssembly(typeof(Sequence)).GetTypes()

where type.IsPublic &&

722 .

chaPter 32 WindoWS WorkFloW FoundATion (WF)

!type.IsNested &&

!type.IsAbstract &&

!type.ContainsGenericParameters &&

(typeof(Activity).IsAssignableFrom(type) ||

typeof(IActivityTemplateFactory).IsAssignableFrom(type))

orderby type.Name

select new ToolboxItemWrapper(type);

query.ToList().ForEach(item => category.Add(item));

Grid.SetRow(toolbox, row);

Grid.SetColumn(toolbox, column);

parent.Children.Add(toolbox);

}

Now you add the designer and the Properties window (both are controls returned from instantiating

the WorkflowDesigner class):

Vb

Private Sub AddDesigner(ByVal parent As Grid,

ByVal designerRow As Integer,

ByVal designerColumn As Integer,

ByVal propertiesRow As Integer,

ByVal propertiesColumn As Integer)

Dim designer As New WorkflowDesigner()

designer.Load(New Sequence())

Grid.SetRow(designer.View, designerRow)

Grid.SetColumn(designer.View, designerColumn)

parent.Children.Add(designer.View)

Grid.SetRow(designer.PropertyInspectorView, propertiesRow)

Grid.SetColumn(designer.PropertyInspectorView, propertiesColumn)

parent.Children.Add(designer.PropertyInspectorView)

End Sub

c#

private void AddDesigner(Grid parent, int designerRow, int designerColumn,

int propertiesRow, int propertiesColumn)

{

WorkflowDesigner designer = new WorkflowDesigner();

designer.Load(new Sequence());

Grid.SetRow(designer.View, designerRow);

Grid.SetColumn(designer.View, designerColumn);

parent.Children.Add(designer.View);

Grid.SetRow(designer.PropertyInspectorView, propertiesRow);

Grid.SetColumn(designer.PropertyInspectorView, propertiesColumn);

parent.Children.Add(designer.PropertyInspectorView);

}

Now call these three functions from the window’s New method/constructor, like so:

summary .

723

Vb

Public Sub New()

InitializeComponent()

RegisterMetadata()

AddToolboxControl(WFLayoutGrid, 0, 0)

AddDesigner(WFLayoutGrid, 0, 1, 0, 2)

End Sub

c#

public MainWindow()

{

InitializeComponent();

RegisterMetadata();

AddToolboxControl(WFLayoutGrid, 0, 0);

AddDesigner(WFLayoutGrid, 0, 1, 0, 2);

}

Now you can run the project and test it. Your final user interface should look something like

Figure 32-14 (which can, of course, be improved upon by spending some time styling the page).

fiGure 32-14

suMMary

In this chapter, you learned that Windows Workflow is a means of defining a business process,

which is especially useful to use when you have a business process that changes frequently or is

a long running process. You also learned how to create and run a basic workflow, and how to

host the workflow designer in your own application. Windows Workflow is quickly becoming the

standard for implementing workflows on the Microsoft platform, enabling you to reuse the skills

you have gained here to also build workflows in the various products that support it.

33

Client application services

what’s in this chaPter?

.

Accessing client application services

.

Managing application roles

.

Persisting user settings

.

Specifying a custom login dialog

A generation of applications built around services and the separation of user experience

from backend data stores has seen requirements for occasionally connected applications

emerge. Occasionally connected applications are those that continue to operate regardless of

network availability. In Chapter 34 you will learn how data can be synchronized to a local

store to allow the user to continue to work when the application is offline. However, this

scenario leads to discussions (often heated) about security. Because security (that is, user

authentication and role authorization) is often managed centrally, it is difficult to extend so

that it incorporates occasionally connected applications.

In this chapter you become familiar with the client application services that extend ASP.NET

Application Services for use in client applications. ASP.NET Application Services is a provider-

based model for performing user authentication, role authorization, and profile management

that has in the past been limited to web services and web sites. In Visual Studio 2010, you can

configure your rich client application, either Windows Forms or WPF, to make use of these

services throughout your application to validate users, limit functionality based on what roles

users have been assigned, and save personal settings to a central location.

client serVices

Over the course of this chapter you are introduced to the different application services via a simple

WPF application. In this case it is an application called ClientServices, which you can create by

selecting the (C# or VB) WPF Application template from the File . New . Project menu item.

726 .

chaPter 33 clienT ApplicATion SerViceS

To begin using the client application services, you need to enable the checkbox on the Services tab

of the project properties designer, as shown in Figure 33-1. The default authentication mode is to

use Windows authentication. This is ideal if you are building your application to work within the

confines of a single organization and you can assume that everyone has domain credentials. Selecting

this option ensures that those domain credentials are used to access the roles and settings services.

Alternatively, you can elect to use Forms authentication, in which case you have full control over the

mechanism that is used to authenticate users. We return to this topic later in the chapter.

fiGure 33-1

You can also add the client application services to existing applications via the

Visual Studio 2010 project properties designer in the same way as for a new

application.

You will notice that when you enabled the client application services, an app.config file was added

to your application if one did not already exist. Of particular interest is the < system.web > section,

which should look similar to the following snippet:

< system.web >

< membership defaultProvider="ClientAuthenticationMembershipProvider" >

< providers >

< add name="ClientAuthenticationMembershipProvider" type=

"System.Web.ClientServices.Providers.ClientWindowsAuthentication

Client services .

727

MembershipProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral,

PublicKeyToken=31bf3856ad364e35" serviceUri="" connectionStringName="Default

Connection" credentialsProvider=""/>

</providers>

</membership>

<roleManager defaultProvider="ClientRoleProvider" enabled="true">

<providers>

<add name="ClientRoleProvider"

type="System.Web.ClientServices.Providers.ClientRoleProvider, System.Web.Ext

ensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"

serviceUri="" cacheTimeout="86400" connectionStringName="DefaultConnection"/>

</providers>

</roleManager>

</system.web>

Code snippet app.config

Here you can see that providers have been defined for membership and role management.

You can extend the client application services framework by building your own providers

that can talk directly to a database or to some other remote credential store such as Active

Directory. Essentially, all the project properties designer does is modify the app.config file

to use the providers that ship with the .NET Framework and define associated properties. To

implement your own providers, you need to create concrete classes that implement the abstract

methods defined in the System.Web.Security.RoleProvider, System.Web.Security

.MembershipProvider, or System.Configuration.SettingsProvider classes (depending on

which provider you are implementing).

After you define the default role and membership providers, you use the client application services

to validate the application user. To do this, you need to invoke the ValidateUser method on the

System.Web.Security.Membership class, as shown in the following snippet:

c#

using System.Web.Security;

public partial class MainWindow : Window{

public MainWindow(){

InitializeComponent();

}

private void Window_Loaded(object sender, RoutedEventArgs e){

if (Membership.ValidateUser(null, null)){

MessageBox.Show("User is valid");

}

else{

MessageBox.Show("Unable to verify user, application exiting");

this.Close();

return;

}

}

}

目录
设置
设置
阅读主题
字体风格
雅黑 宋体 楷书 卡通
字体大小
适中 偏大 超大
保存设置
恢复默认
手机
手机阅读
扫码获取链接,使用浏览器打开
书架同步,随时随地,手机阅读
首 页 < 上一章 章节列表 下一章 > 尾 页