Sei sulla pagina 1di 220

Visual Studio Tools for Microsoft Dynamics GP 2013 R2

Programmers Guide
Copyright Copyright 2014 Microsoft Corporation. All rights reserved.

Limitation of liability This document is provided as-is. Information and views expressed in this document, including URL
and other Internet Web site references, may change without notice. You bear the risk of using it.

Some examples depicted herein are provided for illustration only and are fictitious. No real
association or connection is intended or should be inferred.

Intellectual property This document does not provide you with any legal rights to any intellectual property in any Microsoft
product.

You may copy and use this document for your internal, reference purposes.

Trademarks Microsoft, Dexterity, Microsoft Dynamics, Visual Basic, Visual Studio, Windows, Windows Server, and
Windows Vista are trademarks of the Microsoft group of companies.

All other trademarks are property of their respective owners.

Warranty disclaimer Microsoft Corporation disclaims any warranty regarding the sample code contained in this
documentation, including the warranties of merchantability and fitness for a particular purpose.

License agreement Use of this product is covered by a license agreement provided with the software product. If you have
any questions, please call the Microsoft Dynamics GP Customer Assistance Department at
800-456-0025 (in the U.S. or Canada) or +1-701-281-6500.

Publication date May 2014


Contents
Introduction ................................................................................................................................................. 2
Whats in this manual...................................................................................................................................2
Whats new in this release of Visual Studio Tools....................................................................................2
Prerequisites...................................................................................................................................................3
Symbols and conventions ............................................................................................................................3
Product support ............................................................................................................................................3

Part 1: Getting Started ................................................................................................................. 6


Chapter 1: SDK Installation ........................................................................................................ 7
Installation procedure ..................................................................................................................................7
Template registration....................................................................................................................................8
What was installed........................................................................................................................................9
Upgrading to a newer Visual Studio..........................................................................................................9

Chapter 2: Integration Basics.................................................................................................. 11


What Visual Studio Tools provides .......................................................................................................... 11
Architecture ................................................................................................................................................. 11
Creating a project ........................................................................................................................................12

Chapter 3: Upgrading an Integration .............................................................................. 15


Upgrading from Release 9 .........................................................................................................................15
Upgrading from Release 10 or later .........................................................................................................20

Part 2: Developing Integrations ................................................................................... 24


Chapter 4: WinForms ...................................................................................................................... 25
Adding a Dynamics GP form to a project ...............................................................................................25
WinForm properties....................................................................................................................................26
Adding controls...........................................................................................................................................27

Chapter 5: Control Reference ................................................................................................ 29


Buttons..........................................................................................................................................................29
TextBoxes......................................................................................................................................................31
Labels ............................................................................................................................................................32
ComboBoxes ................................................................................................................................................32
ListBoxes ......................................................................................................................................................32

Chapter 6: Dictionary Assembly Generator .............................................................. 33


Creating application assemblies ...............................................................................................................33
Output files ..................................................................................................................................................33
Using the Dictionary Assembly Generator .............................................................................................34
Optimizing the assembly generating process.........................................................................................36

Chapter 7: Accessing Dictionary Resources ............................................................ 37


Adding references.......................................................................................................................................37
Namespace...................................................................................................................................................38

PROGRAMMERS GUIDE i
C O N T E N T S

Dictionary class ...........................................................................................................................................38


Accessing additional resources .................................................................................................................39
Variables for dictionary resources ............................................................................................................39

Chapter 8: Events .............................................................................................................................. 41


Registering events.......................................................................................................................................41
Responding to events .................................................................................................................................43
Unregistering events...................................................................................................................................44

Chapter 9: Working with Tables ........................................................................................... 47


Tables in Microsoft Dynamics GP.............................................................................................................47
Table buffers.................................................................................................................................................48
Opening and closing tables .......................................................................................................................49
Keys...............................................................................................................................................................50
Retrieving a row..........................................................................................................................................50
Saving a row ................................................................................................................................................51
Updating a row ...........................................................................................................................................52
Removing a row ..........................................................................................................................................53
Table operation errors ................................................................................................................................54
Ranges...........................................................................................................................................................55
Row locking .................................................................................................................................................59
Multiuser processing ..................................................................................................................................59

Chapter 10: Building and Deploying ................................................................................ 65


Setting assembly information....................................................................................................................65
Specifying supported clients .....................................................................................................................66
Building an integration ..............................................................................................................................67
Deploying an integration...........................................................................................................................68

Chapter 11: Debugging ................................................................................................................. 69


Preparing to debug .....................................................................................................................................69
Examining the application.........................................................................................................................70
Disabling events ..........................................................................................................................................70

Chapter 12: Modified and Alternate Forms............................................................... 71


Modified forms............................................................................................................................................71
Alternate forms ...........................................................................................................................................72
Guidelines ....................................................................................................................................................73

Chapter 13: Implementing Macro Support ................................................................ 75


Overview of macro support ......................................................................................................................75
Recording macros .......................................................................................................................................75
Playing macros ............................................................................................................................................76
Handling asynchronous processes during playback.............................................................................78

Chapter 14: Using Lookups ...................................................................................................... 79


How lookups work .....................................................................................................................................79
Available lookups........................................................................................................................................80
Lookup example..........................................................................................................................................80

ii P R O G R A M M E R S G U I D E
C O N T E N T S

Chapter 15: Helper Functions ................................................................................................. 83


Helper function overview..........................................................................................................................83
Helper function reference ..........................................................................................................................83
DexAsk()...............................................................................................................................................85
DexDefaultsRead()..............................................................................................................................87
DexDefaultsWrite() .............................................................................................................................88
DexError() ............................................................................................................................................89
DexFileGetTempDirectory() ..............................................................................................................90
DexFileLaunch()..................................................................................................................................91
DexGetmsg() ........................................................................................................................................93
DexGetstring() .....................................................................................................................................95
DexPathGetForApp() .........................................................................................................................96
DexRuntimeGetClientType().............................................................................................................97
DexRuntimeGetWebClientTrustLevel()...........................................................................................99
DexUtilityLaunchUrl() .....................................................................................................................100
DexWarning() ....................................................................................................................................101
DexWinHelpLaunchUrl() ................................................................................................................102

Part 3: Web Client ........................................................................................................................ 106


Chapter 16: Web Client Overview ................................................................................... 107
Enabling integrations for the web client................................................................................................107
Form rendering in the web client ...........................................................................................................108
Code for the web client ............................................................................................................................108

Chapter 17: Dynamic Rendering ........................................................................................ 111


When to use dynamic rendering ............................................................................................................ 111
Enabling dynamic rendering................................................................................................................... 111
Supported properties and events ........................................................................................................... 112
Form and control reference...................................................................................................................... 112

Chapter 18: Custom Rendering .......................................................................................... 117


Implementing the custom messaging interface.................................................................................... 117
Requirements for developing with Silverlight .....................................................................................120
Silverlight project ......................................................................................................................................121
Adding a Silverlight window to the project .........................................................................................123
Sending messages .....................................................................................................................................124
Receiving messages ..................................................................................................................................126
Message examples ....................................................................................................................................126
Session recovery ........................................................................................................................................127
Message rejection ......................................................................................................................................129
Writing to the trace log.............................................................................................................................130
Building and deploying the Silverlight component ............................................................................131

Chapter 19: Developing for the Web Client ........................................................... 133


Determining where code is running ......................................................................................................133
Modal dialogs on the web client.............................................................................................................134
Closing forms on the web client .............................................................................................................134
Local file access .........................................................................................................................................134
Debugging with the web client...............................................................................................................135

PROGRAMMERS GUIDE iii


C O N T E N T S

Part 4: Resource Reference ............................................................................................ 138


Chapter 20: Forms ......................................................................................................................... 139
Accessing forms ........................................................................................................................................139
Form methods ...........................................................................................................................................139
Form properties.........................................................................................................................................141
Form events ...............................................................................................................................................142

Chapter 21: Windows .................................................................................................................. 143


Accessing windows ..................................................................................................................................143
Window methods......................................................................................................................................143
Window properties ...................................................................................................................................143
Window events..........................................................................................................................................144

Chapter 22: Scrolling Windows ......................................................................................... 149


Accessing scrolling windows ..................................................................................................................149
Scrolling window methods......................................................................................................................149
Scrolling window properties ...................................................................................................................149
Scrolling window events..........................................................................................................................149

Chapter 23: Window Fields .................................................................................................... 153


Accessing window fields .........................................................................................................................153
Window field methods.............................................................................................................................153
Window field properties ..........................................................................................................................155
Window field events.................................................................................................................................156

Chapter 24: Tables ......................................................................................................................... 157


Accessing tables ........................................................................................................................................157
Table methods............................................................................................................................................158
Table properties .........................................................................................................................................161

Chapter 25: Table Fields ........................................................................................................... 163


Accessing table fields ...............................................................................................................................163
Table field methods...................................................................................................................................163
Table field properties ................................................................................................................................164

Chapter 26: Commands ............................................................................................................ 165


Command types ........................................................................................................................................165
Accessing commands ...............................................................................................................................165
Command methods ..................................................................................................................................165

Chapter 27: Globals ...................................................................................................................... 167


Accessing globals ......................................................................................................................................167
Global properties.......................................................................................................................................167

Chapter 28: Procedures ............................................................................................................ 169


Accessing global procedures ...................................................................................................................169
Accessing form-level procedures............................................................................................................169
Procedure methods ...................................................................................................................................169
Procedure events.......................................................................................................................................170
Parameters for procedures.......................................................................................................................171

iv P R O G R A M M E R S G U I D E
C O N T E N T S

Invokable procedures ...............................................................................................................................172

Chapter 29: Functions ................................................................................................................ 173


Accessing global functions ......................................................................................................................173
Accessing form-level functions...............................................................................................................173
Function methods .....................................................................................................................................174
Function events .........................................................................................................................................174
Parameters for functions..........................................................................................................................175
Invokable functions ..................................................................................................................................176

Chapter 30: Composites ........................................................................................................... 177


Composite types........................................................................................................................................177
Accessing composites...............................................................................................................................177
Composite field methods.........................................................................................................................179
Composite field properties ......................................................................................................................181
Composite field events.............................................................................................................................182

Part 5: Integration Examples ........................................................................................ 184


Chapter 31: Field Defaulter ................................................................................................... 185
Overview....................................................................................................................................................185
Running the sample application.............................................................................................................185
How Visual Studio Tools was used ........................................................................................................186

Chapter 32: Estimate Freight............................................................................................... 187


Overview....................................................................................................................................................187
Running the sample application.............................................................................................................187
How Visual Studio Tools was used ........................................................................................................188

Chapter 33: Environmental Details ................................................................................ 191


Overview....................................................................................................................................................191
Running the sample application.............................................................................................................191
How Visual Studio Tools was used ........................................................................................................192

Chapter 34: Lookups ................................................................................................................... 195


Overview....................................................................................................................................................195
Running the sample application.............................................................................................................195
How Visual Studio Tools was used ........................................................................................................196

Chapter 35: Salesperson Analysis .................................................................................. 199


Overview....................................................................................................................................................199
Running the sample application.............................................................................................................199
How Visual Studio Tools was used ........................................................................................................202

Glossary ..................................................................................................................................................... 205

Index ............................................................................................................................................................... 207

PROGRAMMERS GUIDE v
vi P R O G R A M M E R S G U I D E
INTRODUCTION
Introduction
Welcome to Visual Studio Tools for Microsoft Dynamics GP. This documentation
explains how to integrate applications you create with Visual Studio into Microsoft
Dynamics GP. Before you begin creating an integration for Microsoft Dynamics GP,
take a few moments to review the information presented here.

Whats in this manual


The Visual Studio Tools for Microsoft Dynamics GP Programmers Guide is
designed to give you an in-depth understanding of how to use these tools to create
an application that integrates with Microsoft Dynamics GP. Even if you are familiar
with using Visual Studio to develop applications, you will find it helpful to browse
the material presented here.

Information is divided into the following parts:

Part 1, Getting Started, explains how to install Visual Studio Tools for
Microsoft Dynamics GP and begin creating an integration.

Part 2, Developing Integrations, provides detailed information about creating


WinForms that match the Microsoft Dynamics GP appearance. Interacting with
Microsoft Dynamics GP through events is discussed. Building, deploying, and
debugging integrations are also addressed.

Part 3, Web Client, explains how to make a Visual Studio Tools integration
work with the Microsoft Dynamics GP web client.

Part 4, Resource Reference, provides detailed information about interacting


with the various types of resources in Microsoft Dynamics GP.

Part 5, Integration Examples, describes example integrations that use Visual


Studio Tools for Microsoft Dynamics GP.

Whats new in this release of Visual Studio Tools


Refer to the following list for more information about the new features added for
this release of Visual Studio Tools for Microsoft Dynamics GP.

1. Web client support


Beginning with Microsoft Dynamics GP 2013 Service Pack 2, Visual Studio
Tools can be used to create user interface integrations. Refer to Part 3, Web
Client, for details about how to make integrations work with the web client.

2. Specifying supported clients


Beginning with Microsoft Dynamics GP 2013 Service Pack 2, an attribute can be
used to specify whether an integration can run on the desktop client, the web
client, or both client types. Refer to Specifying supported clients on page 66 for
information about adding this attribute.

3. Helper functions
Several functions have been added to the Dynamics dictionary for Microsoft
Dynamics GP 2013 Service Pack 2 to support Visual Studio Tools integration
scenarios, like the web client. Refer to Chapter 15, Helper Functions, for
details about these functions.

2 P R O G R A M M E R S G U I D E
IN T RO D U C T IO N

Prerequisites
You must be using Microsoft Dynamics GP 2013. Since you will be working with
Microsoft Dynamics GP, knowledge of the accounting system will be helpful.
Consult the Microsoft Dynamics GP documentation resources to learn more about
the product.

You will also want to install the SDK for Microsoft Dynamics GP. The SDK is
available in the Tools folder on the Microsoft Dynamics GP installation media. It
contains useful information about Microsoft Dynamics GP, such as lists of
commonly-used procedures and functions.

To use Visual Studio Tools for Microsoft Dynamics GP, Visual Studio 2010 or later
is required. Earlier versions of Visual Studio cannot be used. It is assumed that you
are familiar with programming in a managed language such as C#. This
documentation uses both C# and Visual Basic to demonstrate how to create
integrations.

Symbols and conventions


To help you use this documentation more effectively, weve used the following
symbols and conventions within the text to make specific types of information
stand out.

Symbol Description
The light bulb symbol indicates helpful tips, shortcuts,
and suggestions.

Warnings indicate situations you should be aware of


when completing tasks.

Margin notes summarize Margin notes call attention to critical information and
important information. direct you to other areas of the documentation where
a topic is explained.

Convention Description
Part 1, Getting Started Bold type indicates a part name.
Chapter 8, Events Quotation marks indicate a chapter name.
Adding controls Italicized type indicates a section name.
using System.IO; This font is used to indicate script examples.
Dictionary Assembly Acronyms are spelled out the first time theyre used.
Generator (DAG)
TAB or ALT+M Small capital letters indicate a key or a key sequence.

Product support
Microsoft Dynamics GP developer technical support can be accessed online or by
telephone. Go to www.microsoft.com/dynamics and click the CustomerSource or
PartnerSource link, or call 888-477-7877 (in the US and Canada) or 701-281-0555.

PROGRAMMERS GUIDE 3
4 P R O G R A M M E R S G U I D E
PART 1: GETTING STARTED
Part 1: Getting Started
This portion of the documentation describes how to get started creating an
integration using Visual Studio Tools for Microsoft Dynamics GP. The following
topics are discussed:

Chapter 1, SDK Installation, explains how to install Visual Studio Tools SDK
for Microsoft Dynamics GP.

Chapter 2, Integration Basics, describes the architecture of a Visual Studio


Tools for Microsoft Dynamics GP integration. It also explains how to create a
project for a new integration.

Chapter 3, Upgrading an Integration, explains how to upgrade an existing


integration to work with the current version of Visual Studio Tools for
Microsoft Dynamics GP.

6 P R O G R A M M E R S G U I D E
Chapter 1: SDK Installation
The Visual Studio Tools for Microsoft Dynamics GP SDK contains the components
needed to create and build integrations. The following topics are discussed:

Installation procedure
Template registration
What was installed
Upgrading to a newer Visual Studio

Installation procedure
The Visual Studio Tools for Microsoft Dynamics GP SDK installer requires Visual
Studio 2010 or later to be installed first. For testing integrations, you will also want
Microsoft Dynamics GP installed.

If you have installed an earlier version of the Visual Studio Tools SDK, be sure that you
remove it from the system before you install the new version.

To install the Visual Studio Tools for Microsoft Dynamics GP SDK, complete the
following procedure:

1. Start the Visual Studio Tools SDK installer.


Start the installer by running the VSToolsSDK.exe.

2. Acknowledge the license agreement.


Read and acknowledge the license agreement. Click Next to continue.

3. Specify the features to install.


Choose the features that will be installed:

Feature Description
Visual Studio 2010 Templates The C# and Visual Basic templates for projects and forms.
Visual Studio 2010 is required to install this feature.
Visual Studio 2012 Templates The C# and Visual Basic templates for projects and forms.
Visual Studio 2012 is required to install this feature.
Documentation The Visual Studio Tools for Microsoft Dynamics GP
Programmers Guide.
Samples Sample integrations that demonstrate Visual Studio
Tools.
Assemblies and Assembly The Dictionary Assembly Generator (Dag.exe) and the
Generator dictionary assemblies for the products that ship with
Microsoft Dynamics GP. Also includes the IntelliSense
XML files used by Visual Studio to display information
about the resources accessed through the application
assemblies.

4. Specify the installation location.


Use the default location, or choose another location. Click next to continue.

5. Begin the installation.


Click Install to begin installing the SDK components.

During the installation, Visual Studio must be reconfigured to recognize the new
templates being installed. This process may take a few minutes to complete.

PROGRAMMERS GUIDE 7
PA RT 1 G E TT I N G S T A R TE D

6. Finish the installation.


Click Finish to complete the installation.

Template registration
If you are running with limited user privileges or with User Account Control (UAC)
active, the templates installed for Visual Studio Tools may not be registered in
Visual Studio. You may need to manually register the templates so they will appear
as selections when you create new projects.

Use the following command for Visual Studio 2010 to re-create its template cache:

C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\devenv.exe /setup

If you are using a 64-bit version of Windows, the Visual Studio files will be located in the
Program Files (x86) folder.

On systems that are running with UAC (User Account Control), you will need to set
the properties of the devenv.exe application to be run with administrative
privileges.

On systems with UAC,


choose to run devenv.exe
as an administrator.

8 P R O G R A M M E R S G U I D E
C H A P T E R 1 S D K I N S T A L L A T I O N

What was installed


The following items are installed for Visual Studio Tools for Microsoft Dynamics
GP in the location you specified:

Component Description
VSTDGPReadme.rtf Contains late-breaking information about
Visual Studio Tools for Microsoft Dynamics
GP.
VSTDGPProgrammersGuide.pdf Documentation for Visual Studio Tools.
Samples.zip Sample Visual Studio projects that
demonstrate Visual Studio Tools.
Microsoft.Dexterity.Bridge.dll Core Microsoft Dynamics GP components
Microsoft.Dexterity.Shell.dll used by Visual Studio Tools integrations.
Microsoft.Dynamics.Framework.UI.Navigation.dll
Microsoft.Dynamics.Framework.UI.WinForms.
Controls.dll
Dag.exe The Dictionary Assembly Generator, used to
create application assemblies for application
dictionaries and forms dictionaries.
Bidi32.dll Support files needed for Dag.exe
Ddapi.dll
Tntlib.dll
Dex.dic
Dex.ini
Application Assemblies Assemblies that contain information about
the resources in each dictionary that is
shipped with Microsoft Dynamics GP. In
addition to US English, other local versions
of application assemblies are included.
IntelliSense XML files Used by Visual Studio to display information
about the corresponding application
assembly.

If you chose to install them, the project templates for C# and Visual Basic will be in
the appropriate locations for Visual Studio.

Upgrading to a newer Visual Studio


If you have previously installed the Visual Studio Tools for Microsoft Dynamics GP
SDK and want to upgrade to a newer version of Visual Studio, complete the
following procedure:

1. Install the new version of Visual Studio.


Install the new version of Visual Studio that you are moving to, such as Visual
Studio 2010.

2. Start the Visual Studio Tools SDK installer.


Start the installer by running the VSToolsSDK.exe. The updated components for
Visual Studio Tools will be installed.

3. Close the installer.


When the installer has finished updating components, click Finish.

4. Change the Visual Studio Tools installation.


In Programs and Features, choose Visual Studio Tools for Microsoft Dynamics
GP SDK. Click Change.

PROGRAMMERS GUIDE 9
PA RT 1 G E TT I N G S T A R TE D

5. Add a new feature.


Click Add/Remove Features to add a new feature to the Visual Studio Tools
installation.

6. Install the Visual Studio templates.


Mark the option to install the Visual Studio templates for the version of Visual
Studio that you are using, and then click Next. Click Install to begin the
installation process.

7. Finish the installation.


Click Finish to complete the installation.

10 P R O G R A M M E R S G U I D E
Chapter 2: Integration Basics
Before you create an integration using Visual Studio Tools for Microsoft Dynamics
GP, it will be helpful to understand the basics of an integration. The following
topics are discussed:

What Visual Studio Tools provides


Architecture
Creating a project

What Visual Studio Tools provides


Visual Studio Tools for Microsoft Dynamics GP provides three main capabilities for
an integrating application:

Customized WinForms
Any WinForms included in an integrating application can use capabilities provided
by Visual Studio Tools for Microsoft Dynamics GP to match the appearance of the
core application. The appearance of the window as well as the various controls in
the window can be customized. You will learn about creating windows for your
integration in Chapter 4, WinForms, and Chapter 5, Control Reference.

Access to dictionary resources


Integrating applications have access to the numerous resources available in the
application dictionaries used for Microsoft Dynamics GP. An integrating
application can access the forms, windows, window fields, tables, and table fields in
each dictionary. They can also access global variables, commands, procedures, and
functions defined in each dictionary. You will learn about accessing dictionary
resources in Chapter 7, Accessing Dictionary Resources.

Access to events
Integrating applications can be notified of events that occur in Microsoft Dynamics
GP, such as a window being opened, or the focus moving to a field. The applications
can respond to the events, performing actions like verifying field values or opening
additional windows. Chapter 8, Events, contains information about registering
for and responding to events.

Architecture
Visual Studio Tools for Microsoft Dynamics GP consists of runtime components
and development components.

Runtime components
The runtime components for Visual Studio Tools are installed with Microsoft
Dynamics GP, and provide the functionality used by the integrations. These consist
of the following:

Dexterity Shell This assembly (Microsoft.Dexterity.Shell.dll) provides the


drawing capabilities that allow an integrating application to match the appearance
of Microsoft Dynamics GP.

Dexterity Bridge This assembly (Microsoft.Dexterity.Bridge.dll) provides the


access to events in Microsoft Dynamics GP, as well as the resources in the
application dictionaries.

PROGRAMMERS GUIDE 11
PA RT 1 G E TT I N G S T A R TE D

Application assemblies Each dictionary that will be accessed by a Visual


Studio Tools for Microsoft Dynamics GP integration will have an application
assembly. Each application assembly provides access to the resources in its
corresponding dictionary. For example, the Application.Dynamics.dll assembly
provides access to the resources in the Dynamics.dic dictionary.

Visual Studio Tools for Microsoft Dynamics GP includes the application assemblies
for all the modules that ship with Microsoft Dynamics GP. You can use the
Dictionary Assembly Generator tool (Dag.exe) to create application assemblies for
other third-party dictionaries for Microsoft Dynamics GP. You will learn more
about this tool in Chapter 6, Dictionary Assembly Generator.

AddIns folder The assemblies for the integrating applications created with
Visual Studio Tools for Microsoft Dynamics GP are placed in this folder. When
Microsoft Dynamics GP is launched, it automatically looks in this folder and
attempts to launch the integrating applications it finds there.

Development components
The following development components are installed in the folder where you chose
to install Visual Studio Tools for Microsoft Dynamics GP:

DAG.exe This is the Dictionary Assembly Generator tool, used to create


application assemblies for dictionaries. You will use this to create application
assemblies for third-party dictionaries that do not have them. You will also use it to
create application assemblies for forms dictionaries in cases where your integration
must interact with modified forms in Microsoft Dynamics GP.

IntelliSense XML files The IntelliSense XML file contains the information
about the application assembly that is displayed in the IntelliSense within Visual
Studio. The name of the application XML file matches that of the application
assembly it corresponds to. For example, the Application.Dynamics.xml file
contains information about the Application.Dynamics.dll assembly.

The following components are installed into the Visual Studio installation:

Visual Basic project This is the template project for an add-in that is based in
Visual Basic.

Visual C# project This is the template project for an add-in that is based in
Visual C#.

Creating a project
Use the following procedure to create a new Visual Studio project for a Microsoft
Dynamics GP add-in.

1. Start Visual Studio.


If it isnt already running, start Visual Studio.

2. Create a new project.


In the File menu, point to New and choose Project.

3. Select the project type.


Choose either a Visual Basic project or a Visual C# project. Under the type you
have selected, choose Dynamics GP.

12 P R O G R A M M E R S G U I D E
C H A P T E R 2 I N T E G R A T I O N B AS I C S

4. Choose the Microsoft Dynamics GP Add-in template.


In the list of available templates, choose the Microsoft Dynamics GP Add-in
project template.

If the Microsoft Dynamics GP templates are not listed, you may need to register them
manually. Refer to Template registration on page 8 for details about doing this.

5. Specify the name and location of the project.


Click OK to create the project.

PROGRAMMERS GUIDE 13
14 P R O G R A M M E R S G U I D E
Chapter 3: Upgrading an Integration
If you have created an integration with Visual Studio Tools for an earlier release of
Microsoft Dynamics GP, use the following procedures to upgrade your integration
to work with the current version of Visual Studio Tools. Be sure you have installed
the current version of Visual Studio Tools before attempting to upgrade your
integrations. The following upgrade procedures are described:

Upgrading from Release 9


Upgrading from Release 10 or later

Upgrading from Release 9


If your integration was created with Release 9 of Visual Studio Tools, use the
following procedures to upgrade your integration to work with Visual Studio Tools
for Microsoft Dynamics GP 2013. Separate procedures are included for C# and
Visual Basic.

C# integration
Use the following procedure to upgrade a Visual Studio Tools integration created
with C#.

1. Open the solution for your integration.


Using Visual Studio, open the solution file for the integration you want to
upgrade.

2. Use the Visual Studio Conversion Wizard.


The Visual Studio project must be converted to work with the current version of
Visual Studio. Complete the steps in the Visual Studio Conversion Wizard to
convert the project.

3. Rebuild application assemblies.


If you had built any application assemblies for your integration, you will need
to re-build them so they are up-to-date with the latest version of Microsoft
Dynamics GP. Refer to Chapter 6, Dictionary Assembly Generator, for
information about generating application assemblies.

4. Set the version of the .NET framework to target.


Visual Studio Tools for Microsoft Dynamics GP 2013 integrations must target
.NET Framework 4 to build properly. To specify the target framework, display
the project properties. In the Application group, set the Target framework field
to .NET Framework 4. In the message displayed, click Yes indicate that you
want to make the change.

If you do not target the .NET Framework 4, you will see numerous build errors when
you build your project.

PROGRAMMERS GUIDE 15
PA RT 1 G E TT I N G S T A R TE D

5. Update the assembly references.


The assembly references for the project likely will be incorrect, because they
wont refer to the new versions of the Visual Studio Tools components and
application assemblies.

The assembly references


are incorrect and need to
be updated.

Add references to the updated Visual Studio Tools assemblies, to replace the
broken references.

The reference to the Microsoft.Dexterity.Shell.UI assembly is a special situation. This


component was merged into the Microsoft.Dexterity.Shell assembly. Create a reference
to the Microsoft.Dexterity.Shell assembly, and delete the reference to the
Microsoft.Dexterity.Shell.UI assembly.

6. Update the namespaces used in integration code.


The namespace for the shell (user interface) components of the Visual Studio
Tools integration has changed. The namespace reference must be changed from:

Microsoft.Dexterity.Shell.UI

To the updated value:

Microsoft.Dexterity.Shell

7. Update the namespace references used for any forms.


The same namespace change must be made for any forms you created for your
integration. When you attempt to open a form in the Visual Studio designer,
you will see an error similar to the following:

16 P R O G R A M M E R S G U I D E
C H A P T E R 3 U P G R A D I N G A N I N TE G R A T I O N

This means that the code used for the form is using the old namespace, rather
than the new Microsoft.Dexterity.Shell namespace. You must view the code for
the form, and change all of the namespace references to remove the UI
portion. This will be required in several places. An example of code to be fixed
is shown highlighted in the following illustration.

You may need to expand some hidden sections of the code to find all of the references.

After making these changes to the forms code, save the updated file. Close the
form designer if it is still open, and then re-open the form. The form should now
open and have the updated Microsoft Dynamics GP appearance.

8. Build the solution.


Choose to build the updated solution in Visual Studio. You may encounter
build errors if your integration references resources in Microsoft Dynamics GP
that have been deleted, moved, or renamed. You will need to fix these issues
and rebuild the integration.

Visual Basic integration


Use the following procedure to upgrade a Visual Studio Tools integration created
with Visual Basic.

1. Open the solution for your integration.


Using Visual Studio, open the solution file for the integration you want to
upgrade.

2. Use the Visual Studio Conversion Wizard.


The Visual Studio project must be converted to work with the current version of
Visual Studio. Complete the steps in the Visual Studio Conversion Wizard to
convert the project.

3. Rebuild application assemblies.


If you had built any application assemblies for your integration, you will need
to re-build them so they are up-to-date with the latest version of Microsoft
Dynamics GP. Refer to Chapter 6, Dictionary Assembly Generator, for
information about generating application assemblies.

4. Set the version of the .NET framework to target.


Visual Studio Tools for Microsoft Dynamics GP 2013 integrations must target
.NET Framework 4 to build properly. To specify the target framework, display
the project properties. In the Compile group, click Advanced Compile Options.
Set the Target framework (all configurations) field to .NET Framework 4, and
then click OK. In the message displayed, click Yes to indicate that you want to
make the change.

PROGRAMMERS GUIDE 17
PA RT 1 G E TT I N G S T A R TE D

If you do not target the .NET Framework 4, you will see numerous build errors when
you build your project.

5. Update the assembly references.


The assembly references for the project will be incorrect, because they wont
refer to the new versions of the Visual Studio Tools components and application
assemblies.

The assembly references


are incorrect and need to
be updated.

Add references to the updated Visual Studio Tools assemblies, to replace the
broken references.

The reference to the Microsoft.Dexterity.Shell.UI assembly is a special situation. This


component was merged into the Microsoft.Dexterity.Shell assembly. Create a reference
to the Microsoft.Dexterity.Shell assembly, and delete the reference to the
Microsoft.Dexterity.Shell.UI assembly.

6. Update the namespaces used in integration code.


The namespace for the shell (user interface) components of the Visual Studio
Tools integration has changed. Any namespace reference must be changed
from:

Microsoft.Dexterity.Shell.UI

To the updated value:

Microsoft.Dexterity.Shell

18 P R O G R A M M E R S G U I D E
C H A P T E R 3 U P G R A D I N G A N I N TE G R A T I O N

7. Update the namespace references used for any forms.


The same namespace change must be made for any forms you created for your
integration. When you attempt to open a form in the Visual Studio designer,
you will see an error that prevents the form from being displayed. View the
code for the form:

Fix the namespace


references for the form.

8. Update the form designer code.


Open the Designer source file for the form to fix the references so they use the
new Microsoft.Dexterity.Shell namespace. Change all of the namespace
references to remove the UI portion. This will be required in several places.
An example of code to be fixed is shown in the following illustration.

Fix all of the references


to use the new
Microsoft.Dexterity.Shell
namespace.

After making these changes to the forms code, save the updated file. Re-open
the form. The form should appear in the form designer and have the updated
Microsoft Dynamics GP appearance.

9. Build the solution.


Choose to build the updated solution in Visual Studio. You may encounter
build errors if your integration references resources in Microsoft Dynamics GP
that have been deleted, moved, or renamed. You will need to fix these issues
and rebuild the integration.

PROGRAMMERS GUIDE 19
PA RT 1 G E TT I N G S T A R TE D

Upgrading from Release 10 or later


If your integration was created with Release 10 or later of Visual Studio Tools, use
the following procedures to upgrade your integration to work with Visual Studio
Tools for Microsoft Dynamics GP 2013. The upgrade procedure is relatively simple.
The same procedure can be used for both C# and Visual Basic.

1. Open the solution for your integration.


Using Visual Studio, open the solution file for the integration you want to
upgrade.

2. Use the Visual Studio Conversion Wizard (if required).


If the Visual Studio project must be converted to work with the current version
of Visual Studio, the Visual Studio Conversion Wizard will be displayed.
Complete the steps in the wizard to convert the project.

3. Rebuild application assemblies.


If you had built any application assemblies for your integration, you will need
to re-build them so they are up-to-date with the latest version of Microsoft
Dynamics GP. Refer to Chapter 6, Dictionary Assembly Generator, for
information about generating application assemblies.

4. Set the version of the .NET framework to target.


Visual Studio Tools for Microsoft Dynamics GP 2013 integrations must target
.NET Framework 4 to build properly. To specify the target framework, do the
following:

For a C# project, display the project properties. In the Application group,


set the Target framework field to .NET Framework 4. In the message
displayed, click Yes indicate that you want to make the change.

For a Visual Basic project, display the project properties. In the Compile
group, click Advanced Compile Options. Set the Target framework (all
configurations) field to .NET Framework 4, and then click OK. In the
message displayed, click Yes to indicate that you want to make the change.

If you do not target the .NET Framework 4, you will see numerous build errors when
you build your project.

5. Update the assembly references if necessary.


The assembly references for the project may be incorrect, because they may not
be referencing the new versions of the Visual Studio Tools components and
application assemblies.

20 P R O G R A M M E R S G U I D E
C H A P T E R 3 U P G R A D I N G A N I N TE G R A T I O N

If any of the references are not valid, remove and then re-add references to the
updated Visual Studio Tools assemblies to replace the incorrect references.

6. Build the solution.


Choose to build the updated solution in Visual Studio. You may encounter
build errors if your integration references resources in Microsoft Dynamics GP
that have been deleted, moved, or renamed. You will need to fix these issues
and rebuild the integration.

PROGRAMMERS GUIDE 21
22 P R O G R A M M E R S G U I D E
PART 2: DEVELOPING INTEGRATIONS
Part 2: Developing Integrations
This portion of the documentation describes the various techniques you will use as
you develop integrations using Visual Studio Tools for Microsoft Dynamics GP.
The following topics are discussed:

Chapter 4, WinForms, describes how to create WinForms that have the


appearance of windows in Microsoft Dynamics GP.

Chapter 5, Control Reference, provides details of the various controls that are
modified by Visual Studio Tools for Microsoft Dynamics GP.

Chapter 6, Dictionary Assembly Generator, describes the tool used to create


.NET assemblies that provide access to dictionary resources.

Chapter 7, Accessing Dictionary Resources, explains how to access resources


in dictionaries from your integrating application.

Chapter 8, Events, describes how to register for and respond to events for
Microsoft Dynamics GP.

Chapter 9, Working with Tables, describes how to directly access Microsoft


Dynamics GP tables from an integration.

Chapter 10, Building and Deploying, explains how to build and deploy an
integration you have created.

Chapter 11, Debugging, explains how to debug an integration created with


Visual Studio Tools for Microsoft Dynamics GP.

Chapter 12, Modified and Alternate Forms, describes how to access resources
on modified forms and alternate forms in Microsoft Dynamics GP.

Chapter 13, Implementing Macro Support, explains how to make forms


created with Visual Studio Tools accessible by the macro system in Microsoft
Dynamics GP.

Chapter 14, Using Lookups, describes how to use existing lookups from
Microsoft Dynamics GP in your Visual Studio Tools integration.

Chapter 15, Helper Functions, provides information about functions added to


the Dynamics dictionary that perform useful actions for Visual Studio Tools
integrations.

24 P R O G R A M M E R S G U I D E
Chapter 4: WinForms
Standard WinForms are the basis for the user interface for add-ins created with
Visual Studio Tools for Microsoft Dynamics GP. These WinForms and the controls
placed on them are specially modified to match the appearance of Microsoft
Dynamics GP. Information about WinForms is divided into the following sections:

Adding a Dynamics GP form to a project


WinForm properties
Adding controls

Adding a Dynamics GP form to a project


To add a new Dynamics GP form to an add-in project, complete the following
procedure:

1. Add a new component.


In Visual Studio, choose Add Component from the Project menu.

2. Select a Microsoft Dynamics GP Form.


In the list of templates, choose a Microsoft Dynamics GP form.

Choose a Microsoft
Dynamics GP Form.

3. Name the new form.


Give the form a name that is appropriate for how it will be used.

4. Add the new form.


Click Add to add the new WinForm to the project.

5. Specify the form properties.


Set the necessary properties for the new form.

PROGRAMMERS GUIDE 25
PA RT 2 D E V E L O PI N G I N TE G R A T I O N S

WinForm properties
WinForms that are added to a Visual Studio Tools for Microsoft Dynamics GP
project have several additional properties that control their appearance. Setting
these properties correctly helps match the appearance of Microsoft Dynamics GP.
These properties are:

AutoSetDexColors
ControlArea
StatusArea

These WinForm properties are found in the Dexterity group in the Properties pane in
Visual Studio.

AutoSetDexColors
The AutoSetDexColors property controls whether the colors used for the WinForm
will automatically match the color scheme selected in the user preferences within
Microsoft Dynamics GP. Set this property to True to match the Microsoft Dynamics
GP appearance.

ControlArea
The ControlArea property specifies whether the band called the control area is
drawn at the top of the WinForm. In standard Microsoft Dynamics GP windows,
controls such as Save, Clear, and Delete buttons are placed in the control area. Set
this property to True to display the control area for a WinForm.

This is the control area.

StatusArea
The StatusArea property specifies whether the band called the status area is drawn
at the bottom of the WinForm. A divider line is drawn across the bottom of the
WinForm to indicate the status area. In standard Microsoft Dynamics GP windows,
controls like browse buttons, note buttons, and help buttons are placed in the status
area. Set this property to True to display the status area for a WinForm.

This is the status area.

26 P R O G R A M M E R S G U I D E
C H A P T E R 4 W I N F O R M S

Adding controls
You can add controls to the forms for your Microsoft Dynamics GP integration the
same way you add them to standard windows forms. Simply select the control in
the Toolbox and drag it out onto the form.

To add a control, just


select it in the Toolbox
and drag it onto the form.

When you add the controls, additional properties will be available for some of them
to match the Microsoft Dynamics GP appearance. For example, push buttons will
have additional properties. Refer to Chapter 5, Control Reference, for more
information about individual controls.

PROGRAMMERS GUIDE 27
28 P R O G R A M M E R S G U I D E
Chapter 5: Control Reference
You can use any of the available controls on the WinForms for your Microsoft
Dynamics GP integration. Some of the standard controls have been customized to
better match the appearance of Microsoft Dynamics GP. This portion of the
documentation describes the controls that have additional properties or updated
characteristics when used on a WinForm in a Visual Studio Tools for Microsoft
Dynamics GP project. The following controls are discussed:

Buttons
TextBoxes
Labels
ComboBoxes
ListBoxes

Buttons
Button controls are used for each of the button types in a Microsoft Dynamics GP
form. The button controls on a WinForm for a Microsoft Dynamics GP project get
their additional characteristics from the dexButtonProvider you see on the
WinForm layout. The ButtonType property is an additional property available for
each button. It specifies how the button control is displayed and what
characteristics it will have. You can set the AutoSetDexColors property to True so
the button colors will match colors in Microsoft Dynamics GP.

The following is a list of the settings for the ButtonType property, and a description
of how each button type is used.

Standard
Standard buttons dont have their appearance modified changed when placed on a
WinForm for a Dynamics GP project. The following illustration shows a standard
button.

This is a standard button

Toolbar
Buttons with the ButtonType set to Toolbar are typically placed in the control area
of a Microsoft Dynamics GP form. These buttons have a flat appearance, with a
special color highlighting when the pointer is placed over them. It is also common
for these buttons to have pictures on them. The following illustration shows a
toolbar button.

A toolbar button is
typically placed in the
control area.

PROGRAMMERS GUIDE 29
PA RT 2 D E V E L O PI N G I N TE G R A T I O N S

ToolbarWithSeparator
The buttons with the type ToolbarWithSeparator buttons are typically placed in the
control area, like buttons with the type Toolbar. However, they have an additional
separator line drawn on the right side of the button to separate it from the other
controls in the control area. The following illustration shows two buttons that have
the type ToolbarWithSeparator. Notice the separator line drawn to the right of each
button.

These are toolbar buttons


with separators.

StatusArea
Buttons placed in the status area at the bottom of a window should have the type
StatusArea. These buttons should display only graphics, and will have a special 3-D
border drawn around them when the pointer is placed over them. These buttons
should have the Tooltip property set so they will display a description of the action
the button performs. A status area button is shown in the following illustration. It
displays a tooltip that describes the purpose of the button.

Buttons in the status area


typically have only pictures.

Field
Buttons that show only pictures, and are placed next to other controls in the form
should have the ButtonType property set to Field. These buttons are used for things
like lookups or expansions. Several buttons with this type are shown next to a text
control in the following illustration.

These are field


buttons.

Pictures for buttons


Each Visual Studio for Microsoft Dynamics GP project includes several standard
images that are used for buttons in Microsoft Dynamics GP. These images (in PNG
format) should be used with the buttons you create for your integrations. The
following table lists the images and describes how they are used.

Image Name Description


Field_Delete.png Used for delete buttons in the window area placed
next to fields.
Field_Edit.png Used for edit buttons in the window area placed next
to fields.
Field_Expansion.png Used for expansion buttons in the window area
placed next to fields.
Field_Lookup.png Used for lookup buttons in the window area placed
next to fields.
Field_MapPoint.png Used for MapPoint buttons in the window area placed
next to fields.

30 P R O G R A M M E R S G U I D E
C H A P T E R 5 C O N T R O L R E F E R E N C E

Image Name Description


Field_NoteAbsent.png Used for note buttons in the window area placed next
to fields.
Field_NotePresent.png Used for note buttons in the window area placed next
to fields.
HelpImage.png Used for the Help button placed in the status area of
the window.
Toolbar_Cancel.png Used for the Cancel button placed in the window
control area.
Toolbar_Clear.png Used for the Clear button placed in the window
control area.
Toolbar_Copy.png Used for the Copy button placed in the window
control area.
Toolbar_Delete.png Used for the Delete button placed in the window
control area.
Toolbar_DeleteAll.png Used for the Delete All button placed in the window
control area.
Toolbar_New.png Used for the New button placed in the window control
area.
Toolbar_Open.png Used for the Open button placed in the window
control area.
Toolbar_Post.png Used for the Post button placed in the window control
area.
Toolbar_Print.png Used for the Print button placed in the window control
area.
Toolbar_Redisplay.png Used for the Redisplay button placed in the window
control area.
Toolbar_Save.png Used for the Save button placed in the window
control area.
Toolbar_Void.png Used for the Void button placed in the window control
area.
VCR_First.png Used for the First browse control in the window status
area.
VCR_Last.png Used for the Last browse control in the window status
area.
VCR_Next.png Used for the Next browse control in the window
status area.
VCR_Previous.png Used for the Previous browse control in the window
status area.
Window_NoteAbsent.png Used for the note button in the window status area.

Window_NotePresent.png Used for the note button in the window status area.

TextBoxes
TextBox controls are used for the string, integer, currency, date, and time controls in
a Microsoft Dynamics GP form. Text boxes have the AutoSetDexColors property
that can be set to True so the control colors will match colors in Microsoft Dynamics
GP.

A TextBox control is used


for standard fields like
currency values.

PROGRAMMERS GUIDE 31
PA RT 2 D E V E L O PI N G I N TE G R A T I O N S

Unlike the standard controls in Microsoft Dynamics GP, the textbox controls have
no built-in support to format data such as currency values. You will need to add
additional code to your integration to match the behavior of the controls in
Microsoft Dynamics GP. For instance, the following C# code sets the value of the
textbox in the previous illustration. It uses the Format method for the String object
to format the currency value.

// Display the value, formatting it as a currency amount


textBoxEstimatedFreight.Text = String.Format("{0:C}",EstimatedFreight);

Labels
Label controls are used for the text labels that appear next to controls in the
Microsoft Dynamics GP form. They correspond to the static text items that appear
in standard Microsoft Dynamics GP windows.

A label control displays


the text label that appears
next to another control.

Label controls have the LinkField property that should be set when a specific field
is being labeled. This property is set to the name of the control that the label applies
to. When specified in the Microsoft Dynamics GP User Preferences, the label will be
drawn with the single underline that is standard for prompts.

To have the underlined label draw correctly, be sure the AutoSize property for the label is
set to False.

ComboBoxes
Use the ComboBox control in cases where you would use a drop-down list or
combo box in Microsoft Dynamics GP. ComboBox controls have the
AutoSetDexColors property that can be set to True so the control colors will match
colors in Microsoft Dynamics GP.

The following illustration shows a ComboBox control being used as a drop-down


list in a Microsoft Dynamics GP form.

ListBoxes
Use the ListBox control in cases where you would used a list box or multi-select list
box in Microsoft Dynamics GP.

32 P R O G R A M M E R S G U I D E
Chapter 6: Dictionary Assembly Generator
The Dictionary Assembly Generator (DAG.exe) is a utility included with Visual
Studio Tools for Microsoft Dynamics GP that creates a managed code assembly that
provides access to resources in an application dictionary. Information about this
tool is divided into the following sections:

Creating application assemblies


Output files
Using the Dictionary Assembly Generator
Optimizing the assembly generating process

Creating application assemblies


Several application assemblies are included with the Visual Studio Tools for
Microsoft Dynamics GP. These are the assemblies for the core application
(Dynamics.dic) and the other applications that are delivered with Microsoft
Dynamics GP.

When developing integrations that use resources from these dictionaries, always
use the application assemblies that are included with the Visual Studio Tools
installation. These assemblies are digitally signed, indicating they were produced
by Microsoft. Dont generate your own versions of application assemblies for
dictionaries shipped with the Microsoft Dynamics GP product.

You will create application assemblies for the following cases:

A forms dictionary exists for a product, and you want your Microsoft Dynamics
GP integration to access the modified resources in the forms dictionary.

You have installed a third-party dictionary for which no application assembly


exists, and you want to access resources in this dictionary from your Microsoft
Dynamics GP integration. The third-party dictionary could contain new forms
and other resources. It could contain alternate forms from the Dynamics.dic
dictionary.

Output files
The Dictionary Assembly Generator produces two output files that are used in your
integration: an application assembly and IntelliSense data file.

Application assembly
The most important output is the application assembly. This is the managed code
assembly that provides access to the resources in a dictionary. Each dictionary can
have one corresponding application assembly.

The following naming convention is used for application dictionaries:

Application.ProductName.dll

The following naming convention is used for forms dictionaries:

Application.ProductName.ModifiedForms.dll

ProductName is automatically derived from product name in the launch file. Any
spaces or special characters in the product name are removed.

PROGRAMMERS GUIDE 33
PA RT 2 D E V E L O PI N G I N TE G R A T I O N S

For example, the application assembly that provides access to resources in the
SRVCADV.dic application dictionary is named Application.FieldService.dll. The
application assembly that provides access to the resources in the forms dictionary
(FRMS949.dic) is named Application.FieldService.ModifiedForms.dll.

IntelliSense data file


The second type of output from the Dictionary Assembly Generator is the
IntelliSense data file that will be used by Visual Studio. This file has the same name
as its corresponding application assembly, but has the .xml extension. As you write
code, Visual Studio will use the information from this file to display details about
the resources that can be accessed through the application assembly. An example of
the IntelliSense for a dictionary resource is shown in the following illustration.

Information from the


application assembly
XML file is displayed in
IntelliSense.

Using the Dictionary Assembly Generator


The Dictionary Assembly Generator (DAG.exe) is installed in the location where
you installed Visual Studio Tools. Typically this will be the following location:

C:\Program Files\Microsoft Dynamics\GP2013 VS Tools SDK

If you are using a 64-bit version of Windows, the files will be located in the Program Files
(x86) folder.

The Dictionary Assembly Generator is a command-line tool, and should be run


from a command prompt. Open a command prompt and set the current location to
the folder where DAG.exe is located.

To view the command syntax, use the following command at the command prompt:

dag.exe /?

The Dictionary Assembly Generator uses the product ID to identify the dictionary
for which you want to build the application assembly. Look in the launch file
(typically Dynamics.set) for a list of the products installed.

34 P R O G R A M M E R S G U I D E
C H A P T E R 6 D I C T I O N A R Y A S S EM B L Y G E N ER AT O R

Optionally, you can specify the launch file that the Dictionary Assembly Generator
will look in to find the list of installed products and the corresponding dictionary
locations. If you dont supply the name of the launch file, DAG.exe will look for the
launch file named Dynamics.set in the current location.

Since you are running DAG.exe from a different location than where Microsoft Dynamics
GP is installed, you will need to supply the complete path to the launch file.

The Dictionary Assembly Generator must be able to write to the location where it is being
run from. This means the user running DAG.exe must be part of the Administrators group
or the Power Users group. On a system running with User Account Control (UAC), it
means launching DAG.exe with Administrative privileges.

Building an application assembly


The Dictionary Assembly Generator will build an application assembly for the main
dictionary for an application or for the forms dictionary for an application. When
generating an assembly for an application dictionary, use the /M parameter. For
example, the following command generates the application assembly for the main
dictionary of the Sample Integrating Application. This application has the product
ID value 3333. The path to the launch file (Dynamics.set) is supplied.
dag.exe 3333 "C:\Program Files\Microsoft Dynamics\GP\Dynamics.set" /M

This command produces two files:

Application.SampleIntegratingApp.dll
Application.SampleIntegratingApp.xml

To generate an assembly for a forms dictionary, use the /F parameter. For example,
the following command generates the application assembly for the forms dictionary
of the Field Service product (with dictionary ID 949).
dag.exe 949 "C:\Program Files\Microsoft Dynamics\GP\Dynamics.set" /F

This command produces two files:

Application.FieldService.ModifiedForms.dll
Application.FieldService.ModifiedForms.xml

Refer to Modified forms on page 71 for details about creating an application assembly for the
forms dictionary (Forms.dic) used by Microsoft Dynamics GP.

Signing an application assembly


You may want to sign the application assemblies you create. This is a good practice,
because it helps ensure that only the official version of an application assembly is
being used. The Dictionary Assembly Generator can sign the assemblies that it
creates. It can fully sign the assemblies, or delay sign them. You can use the SN.exe
utility (included with the .NET Framework) to create a strong name key file (.snk)
used to sign the assembly.

After you create and use a strong name key file, keep it in a safe location. You will need to
use it every time you build or rebuild application assemblies.

The following example shows how the application assembly for the sample
integrating application is fully signed using the Sample.snk strong name key. The
Sample.snk file was generated using the SN.exe utility.
dag.exe 3333 "C:\Program Files\Microsoft Dynamics\GP\Dynamics.set" /M
/S:Sample.snk

PROGRAMMERS GUIDE 35
PA RT 2 D E V E L O PI N G I N TE G R A T I O N S

Overriding the application assembly name


When creating an application assembly for a dictionary, the Dictionary Assembly
Generator will use the product name from the launch file. This may not be the name
you want to use for the application assembly. You can use the /N parameter to
specify a different name for the application assembly being generated.

For example, the following command will create an application assembly for the
sample integrating application, but use the name Develop instead of the product
name in the launch file.

dag.exe 3333 "C:\Program Files\Microsoft Dynamics\GP\Dynamics.set" /M


/N:Develop

The generated application assembly will have the name Application.Develop.dll.

Overriding the main referenced dictionary name


When generating application assemblies for dictionaries that integrate with
Microsoft Dynamics GP, the Dictionary Assembly Generator must be able to
reference the application assembly for the main dictionary (typically
Application.Dynamics.dll). If the application assembly for the main dictionary has
been given a different name, you can use the /NM parameter to specify which new
name so the application assembly can be found.

For example, if the application assembly for the main dictionary was named
Application.DynamicsGP.dll, you would use the following command to create an
application assembly for the sample integrating application. Notice that the /NM
parameter is used to specify the name of the main application assembly that is being
referenced.

dag.exe 3333 "C:\Program Files\Microsoft Dynamics\GP\Dynamics.set" /M


/NM:DynamicsGP

Optimizing the assembly generating process


Producing an application assembly for large dictionaries is a resource-intensive
process. The Dictionary Assembly Generator will use a large amount of memory
(often over 1 gigabyte) and substantial processor time when producing an
application assembly. To optimize the process, do the following:

Use the best hardware you have available to generate the application assembly.

Close all other applications before starting the process.

Temporarily turn off background processing tasks, such as virus scanning.

36 P R O G R A M M E R S G U I D E
Chapter 7: Accessing Dictionary Resources
To create an integration for Microsoft Dynamics GP or the additional applications
that are installed with it, your code must access resources in the various application
dictionaries. This portion of the documentation describes how to do this for your
project. The following topics are discussed:

Adding references
Namespace
Dictionary class
Accessing additional resources
Variables for dictionary resources

Adding references
To access the resources in a specific dictionary, a project must contain a reference to
the application assembly for that dictionary. When you create a new Visual Studio
Tools for Microsoft Dynamics GP project, it will automatically contain a reference to
the Application.Dynamics.dll application assembly. This provides access to
resources in the Dynamics.dic dictionary. To access resources in other dictionaries,
add references to the application assemblies for them.

If a dictionary doesnt have a corresponding application assembly, refer to Chapter 6,


Dictionary Assembly Generator, to learn how to create one.

For example, to access resources from the Sample Integrating App application
installed with Microsoft Dynamics GP, the project should contain a reference to the
Application.SampleIntegratingApp.dll application assembly. The following
illustration shows this reference for a C# project.

This reference provides


access to the resources in
the corresponding
dictionary.

PROGRAMMERS GUIDE 37
PA RT 2 D E V E L O PI N G I N TE G R A T I O N S

Namespace
Resources for a dictionary are accessed through the following namespace:

Microsoft.Dexterity.Applications

To make it convenient to access resources, this namespace is included in the C#


project template with the using statement. In the Visual Basic project template, its
included using the Imports statement. Referencing the namespace prevents you
from having to fully-qualify references to dictionary resources.

Dictionary class
The resources in a dictionary are accessed through a single class that is available
after you add the reference to the dictionarys application assembly. The class has
the same name that appears in the application assembly. For instance, the class to
access resources for the Dynamics dictionary is named Dynamics. Similarly, the
class used to access resources for the Sample Integrating Application is named
SampleIntegratingApp. This is the same name that appears in the application
assembly, Application.SampleIntegratingApp.dll.

The five primary resource types in a dictionary are accessed through properties of
the class. These resource types are:

Forms
Globals
Procedures
Functions
Tables

To access a resource of the specific type, start by typing the dictionary class name,
and then property for the resource type. IntelliSense in Visual Studio will present a
list of the specific type of resources available in the dictionary. For example, the
following illustration shows the forms resources in the Dynamics core application.

Type the dictionary class name


and the resource type
property. IntelliSense displays
a list of resources.

When youve selected a resource of the specific type, you will see a list of the
properties, methods, and events available for that resource. The following
illustration shows some of the properties, methods, and events for the AboutBox
form in the Dynamics dictionary.

38 P R O G R A M M E R S G U I D E
C H A P T E R 7 A C C E S S I N G D I C T I O N A R Y R ES O U R C E S

Accessing additional resources


Several additional resource types are accessed through the Forms property of a
dictionary class. These include:

Windows
Commands
Form-level procedures
Form-level functions
Form-level table buffers

As an example, the following C# statement opens the Customer Maintenance


window. Notice how the window is accessed through the form object.

Dynamics.Forms.RmCustomerMaintenance.RmCustomerMaintenance.Open();

Windows provide further access to two additional resource types:

Fields
Scrolling windows

For instance, the following C# statement sets the value of the Comment 1 field in the
Vendor Maintenance window.

Dynamics.Forms.PmVendorMaintenance.PmVendorMaintenance.Comment1.Value
= "A preferred vendor";

You will learn more about the details about using each resource type in Part 4, Resource
Reference.

Variables for dictionary resources


Within your code, it may be useful to create variables for specific resources in an
application dictionary. The definitions for the various dictionary resources are
found in an additional namespace available in the application assembly. This
namespace has the same name that appears in the application assembly, but has
Dictionary appended. For instance, to reference the definitions for resources in
the Dynamics main dictionary, you would use this namespace:

Microsoft.Dexterity.Applications.DynamicsDictionary

To reference resources for the Sample Integrating Application, you would use this
namespace:

Microsoft.Dexterity.Applications.SampleIntegratingAppDictionary;

After creating the variable, you can assign its value and then use it in your code. For
example, the following C# code creates a variable for the Vendor Maintenance form
in Microsoft Dynamics GP. It assigns the form to the variable, and then uses it to
open the form.

PmVendorMaintenanceForm VendorMaintenanceForm;

VendorMaintenanceForm = Dynamics.Forms.PmVendorMaintenance;
VendorMaintenanceForm.Open();

PROGRAMMERS GUIDE 39
PA RT 2 D E V E L O PI N G I N TE G R A T I O N S

Using a variable can simplify your code, especially when accessing dictionary
resources that have long names. For example, the following C# code creates a
variable for the Customer Maintenance window in Microsoft Dynamics GP. Then it
sets the values of two fields in the window. Notice it take less code to set the field
when the variable for the window is used.

// Create the variable and set its value


RmCustomerMaintenanceForm.RmCustomerMaintenanceWindow CustMaintWindow;
CustMaintWindow = Dynamics.Forms.RmCustomerMaintenance.RmCustomerMaintenance;

// Accessing window fields requires less code when using the variable
CustMaintWindow.Comment1.Value = "Comment 1";

Dynamics.Forms.RmCustomerMaintenance.RmCustomerMaintenance.Comment2.Value =
"Comment 2";

40 P R O G R A M M E R S G U I D E
Chapter 8: Events
Applications that integrate with Microsoft Dynamics GP often need to be notified
when specific events occur in the system. This portion of the documentation
describes how to register to be notified when events occur in the system. It also
describes how to write event handlers that can respond to the events. Information is
divided into the following sections:

Registering events
Responding to events
Unregistering events

Registering events
Your integrating application must register every event that it should be notified of
in the system. Event registrations are added to the Initialize() method, located in
the template code that is automatically added when you created your Visual Studio
Tools for Microsoft Dynamics GP project.

The resources for which you can register events, such as forms, windows, or fields,
each list the events they make available. For example, a form has the following
events available:

OpenBeforeOriginal
OpenAfterOriginal
CloseBeforeOriginal
CloseAfterOriginal

Refer to each resource type described in Part 4, Resource Reference, for the list of
events that are available for that resource.

To register an event, find the resource for which you want to register the event. Pick
the event you want, and then specify the event handler method. The event handler
is the method that contains the code that runs in response to the event.

C#
Visual Studio will assist you when you register an event in C# code. Begin by
referencing the resource for which you want to register an event. Add the +=
operator, and Visual Studio will display IntelliSense indicating it will complete the
event handler. Simply press the TAB key to add the event handler registration.

PROGRAMMERS GUIDE 41
PA RT 2 D E V E L O PI N G I N TE G R A T I O N S

After the event handler registration is added, Visual Studio will offer to add the
event handler method for the new event. Press the TAB key again to add the event
handler method. When youre finished, the completed event will look similar to the
following:

public void Initialize()


{
Dynamics.Forms.RmCustomerMaintenance.OpenAfterOriginal += new
EventHandler(RmCustomerMaintenance_OpenAfterOriginal);
}

void RmCustomerMaintenance_OpenAfterOriginal(object sender, EventArgs e)


{
throw new Exception("The method or operation is not implemented.");
}

Visual Basic
Registering an event in a Visual Basic project requires two steps. First, in the
Initialize() method of the project, the AddHandler statement registers the event.
The AddHandler statement takes two parameters. The first specifies the resource
and event, while the second specifies the event handler method that will be run. The
following example registers the AfterOpen event for the Customer Maintenance
form in Microsoft Dynamics GP.

Sub Initialize() Implements IDexterityAddIn.Initialize

AddHandler Dynamics.Forms.RmCustomerMaintenance.OpenAfterOriginal, _
AddressOf RMCustMaintAfterOpen

End Sub

In the second step, the event handler method is added. The parameters for this
method must match those required by the event. The IntelliSense for the event
displays the parameters the event handler must have.

The parameters required


for the event handler
method are displayed.

The following example shows the event handler method added for the event
created in the previous example.

Public Sub RMCustMaintAfterOpen(ByVal sender As Object, ByVal e _


As System.EventArgs)

MsgBox("Not Implemented")

End Sub

42 P R O G R A M M E R S G U I D E
C H A P T E R 8 E V E N T S

Responding to events
The event handler method contains the code that runs in response to the event. This
code can perform whatever action is required for your integrating application. For
example, the following C# code is the event handler that runs in response to the
value of the Sales Document Number field being changed in the Sales Transaction
Entry window. If the EstimateFreight form is open, the controls on the form are set.
void SopNumber_Change(object sender, EventArgs e)
{
// If the Estimate Freight form is open, update the document number
// and clear the other controls so the new calculation can be performed.
if (EstimateFreightForm.Created == true)
{
EstimateFreightForm.textBoxDocumentNumber.Text =
SOPEntryWindow.SopNumber.Value;
EstimateFreightForm.textBoxEstimatedFreight.Clear();
EstimateFreightForm.textBoxTotalWeight.Clear();
}
}

Event arguments
The event arguments for some events provide additional information about the
event. The event arguments for procedure events and function events allow access
to the parameters for the procedure or function call. For instance, the following C#
example is the event handler for InvokeAfterOriginal event for the
GetAutoComplete function in Microsoft Dynamics GP. The event arguments
contain the parameters that were passed into the function. The event handler
examines the value of the first parameter to verify that its value is DYNSA. If it is,
the code sets the result of the function to false.
void GetAutoComplete_InvokeAfterOriginal(object sender,
SyUserDefaultsForm.GetAutoCompleteFunction.InvokeEventArgs e)
{
// Set the return value to always turn off auto-complete for DYNSA user
if (e.inParam1 == "DYNSA")
{
e.result = false;
}
}

The event arguments for modal dialog events allow access to the buttons and
message displayed in the modal dialog. For example, the following Visual Basic
code is the event handler for the BeforeModalDialog event of the Sales Transaction
Entry window. It shows how the event arguments are used to examine the message
text displayed by the modal dialog, and then used to respond to the dialog.
Private Sub SopEntryWindow_BeforeModalDialog(ByVal sender As Object, ByVal e
As BeforeModalDialogEventArgs)

' Examine the dialog to determine whether it is the one to respond do


If e.DialogType = DialogType.Ask Then
If e.Message.Contains("want to add a customer") Then
' Click the Customer button in the modal dialog
e.Response = DialogResponse.Button1
End If
End If
End Sub

PROGRAMMERS GUIDE 43
PA RT 2 D E V E L O PI N G I N TE G R A T I O N S

Cancelling events
Some events can be cancelled through the event handler. Typically, these are events
that occur before the event in the core application, such as the OpenBeforeOriginal
event for a form. The event argument parameter that is passed to the event handler
for these events has a special type that allows the event to be cancelled.

For example, the following Visual Basic example is the event handler for the
BeforeOpen event of the Customer Maintenance form. The event handler method
examines the current user logged into the system. If its the sa user, a message is
displayed and the window isnt opened. Notice how the event arguments are used
to cancel the event.

Public Sub RMCustMaintBeforeOpen(ByVal sender As Object, ByVal e _


As System.ComponentModel.CancelEventArgs)

If Dynamics.Globals.UserId.Value = "sa" Then

'Display the message


MsgBox("Do not access this window as the Administrator")

'Prevent the form from opening


Dynamics.Forms.RmCustomerMaintenance.Close()

'Cancel pending events


e.Cancel = True

End If
End Sub

Unregistering events
At some point after you have registered an event, the event may no longer be
needed. To unregister an event, use the standard syntax for either C# or Visual
Basic. You can unregister the following types of events:

Procedure events
Function events
Modal dialog events

The other types of events cannot be unregistered. If you try to unregister them, an exception
will be thrown.

C#
The following C# example shows how you would unregister an AfterModalDialog
event. The method named IvItemMaintenance_AfterModalDialog had been
registered as the event handler for the modal dialog event.

ItemMaintenanceForm.IvItemMaintenance.AfterModalDialog -= new
EventHandler<AfterModalDialogEventArgs>(IvItemMaintenance_AfterModalDialog);

44 P R O G R A M M E R S G U I D E
C H A P T E R 8 E V E N T S

Visual Basic
The following Visual Basic example shows how you would unregister the
InvokeAfterOriginal event for the AddSuccessfulLoginRecord procedure. The
method named AddSuccessfulLogin had been registered as the event handler for
the procedure event.

RemoveHandler Dynamics.Procedures.AddSuccessfulLoginRecord.InvokeAfterOriginal, _
AddressOf AddSuccessfulLogin

PROGRAMMERS GUIDE 45
46 P R O G R A M M E R S G U I D E
Chapter 9: Working with Tables
A Visual Studio Tools integration can interact directly with tables defined in
Microsoft Dynamics GP. Using the table integration capability is much simpler than
creating and managing external connections to the Microsoft Dynamics GP
database. Information about working with tables is divided into the following
sections:

Tables in Microsoft Dynamics GP


Table buffers
Opening and closing tables
Keys
Retrieving a row
Saving a row
Updating a row
Removing a row
Table operation errors
Ranges
Row locking
Multiuser processing

Tables in Microsoft Dynamics GP


To learn about tables in Microsoft Dynamics GP, you will need to access
information from the following sources.

Resource Descriptions tool


The Resource Descriptions tool available in Microsoft Dynamics GP provides
essential details about each table in the application. Information such as the fields in
the table and the keys defined for the table can be found here.

Important details, such as the


keys defined for the table,
can be found in the Table
Descriptions window.

PROGRAMMERS GUIDE 47
PA RT 2 D E V E L O PI N G I N TE G R A T I O N S

Microsoft Dynamics GP SDK


The Microsoft Dynamics GP SDK contains detailed diagrams and descriptions of
the tables in Microsoft Dynamics GP. You can use these diagrams to learn about the
table in a specific module, and how the tables work together. Information about
how transactions flow through the various tables is also available in the Microsoft
Dynamics GP SDK.

IntelliSense
The IntelliSense available in Visual Studio will be helpful by listing what tables are
available, as well as which fields are available in those tables.

IntelliSense lists which


tables are available. A
description of each table
is also provided.

Table buffers
A table buffer provides access to one row of a specific table. The information in the
table buffer comes from either the table or a script that has run. Your code will
interact with the table buffer when you perform operations on the table. There are
two types of table buffers: global and form-level.

A global table buffer is created when a table is accessed directly through the global list
of tables. Global table buffers are accessed through the dictionary class. This class
has a Tables property that provides access to the collection of tables defined in the
dictionary. A global table buffer is not associated with any specific form. This
makes global table buffers useful in situations where a Visual Studio Tools
integration must read from or write to a Dynamics GP table, but isnt interacting
with the user interface.

Dynamics GP Global Visual Studio Tools


Table Table Buffer Application Code

By default, a global table buffer for a table is shared with all of the other Visual
Studio Tools add-ins that are accessing that same table. If you want your integration
to create a global table buffer that is not shared, use the Clone() method when
creating the instance of the global table buffer.

A form-level table buffer is created when a table is attached to a form in Microsoft


Dynamics GP. There is one table buffer for each table that is attached to the form.
Each form-level table buffer is shared by the code that is part of the form, as well as
any code outside of the form that accesses the table through that form. The Tables
property for the form allows access to the table buffers for the tables that are
attached to the form. Because they are shared, form-level table buffers arent
typically used by Visual Studio Tools integrations to directly read from or write to
tables. Instead, the form-level table buffers are examined to find what data the
Dynamics GP window has read or is writing to the specific table.

48 P R O G R A M M E R S G U I D E
C H A P T E R 9 W O R K IN G W IT H T A B LE S

Form

Dynamics GP
Window

Visual Studio Tools Form-level


Application Code Table Buffers

Dynamics GP Tables

Opening and closing tables


There is no explicit open operation for a table in Visual Studio Tools. The first
time a table buffer is accessed, the table is automatically opened. The table buffer
remains open until it is closed.

When your integrating applications code has finished working with a global table
buffer, it must be closed using the Close() method for the table. Failing to close a
global table buffer will cause a Background process is running: Exit Aborted error
when the user attempts to exit Microsoft Dynamics GP.

The user will see this error


when global table buffers are
left open in a Visual Studio
Tools integration.

For form-level table buffers, the table buffer will be closed when the form is closed.
Explicitly closing a form-level table buffer with the Close() method is needed rarely.

The following C# example shows how a table is accessed through a global table
buffer. The first row of the table (the RM Customer Master table) is retrieved, and
the customer number is displayed. Notice how the table buffer is closed at the end
of the example.
RmCustomerMstrTable CustomerMasterTable;
CustomerMasterTable = Dynamics.Tables.RmCustomerMstr;

// Read the first row of the table


CustomerMasterTable.GetFirst();

// Display the name for the row retrieved


MessageBox.Show(CustomerMasterTable.CustomerName.Value);

// Close the table buffer


CustomerMasterTable.Close();

PROGRAMMERS GUIDE 49
PA RT 2 D E V E L O PI N G I N TE G R A T I O N S

Keys
A key is a field or combination of fields in a table that is used to sort and locate
specific rows in the table. Typically, the value of the key field or fields is unique for
each row in a table so a specific row can be located. Keys that dont uniquely
identify a specific row are used to refer to a range of rows in the table.

The keys for a table are identified by number, beginning with the value 1. When
you specify the key you want to use for a table, you will supply the corresponding
integer. The Table Descriptions window in Microsoft Dynamics GP lists the keys for
each table, and the key segments (fields) that each key contains.

The keys for the table are


listed in numeric order.

The fields in each key are


listed here.

You will use the keys for a table when you retrieve a specific row from the table.
This is described in the next section, Retrieving a row. You will also use keys when
you want to perform operations on a range of rows in the table. You will learn more
about this in Ranges on page 55.

Retrieving a row
Retrieving a row from a table is a multi-step process. First, you must decide which
key you want to use to retrieve the row. Use the Table Descriptions window in
Microsoft Dynamics GP to view the keys and each keys components. Specify the
key to use, and then set the values of the key fields. Finally, use the Get() or
Change() method for the table to retrieve the record. Which you use depends on
whether you want to lock the record. You will learn more about locking in Row
locking on page 59.

The following C# example retrieves the row for the customer American Electrical
Contractor from the RM_Customer_MSTR table. The second key of the
RM_Customer_MSTR table is used. This key contains one component, the
Customer Name. The contact person for the retrieved customer is displayed in a
dialog.

// Variable for any table operation error


TableError err;

// Create a reference to the table


RmCustomerMstrTable CustomerMasterTable;
CustomerMasterTable = Dynamics.Tables.RmCustomerMstr;

// Set the key to use for the table


// Key 2 - Contains the Customer Name
CustomerMasterTable.Key = 2;

// Set the value for the key columns


CustomerMasterTable.CustomerName.Value = "American Electrical Contractor";

50 P R O G R A M M E R S G U I D E
C H A P T E R 9 W O R K IN G W IT H T A B LE S

// Retrieve the row


err = CustomerMasterTable.Get();

if (err == TableError.NoError)
{
MessageBox.Show(CustomerMasterTable.ContactPerson.Value);
}
else
{
// Display the error that occurred
MessageBox.Show(err.ToString());
}
// Close the table
CustomerMasterTable.Close();

Saving a row
To save a new row in a table, set the fields in the table to the values you want to
save. Then use the Save() method to save the new row in the table. The following
C# example adds a new row to the GL_Account_Category_MSTR table. It sets the
values for the fields in the table, then saves the new row.

// Variable for any table operation error


TableError err;

// Create a reference to the table


GlAccountCategoryMstrTable CategoryMasterTable;
CategoryMasterTable = Dynamics.Tables.GlAccountCategoryMstr;

// Set the fields in the table


CategoryMasterTable.AccountCategoryNumber.Value = (short)49;
CategoryMasterTable.AccountCategoryDescription.Value = "Profit Sharing";

// Save the new row


err = CategoryMasterTable.Save();

if(err == TableError.Duplicate)
{
MessageBox.Show("Account category already exists");
}

// Close the table


CategoryMasterTable.Close();

PROGRAMMERS GUIDE 51
PA RT 2 D E V E L O PI N G I N TE G R A T I O N S

Updating a row
To update a row in a table, first read the row with the Change() method. This
retrieves the row and locks it, allowing you to make changes. Set the values of the
fields you want to change for the row. Finally, use the Save() method to save the
changed row back to the table.

The following C# example reads the row for Adam Park Resort. The Contact Person
for this row is changed the Steve K. Then the row is saved back to the
RM_Customer_MSTR table.

// Variable for any table operation error


TableError err;

// Create a reference to the table


RmCustomerMstrTable CustomerMasterTable;
CustomerMasterTable = Dynamics.Tables.RmCustomerMstr;

// Set the key to use for the table


// Key 1 - Contains the Customer Number
CustomerMasterTable.Key = 1;

// Set the key field in the table


CustomerMasterTable.CustomerNumber.Value = "ADAMPARK0001";

// Attempt to read the row. The Change() method will lock the row.
err = CustomerMasterTable.Change();

if (err == TableError.NoError)
{
// The row was read successfully, so update the value
CustomerMasterTable.ContactPerson.Value = "Steve K.";

// Save the updated row


err = CustomerMasterTable.Save();

if (err != TableError.NoError)
{
MessageBox.Show("An error occurred updating the row: " +
err.ToString());
}
}
else
{
MessageBox.Show("An error occurred retrieving the row to update: " +
err.ToString());
}

// Close the table


CustomerMasterTable.Close();

52 P R O G R A M M E R S G U I D E
C H A P T E R 9 W O R K IN G W IT H T A B LE S

Removing a row
To remove a row from a table, first read the row with the Change() method. This
retrieves the row and locks it. Then use the Remove() statement to remove the row
from the table.

The following C# example reads and locks the row for the inventory item
WIRE100 in the IV_Item_MSTR table. If the item is successfully read, it is
removed from the table.

// Variable for any table operation error


TableError err;

// Create a reference to the table


IvItemMstrTable ItemMasterTable;
ItemMasterTable = Dynamics.Tables.IvItemMstr;

// Set the key to use for the table


// Key 1 - Contains the Item Number
ItemMasterTable.Key = 1;

// Set the key field in the table


ItemMasterTable.ItemNumber.Value = "WIRE100";

// Attempt to read the row. The Change() method will lock the row.
err = ItemMasterTable.Change();

if (err == TableError.NoError)
{
// Attempt to remove the row
err = ItemMasterTable.Remove();

if (err != TableError.NoError)
{
MessageBox.Show("An error occured removing the row: " +
err.ToString());
}
}

// Close the table


ItemMasterTable.Close();

PROGRAMMERS GUIDE 53
PA RT 2 D E V E L O PI N G I N TE G R A T I O N S

Table operation errors


An error code is returned from each of the table operations that can be performed.
The possible error codes are contained in the TableError enumeration. Many of the
errors included in the enumeration will not occur in the released versions of
Microsoft Dynamics GP. The following table describes the error values that your
Visual Studio Tools integration is likely to encounter:

Constant Description
Changed The row being saved was changed by another user.
DatabasePermissionViolation The current user does not have security privileges to access
the table.
DoubleLock A row was already locked in the table buffer.
Duplicate The row being saved already exists in the table.
EndOfTable The row cannot be retrieved because the beginning or end of
the table has been reached.
InvalidKeyNumber The table does not have a key with the number specified.
NoError No error occurred.
NoLock An operation such as Remove() was performed, but no row
had been locked.
NotFound The row was not found in the table.
NotSupported The table operation is not supported for the table. For
example, attempting to actively lock a row on a table that
doesnt allow it.
Sharing The row is actively locked by another user.
TooManyOpenTables Too many tables are open in the application.
Unknown An unknown error occurred.

Typically, your code will do one or both of the following after each table operation:

Check for the NoError value, indicating the table operation was successful. If
the operation was successful, the next processing step can continue.

Check for a specific error, such as NotFound. The code must respond
appropriately, such as displaying a message for the user.

If an unexpected error occurs after performing a table operation, its always a good
idea to display the details of the error to the user. Include information such as the
table, the operation being performed, and the error that occurred.

When a table operation error occurs, your code wont follow the typical code path. Be sure
that your code closes any tables it has accessed. Otherwise, the user wont be able to exit
Microsoft Dynamics GP.

54 P R O G R A M M E R S G U I D E
C H A P T E R 9 W O R K IN G W IT H T A B LE S

Ranges
When working with tables, it is often efficient to limit the amount of information
being accessed. You can do this by setting up a range for the table. A range is based
on a key for the table, and allows you to access a specified portion of the rows in the
table. The selected range will be treated as an entire table. For instance, calling the
GetFirst() method returns the first row in the range. Calling the GetLast() method
returns the last row in the range, and so on.

You use the RangeStart() and RangeEnd() methods to specify the range for a table.
You can specify one range per table, and the range is associated with a specific key.
The range will be used only when the table is accessed using the key the range is
associated with. To clear the range specified for a table, use the RangeClear()
method.

Example 1 - Range with simple key


In the following C# example, a range is used to limit the rows accessed to only those
customers whose names begin with A. Notice that the second key for the table,
composed of the Customer Name field, is used for the RangeStart() and
RangeEnd() methods. The first and last rows in the range are displayed.

// Variable for any table operation error


TableError err;

// Create a reference to the table


RmCustomerMstrTable CustomerMasterTable;
CustomerMasterTable = Dynamics.Tables.RmCustomerMstr;

// Set the key to use for the table


// Key 2 - Contains the Customer Name
CustomerMasterTable.Key = 2;

// Specify the start of the range


CustomerMasterTable.Clear();
CustomerMasterTable.CustomerName.Value = "A";
CustomerMasterTable.RangeStart();

// Specify the end of the range


CustomerMasterTable.Clear();
CustomerMasterTable.CustomerName.Value = "B";
CustomerMasterTable.RangeEnd();

// Display the first item in the range


err = CustomerMasterTable.GetFirst();

if (err == TableError.NoError)
{
MessageBox.Show("First customer: " +
CustomerMasterTable.CustomerName.Value);
}
else
{
MessageBox.Show("An error occured retrieving the row: " +
err.ToString());
}

PROGRAMMERS GUIDE 55
PA RT 2 D E V E L O PI N G I N TE G R A T I O N S

// Display the last item in the range


err = CustomerMasterTable.GetLast();

if (err == TableError.NoError)
{
MessageBox.Show("Last customer: " +
CustomerMasterTable.CustomerName.Value);
}
else
{
MessageBox.Show("An error occured retrieving the row: " +
err.ToString());
}

// Close the table


CustomerMasterTable.Close();

Example 2 - Range with multi-segment key


If a key is composed of several segments, you can create ranges based on serveral
key segments. Its important that all segments of the key be set when specifying the
start and end of the range. The Clear() and Fill() methods are often used when
creating a range based on a multi-segment key. They are used to set all of the fields
in the table buffer to the empty value or the filled value. This ensures that all of the
key segments have been specified before the RangeStart() or RangeEnd() methods
are called.

For example, the following C# code creates a range for the IV_Item_MSTR table that
includes only items in the COMPONENTS class. The range is created using key 3
for the Item Master table. This key has two segments: Item Class Code and Item
Number.

To set the beginning of the range, the Clear() method is used to set the fields in the
IV_Item_MSTR table buffer to the minimum value. The Item Class Code field in the
table buffer is set to COMPONENTS. The RangeStart() method specified this is
the beginning of the range.

To set the end of the range, the Fill() method is used to set the fields in the
IV_Item_MSTR table buffer to the maximum value. The Item Class Code field in the
table buffer is set to COMPONENTS. The RangeEnd() method specifies this is the
end of the range.

The key values for the range are shown in the following illustration. The range will
include rows where the Item Class Code value is COMPONENT and the Item
Number can be any value.

Item Class Code Item Number

Range Start COMPONENT (Cleared)

Range End COMPONENT (Filled)

56 P R O G R A M M E R S G U I D E
C H A P T E R 9 W O R K IN G W IT H T A B LE S

// Variable for any table operation error


TableError err;

// Create a reference to the table


IvItemMstrTable ItemMasterTable;
ItemMasterTable = Dynamics.Tables.IvItemMstr;

// Set the key to use for the table


// Key 3 - Contains the Item Class Code and the Item Number
ItemMasterTable.Key = 3;

// Specify the start of the range


ItemMasterTable.Clear();
ItemMasterTable.ItemClassCode.Value = "COMPONENTS";
ItemMasterTable.RangeStart();

// Specify the end of the range


ItemMasterTable.Fill();
ItemMasterTable.ItemClassCode.Value = "COMPONENTS";
ItemMasterTable.RangeEnd();

// Read through the items in the range


StringBuilder itemList = new StringBuilder();

err = ItemMasterTable.GetFirst();

while(err == TableError.NoError)
{
// Add the item to the list
itemList.AppendLine(ItemMasterTable.ItemNumber + " " +
ItemMasterTable.ItemDescription);

// Get the next item in the range


err = ItemMasterTable.GetNext();
}

// Display the list of items


MessageBox.Show(itemList.ToString());

// Close the table


ItemMasterTable.Close();

Example 3 - Removing rows in a range


Once a range is created for a table, you can use the RangeRemove() method to
remove all of the rows in that range from the table. In many cases, this will be faster
than removing individual rows using the Remove() method.

The following C# example deletes all customer information for St. Patricks
Hospital. A single row must be deleted from the RM_Customer_MSTR and the
RM_Customer_MSTR_SUM tables. Several rows must be deleted from the
RM_Customer_MSTR_ADDR table. A range is used to remove the rows from this
table.

// Variable for any table operation error


TableError err;

PROGRAMMERS GUIDE 57
PA RT 2 D E V E L O PI N G I N TE G R A T I O N S

// Create references to the tables


RmCustomerMstrTable CustomerMasterTable;
CustomerMasterTable = Dynamics.Tables.RmCustomerMstr;

RmCustomerMstrSumTable CustomerMasterSummaryTable;
CustomerMasterSummaryTable = Dynamics.Tables.RmCustomerMstrSum;

RmCustomerMstrAddrTable CustomerMasterAddressTable;
CustomerMasterAddressTable = Dynamics.Tables.RmCustomerMstrAddr;

// Delete the row from the Customer Master Summary table


CustomerMasterSummaryTable.Key = 1;
CustomerMasterSummaryTable.CustomerNumber.Value = "STPATRIC0001";
err = CustomerMasterSummaryTable.Change();
if (err == TableError.NoError)
{
err = CustomerMasterSummaryTable.Remove();
}

// Close the table


CustomerMasterSummaryTable.Close();

// Delete the row from the Customer Master table


CustomerMasterTable.Key = 1;
CustomerMasterTable.CustomerNumber.Value = "STPATRIC0001";
err = CustomerMasterTable.Change();
if (err == TableError.NoError)
{
err = CustomerMasterTable.Remove();
}

// Close the table


CustomerMasterTable.Close();

// Delete the rows from the Customer Master Address table


// Key 1 has two segments (Customer Number and Address Code)
CustomerMasterAddressTable.Key = 1;

// Specify the start of the range


CustomerMasterAddressTable.Clear();
CustomerMasterAddressTable.CustomerNumber.Value = "STPATRIC0001";
CustomerMasterAddressTable.RangeStart();

// Specify the end of the range


CustomerMasterAddressTable.Fill();
CustomerMasterAddressTable.CustomerNumber.Value = "STPATRIC0001";
CustomerMasterAddressTable.RangeEnd();

// Remove the rows from the range


CustomerMasterAddressTable.RangeRemove();

// Close the table


CustomerMasterAddressTable.Close();

58 P R O G R A M M E R S G U I D E
C H A P T E R 9 W O R K IN G W IT H T A B LE S

Row locking
A row must be locked to delete it or save any changes made to it. A lock is applied
when a row is read from a table. Two types of locked can be used: passive and
active.

Passive locking
A passive lock allows other users to access the row. They can delete the row or make
changes to it. Passive locking ensures that other users accessing the row can be
made aware that the row has been deleted or that the contents of the row have
changed. A pasive lock is applied every time a row is read using the Change()
method.

The Get() method is used only to read a row. It never locks the row.

Active locking
An active lock allows other users to read the row, but not make any changes or delete
the row. Active locking ensures that the user who has the active lock is the only user
who can make changes or delete the row. If other users try to delete or change the
row, they will receive a sharing error. An ative lock is applied each time a row is
read using the Change() method and the activeLock parameter for the method is set
to true.

Not all tables in Microsoft Dynamics GP allow active locking. If you try to actively lock a
row on a table that doesnt support it, a NotSupported error will be returned.

Releasing locks
Any of the following actions release a row lock:

Using the Release() method.

Using the Save() method or the Remove() method, regardless of whether the
method was successful.

If a row is currently locked in a table buffer, and you attempt to lock another row,
you will receive an DoubleLock error that indicates a row was already locked.

Multiuser processing
Microsoft Dynamics GP supports multiple users accessing the same table at the
same time. This is accomplished through Optimistic Concurrency Control (OCC), a
form of record locking that allows multiple users to work in the same tables and
access the same rows with minimal restrictions, while helping to ensure data
integrity.

To allow multiple users to successfully use Microsoft Dynamics GP while Visual


Studio Tools integrations are accessing data, you must choose the type of locking
used. You must also handle any error conditions that occur as a result of multiple
users working with the same row in a table.

PROGRAMMERS GUIDE 59
PA RT 2 D E V E L O PI N G I N TE G R A T I O N S

The following table lists the various locking scenarios that can occur. The events
listed happen in order from left to right. For example, in the first row User A
passively locks a row, then User B passively locks the same row. User A deletes the
row, then User B changes the contents of the row and saves the row. The changes
User B made will be saved.

User A User B User A User B Result


1 Passively locks a Passively locks Deletes the row. Changes the The changes User B made will be
row. the same row. contents of the row saved.
and saves the
changes.
2 Passively locks a Passively locks Changes the Deletes the row. The row will be deleted.
row. the same row. contents of the row
and saves the row.
3 Passively locks a Passively locks Changes a field Changes a Both changes will be saved.
row. the same row. and saves the row. different field and
saves the row.
4 Passively locks a Passively locks Changes a field Changes the same User B will get an error indicating
row. the same row. and saves the row. field and attempts the row changed. User Bs changes
to save the row. wont be saved.
5 Passively locks a Passively locks Deletes the row. Attempts to delete User B will get an error indicating
row. the same row. the row. the row is missing.
6 Actively locks a Passively locks Keeps the active Attempts to delete User B will get a row locked error.
row. the same row. lock. the row or change The row wont be deleted or the
a field and save the changes wont be saved.
row.
7 Actively locks a Passively locks Deletes the row. Changes the row If user B changed the row and
row. the same row. The active lock is and saves it or saved, the changes will be saved.
released. deletes the row. If User B attempts to delete the row,
User B will get an error indicating
the row is missing.
8 Actively locks a Passively locks Makes changes Changes the row If User B changed the same field as
row. the same row. and saves the row. and saves it or User A, User B will get an error
The active lock is deletes the row. indicating the row changed. User
released. Bs changes wont be saved.
If user B changed different fields,
the changes will be saved.
If User B deleted the row, the row
will be deleted.
9 Passively locks a Actively locks the Attempts to delete Keeps the active User A will get a row locked error,
row. same row. the row or change lock. even though User Bs active lock
a field and save the came later than User As lock.
row.
10 Actively locks a Attempts to User B will get a row locked error.
row. actively lock the
same row.

Scenarios 1 through 3 dont produce any errors. To be multiuser compatible, your


application should be able to handle scenarios 4 to 10, alerting users that an error
occurred, and allowing them to respond appropriately.

Use the error value returned from the various table operations like Save() or
Remove() to trap errors so your code can deal with the errors that occur. The
following examples show how to trap for multiuser errors when reading, saving
and removing records.

You should not check for multiuser error conditions on tables containing text fields. Text
fields are those that store text up to 32,000 characters long. Multiuser error codes are not
properly returned for tables containing text fields.

60 P R O G R A M M E R S G U I D E
C H A P T E R 9 W O R K IN G W IT H T A B LE S

Example 1
The following C# example reads and actively locks the first row in the
RM_Sales_WORK table. It uses the value returned from the ChangeFirst() method
to handle the Sharing error resulting from the row being actively locked by another
user.
// Variable for any table operation error
TableError err;

// Create references to the tables


RmSalesWorkTable SalesWorkTable;
SalesWorkTable = Dynamics.Tables.RmSalesWork;

// Release any existing lock


SalesWorkTable.Release();

// Retrieve the first row and actively lock it


err = SalesWorkTable.ChangeFirst(true);
if (err == TableError.Sharing)
{
// The row is actively locked by another user
MessageBox.Show("This row is currently locked by another user.");
}

// Close the table


SalesWorkTable.Close();

Example 2
The following C# example reads the first row of the RM_Customer_MSTR table,
changes the Salesperson ID, and attempts to save the changed row. The return
value from the Save() method is used to handle an error resulting from the row
being changed or actively locked by another user.
// Variable for any table operation error
TableError err;

// Create reference to the table


RmCustomerMstrTable CustomerMasterTable;
CustomerMasterTable = Dynamics.Tables.RmCustomerMstr;

// Release any existing lock


CustomerMasterTable.Release();

// Read the first row in the table


err = CustomerMasterTable.ChangeFirst();

// Change the Salesperson ID


CustomerMasterTable.SalespersonId.Value = "STEVE K.";

// Save the changed row


err = CustomerMasterTable.Save();

// Handle any errors


if (err == TableError.Changed)
{
// The row was changed by another user.
MessageBox.Show("This row has been changed by another user. Their changes
will be overridden.");

PROGRAMMERS GUIDE 61
PA RT 2 D E V E L O PI N G I N TE G R A T I O N S

// Re-read the current row to lock it


CustomerMasterTable.Change();

// Re-write the value


CustomerMasterTable.SalespersonId.Value = "STEVE K.";

// Attempt the save again


err = CustomerMasterTable.Save();

if (err != TableError.NoError)
{
MessageBox.Show("Customer could not be updated.");
}
}
else if (err == TableError.Sharing)
{
MessageBox.Show("This row is actively locked by another user. Changes will
not be saved.");
}
else if (err != TableError.NoError)
{
// Some other table error occurred
MessageBox.Show("An error occured updating the customer: " +
err.ToString());
}

// Close the table


CustomerMasterTable.Close();

Example 3
The following script reads the last row in the GL_Account_Category_MSTR table
and attempts to delete it. The error value returned from the Remove() method is
used to handle an error resulting from the row being actively locked or already
deleted by another user.

// Variable for any table operation error


TableError err;

// Create reference to the table


GlAccountCategoryMstrTable AccountCategoryMasterTable;
AccountCategoryMasterTable = Dynamics.Tables.GlAccountCategoryMstr;

// Release any lock on the row


AccountCategoryMasterTable.Release();

// Retrieve the last row


err = AccountCategoryMasterTable.ChangeLast();

if (err == TableError.NoError)
{
// Row was read and can be removed
err = AccountCategoryMasterTable.Remove();

if (err == TableError.Sharing)
{

62 P R O G R A M M E R S G U I D E
C H A P T E R 9 W O R K IN G W IT H T A B LE S

// The row is actively locked


MessageBox.Show("This row is actively locked by another user.
It cannot be removed.");
}
else if (err == TableError.NotFound)
{
// The row was removed by another user
MessageBox.Show("This row was removed by another user.");
}
else if (err != TableError.NoError)
{
// Some other table error occurred
MessageBox.Show("An error occured removing the row: " +
err.ToString());
}
}
else
{
// Some other table error occurred
MessageBox.Show("An error occured retrieving the row: " +
err.ToString());
}

// Close the table


AccountCategoryMasterTable.Close();

PROGRAMMERS GUIDE 63
64 P R O G R A M M E R S G U I D E
Chapter 10: Building and Deploying
This portion of the documentation describes how to build and deploy an integration
created with Visual Studio Tools for Microsoft Dynamics GP. Information is
divided into the following sections:

Setting assembly information


Specifying supported clients
Building an integration
Deploying an integration

Setting assembly information


Its important to set the assembly information so the assembly you build for your
Visual Studio Tools for Microsoft Dynamics GP integration is properly identified
and versioned. Be sure you set the following items:

Title
Description
Company
Major, minor, and build numbers

C# application
For integrations written in C#, the assembly information is set in the
AssemblyInfo.cs source file for the project. The following portion of this file shows
the various name values that should be set.

// General Information about an assembly is controlled through the following


// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Estimate Freight")]
[assembly: AssemblyDescription("Estimate Freight Sample Integration")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Microsoft")]
[assembly: AssemblyProduct("EstimateFreight")]
[assembly: AssemblyCopyright("Copyright Microsoft 2012")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

The following portion of this file shows the version, build, and revision numbers
that should be set.

// Version information for an assembly consists of the following four values:


//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all values or default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

PROGRAMMERS GUIDE 65
PA RT 2 D E V E L O PI N G I N TE G R A T I O N S

Visual Basic application


For integrations written in Visual Basic, the assembly information is set in the
Assembly Information window. Access this window. To view this windows, choose
to display the properties for the Visual Basic project. Click the Application tab, and
then click the Assembly Information button.

Specifying supported clients


By default, an integration created with Visual Studio Tools will operate in the
Microsoft Dynamics GP desktop client. The integration will not operate in the
Microsoft Dynamics GP web client by default, because often some additional work
must be done to support the web client.

As part of developing your integration, you should specify which client types are
supported by the integration. The Microsoft Dynamics GP runtime will use this
information to determine whether or not to load the integration when Microsoft
Dynamics GP is started. There are two ways to specify the client types supported:
using an attribute in the code and using the Dynamics.exe.config file.

Using an attribute
The preferred way of specifying which client types are supported is to add the
SupportedDexPlatforms attribute to the class that implements the IDexterityAddIn
interface. The SupportedDexPlatforms attribute takes one parameter that indicates
with platform or platforms are supported by the integration. When Microsoft
Dynamics GP is started, the DLLs in the AddIns folder are examined for this
attribute. Each add-in is loaded based on the attribute setting.

In the following C# example, the logical-or operation is used to indicate that both
the desktop client and the web client are supported.
namespace CSharpSample
{
[SupportedDexPlatforms(DexPlatforms.DesktopClient |
DexPlatforms.WebClient)]
public class GPAddIn : IDexterityAddIn
{
// IDexterityAddIn interface
public void Initialize()
{
}
}
}

66 P R O G R A M M E R S G U I D E
C H A P T E R 1 0 B U I LD IN G A N D D EP LO Y IN G

The following Visual Basic example shows how to enable a Visual Basic integration
for both the desktop client and the web client. In this example, the logical-or
operation is used to indicate that both the desktop client and the web client are
supported.

<SupportedDexPlatforms(DexPlatforms.DesktopClient Or DexPlatforms.WebClient)>
Public Class GPAddIn
Implements IDexterityAddIn

' IDexterityAddIn interface


Sub Initialize() Implements IDexterityAddIn.Initialize

End Sub

End Class

Using the Dynamics.exe.config file


You can also use the Dynamics.exe.config file to register the add-ins to be loaded.
This configuration file contains sections that indicate which Visual Studio Tools
add-ins are loaded for the desktop client, GP utilities, and the web client. The
assemblies for the Visual Studio Tools add-ins are placed directly into the main
folder of the Microsoft Dynamics GP installation. You would add an entry for your
add-in to the appropriate section, based on when you want your add-in to be
loaded. This is how Visual Studio Tools add-ins that ship with Microsoft Dynamics
GP are loaded. The full syntax to use for the entry is found in the
Dynamics.exe.config file.

As an example, the following entry will load the FieldDefaulter sample add-in:

<addin name="FieldDefaulter" type="FieldDefaulter.GPAddIn,FieldDefaulter"/>

Building an integration
To build the integration, complete the following procedure:

1. Set the solution configuration.


If youre building a test version of the integration, set the solution configuration
to Debug. If you are building a final version of the integration, set the
solution configuration to Release.

Set the solution


configuration to either
Debug or Release.

2. Build the solution.


Choose Build Solution from the Build menu.

3. Verify there were no build warnings.


If there were build warnings, fix them and build again.

4. Copy the assembly to the AddIns folder.


Copy the assembly for your integration from the Debug or Release folder
for your project to the AddIns folder in the Microsoft Dynamics GP installation.

PROGRAMMERS GUIDE 67
PA RT 2 D E V E L O PI N G I N TE G R A T I O N S

5. Copy any application assemblies needed.


If you created any application assemblies for your integration, be sure to copy
them to the Microsoft Dynamics GP folder.

6. Start Microsoft Dynamics GP.


Your integrating application should be loaded when Microsoft Dynamics GP
starts. Verify that your integration is working properly.

Deploying an integration
When deploying your integration built with Visual Studio Tools for Microsoft
Dynamics GP, be sure that you include the following:

The assembly for your integration.

Any additional application assemblies you generated that are specific to your
integration.

The .xap file that you created, if your integration is being used with the
Microsoft Dynamics GP web client, and implements custom rendering.

Instructions that explain how to install your integration.

68 P R O G R A M M E R S G U I D E
Chapter 11: Debugging
When developing an integrating application, you may find it necessary to examine
the code with the Visual Studio debugger. Information about debugging your
Microsoft Dynamics GP integration is divided into the following sections:

Preparing to debug
Examining the application
Disabling events

Preparing to debug
To prepare your integrating application for debugging, complete the following
procedure.

1. Build and deploy the integration.


Be sure that you have built the Debug version of your project.

2. Start Microsoft Dynamics GP.


Microsoft Dynamics GP must be running so that your integrating application is
loaded.

3. Set breakpoints in your code.


Within Visual Studio, set breakpoints in your code to indicate where you want
processing to wait.

4. Choose to attach to a process.


Since your integrating application is running within the Dynamics.exe process,
you must attach the Visual Studio debugger to this process. From within Visual
Studio, choose Attach to Process from the Debug menu.

5. Select the Dynamics.exe process.


In the Attach to Process window, locate the Dynamics.exe process and select it
in the list.

Locate the Dynamics.exe


process and select it in
the list.

Click Attach to attach to the process. Control will be returned to Visual Studio.

PROGRAMMERS GUIDE 69
PA RT 2 D E V E L O PI N G I N TE G R A T I O N S

Examining the application


Once your integrating application has stopped at a breakpoint, you can use Visual
Studios tools to examine your code. Do the following:

1. Switch to Microsoft Dynamics GP.

2. Perform the actions to exercise your code.


Within Microsoft Dynamics GP, perform the actions that will execute the code
you want to examine.

3. Examine your code.


When Visual Studio encounters a breakpoint, it will become the active
application. Use the tools within Visual Studio to examine your code.

Examine your code while


stopped at the
breakpoints you set.

4. Finish debugging.
When you have finished debugging your integrating application, choose Stop
Debugging from the Debug menu in Visual Studio.

Disabling events
In some cases, you may want to disable the events for the Visual Studio Tools add-
ins to confirm whether they are causing some specific behavior in the Microsoft
Dynamics GP application. To disable events, use the Customization Status window
in Microsoft Dynamics GP. To open this window, point to Customize in the Tools
menu, and then choose Customization Status. Select the Microsoft Dynamics GP
product, and then click Disable. Be sure to enable the events after you have
completed your tests.

70 P R O G R A M M E R S G U I D E
Chapter 12: Modified and Alternate Forms
To access modified or alternate forms from a Visual Studio Tools for Microsoft
Dynamics GP, a special process is used. This portion of the documentation
describes the steps necessary. Information is divided into the following sections:

Modified forms
Alternate forms
Guidelines

Modified forms
Modified forms contain modifications that have been made with the Modifier. To
access these modifications from your Visual Studio Tools for Microsoft Dynamics
GP project, complete the following procedure:

1. Create an application assembly for the forms dictionary.


If the forms dictionary for the application that has been modified doesnt have
an application assembly, create one using the process described in Chapter 6,
Dictionary Assembly Generator. For example, the following command
creates the application assembly for the forms dictionary of the core Dynamics
GP product:

dag.exe 0 "C:\Program Files\Microsoft Dynamics\GP\Dynamics.set" /F /N:Dynamics

The /N option is necessary because the application assembly uses the name
Dynamics, while the product name in the launch file is Microsoft Dynamics GP.

2. Add the reference to the application assembly for your project.


In Visual Studio, add the reference to the application assembly. The following
illustration show the reference added for the application assembly that
provides access to modified forms for the Dynamics GP core dictionary.

This reference to the


application assembly provides
access to the modified forms
for the application.

3. Access the modified forms.


Modified forms are accessed through an additional dictionary class that has the
same name as the applications dictionary class, but with the additional phrase
Modified. For instance, the dictionary class used to access modified forms for
the Dynamics core application is:

DynamicsModified

PROGRAMMERS GUIDE 71
PA RT 2 D E V E L O PI N G I N TE G R A T I O N S

The following C# code sets the value of a new field on the Credit Limit window of
the Customer Maintenance form. The new field is a local field, added with the
Modifier, and named Test.

DynamicsModified.Forms.RmCustomerMaintenance.RmCreditLimit.LocalTest.Value =
"Modified Field";

When accessing resources that are defined in the main dictionary for an application, access
them through the main dictionary class, rather than through the Modified class for the
application.

Alternate forms
Alternate forms are forms from the core Dynamics dictionary that have been
changed by a third-party developer, and are stored in a third-party dictionary. The
new and changed resources for the alternate form are accessed through the third-
party applications application assembly. To access alternate forms from you Visual
Studio Tools for Microsoft Dynamics GP project, complete the following procedure:

1. Create an application assembly for the third-party dictionary.


If the third-party dictionary doesnt already have an application assembly,
create one using the process described in Chapter 6, Dictionary Assembly
Generator. For example, the following command creates the application
assembly for the Sample Integrating Application, to which an alternate form
(PM Vendor Maintenance) was added for this example:

dag.exe 3333 "C:\Program Files\Microsoft Dynamics\GP\Dynamics.set" /M

2. Add the reference to the application assembly for your project.


In Visual Studio, add the reference to the application assembly. The following
illustration show the reference added for the application assembly that
provides access to the alternate forms in the Sample Integrating App
application.

This reference to the


application assembly provides
access to the alternate forms
for the application.

3. Access the alternate forms.


Alternate forms are accessed through the dictionary class for the assembly that
contains them. For instance, the alternate forms in the Sample Integrating App
application would be accessed through its dictionary class:

SampleIntegratingApp

72 P R O G R A M M E R S G U I D E
C H A P T E R 1 2 M O D IFI ED A N D AL T ER N AT E F O R M S

The following C# code sets the value of a new field on the Vendor Maintenance
window of the alternate version of the Vendor Maintenance form, which is part of
the Sample Integrating App dictionary. The new field is a local field named Test.

SampleIntegratingApp.Forms.PmVendorMaintenance.PmVendorMaintenance.
LocalTest.Value = "Alternate Field";

Guidelines
If you are planning to use Visual Studio Tools for Microsoft Dynamics GP to
develop an integration for general distribution, we recommend that you limit the
references to resources on modified or alternate forms. Because of security settings,
a specific user may not have access to the modified or alternate version of a form,
possibly causing errors in your integration. If you do distribute an integration
which accesses modified or alternate forms, be sure that your code properly
handles cases when these resources are not available.

For instance, when you set or retrieve the value of a field, use a try...catch block to
enclose the statements. This allows your code to catch any exceptions that are
thrown because the field cannot be accessed. The following C# example shows how
a field in window for an alternate version of the Vendor Maintenance form can be
set within a try...catch block.

// Set the Status local field in the alternate form


try
{
SampleIntegratingApp.Forms.PmVendorMaintenance.PmVendorMaintenance.
LocalStatus.Value = "Preferred";
}
catch (Exception ex)
{
// The field was not accessible. In this example, display a message.
MessageBox.Show(ex.Message);
}

PROGRAMMERS GUIDE 73
74 P R O G R A M M E R S G U I D E
Chapter 13: Implementing Macro Support
You can add macro support for the forms you create with Visual Studio Tools.
Information about doing this is contained in the following sections:

Overview of macro support


Recording macros
Playing macros
Handling asynchronous processes during playback

Overview of macro support


In Visual Studio Tools, forms you create that inherit from the DexUIForm can be
integrated into the macro system in Microsoft Dynamics GP. Support for the macro
system is not automatic. To support the macro system you will do the following:

You must add calls to the RecordMacroItem() method in the appropriate places
in your Visual Studio Tools add-in to record macro commands for your form.

You must override the PlayMacroItem() method in the DexUIForm base class,
and add code to support playback of your macro commands.

If your Visual Studio Tools form makes asynchronous calls to other processes
that the macro system will need to wait for, you will need to override the
IsAsynchEventPending() method.

Recording macros
In your Visual Studio Tools form, identify the places that the user can perform
actions. Actions include things like clicking buttons, adding text to text fields, or
moving the focus. In the events that run due to these user actions, you will add code
that calls the RecordMacroItem() method to record a text string and optional
comment that identify and describe the action. For example, the following C# code
records a macro command for the Energy Star check box:

RecordMacroItem("ClickHit EnergyStar", "Toggle the Energy Star check box");

The text strings passed to the RecordMacroItem() method are written to the macro
as ShellCommand macro statements.

ShellCommand 'ClickHit EnergyStar' # Toggle the Energy Star check box

The RecordMacroItem() method records values only when a macro is being recorded.

Macro syntax
The text string and optional comment recorded in the macro are the only
information available to your Visual Studio Tools add-in when the macro is played
back. These text strings must contain enough information for your code to
determine the action that must be performed.

There is no predefined syntax for the text strings recorded. You must define the text
strings so that they can be parsed by your add-in, and then the add-in can perform
the actions indicated. The macro support in the Environmental Details Visual Studio
Tools sample is a good starting point. The syntax of its macro statements is similar
to the standard Microsoft Dynamics GP macro language.

PROGRAMMERS GUIDE 75
PA RT 2 D E V E L O PI N G I N TE G R A T I O N S

Placement
Where you place the RecordMacroItem() calls in your code can affect how data is
written to the macro. Some experimenting may be required to find which event for a
control is most appropriate for recording a macro action. For example, when
recording the text entered into a text box control, the Validating event is the most
appropriate place for the RecordMacroItem() call. The following C# example shows
the Validating event for the YearlyEnergyCost text box in the Environmental Details
sample.

private void textBoxYearlyEnergyCost_Validating(object sender,


CancelEventArgs e)
{
// Set the change flag for the Item Maintenance window
GPAddIn.ItemMaintenanceWindow.IsChanged = true;

// If a macro is being recorded, record the value.


RecordMacroItem("TypeTo YearlyEnergyCost \"" +
textBoxYearlyEnergyCost.Text + "\"", String.Empty);
}

The following table lists the event where the macro recording code should be placed
for common controls.

Control Event
Text box Validating
Push Button Click
Check box Validating

Playing macros
When a ShellCommand macro statement is played back, and your Visual Studio
Tools form is active, the PlayMacroItem() method will be called. You must override
this method in your Visual Studio Tools add-in code, and process the macro
statements for your form. The following C# example shows how you override the
base method.

public override void PlayMacroItem(MacroPlaybackEventArgs e)


{

Event arguments
The following event arguments are passed into the PlayMacroItem() method:

Handled This is a boolean parameter that indicates whether the action for macro
statement has been performed. You should check the value of this parameter at the
beginning of your PlayMacroItem() method. If its value is true, the macro statement
has already been handled, so your code should take no action. If you determine that
your code should perform the action for the macro statement, set the Handled
parameter to true when the action is complete. This tells other code that the macro
statement has already been processed.

MacroText This string parameter contains the macro string that was written by
the RecordMacroItem() method when the macro was recorded. You will need parse
this string to determine whether your add-in must perform the macro action.

76 P R O G R A M M E R S G U I D E
C H A P T E R 1 3 I M P L EM EN T I N G M A C R O S U PP O R T

MacroComment This string parameter contains the comment that was written
by the RecordMacroItem() method when the macro was recorded.

Processing macro statements


Your code will retrieve the MacroText parameter from the event arguments, and
then parse the text to determine whether this macro statement should be performed
by your add-in. You can use any approach you like when parsing the macro
statement. The Environmental Details sample uses regular expressions to parse the
macro statement. The following C# example shows the complete PlayMacroItem()
method for the sample. Notice that if the code performs the macro action, it sets the
Handled parameter to true. If it doesnt perform the action, it allows the base class
to do so.

public override void PlayMacroItem(MacroPlaybackEventArgs e)


{
Match m;

if (e.Handled == false)
{
// Process Yearly Energy Cost text box
m = Regex.Match(e.MacroText, "TypeTo YearlyEnergyCost \"(.+)\"");
if (m.Success)
{
if (m.Groups.Count >= 2)
{
textBoxYearlyEnergyCost.Focus();
textBoxYearlyEnergyCost.Text = m.Groups[1].Value;
e.Handled = true;
}
}

// Process Notes text box


m = Regex.Match(e.MacroText, "TypeTo EnvNotes \"(.+)\"");
if (m.Success)
{
if (m.Groups.Count >= 2)
{
textBoxNotes.Focus();
textBoxNotes.Text = m.Groups[1].Value;
e.Handled = true;
}
}

// Process the push buttons and check boxes


m = Regex.Match(e.MacroText, "ClickHit (\\w+)");
if (m.Success)
{
if (m.Groups.Count >= 2)
{
// Energy Star check box
if (m.Groups[1].Value == "EnergyStar")
{
checkBoxEnergyStar.Focus();
checkBoxEnergyStar.Checked = !checkBoxEnergyStar.Checked;
e.Handled = true;
}

PROGRAMMERS GUIDE 77
PA RT 2 D E V E L O PI N G I N TE G R A T I O N S

// Recyclable check box


if (m.Groups[1].Value == "Recyclable")
{
checkBoxRecyclable.Focus();
checkBoxRecyclable.Checked = !checkBoxRecyclable.Checked;
e.Handled = true;
}

// Close button
if (m.Groups[1].Value == "CloseButton")
{
buttonClose.Focus();
buttonClose.PerformClick();
e.Handled = true;
}
}
}
}

// Macro command was not ours, so let the base class process it.
base.PlayMacroItem(e);
}

Handling asynchronous processes during playback


If your Visual Studio Tools form makes asynchronous calls to other processes that
the macro system will need to wait for, you may need to override the
IsAsynchEventPending() method of the DexUIForm base class. This method is
called periodically when a macro is being played. If the method returns true, the
macro system will wait for the asynchronous event to finish before additional
macro statements are processed.

Override the IsAsynchEventPending() method only if your Visual Studio Tools add-in has
asynchronous processes that the macro system must wait for.

The following C# example shows how you override the method from the base class.
Typically, you will create your own flag that tracks whether your add-in is running
an asynchronous process. In the IsAsynchEventPending() method, you will return
the value of this flag. When the asynchronous process starts, you will set the flag to
true. This causes the macro system to wait for the asynchronous event. When the
asynchronous process finishes, you will set the flag to false. This will allow the
macro system to resume processing.

public override bool IsAsyncEventPending


{
get
{
// Return the value of the flag that indicates whether an
// asynchronous event is being processed.
return InAsyncEventFlag;
}
}

78 P R O G R A M M E R S G U I D E
Chapter 14: Using Lookups
Lookups are special-purpose windows used to retrieve existing ID values for
objects in Microsoft Dynamics GP, such as customers, vendors, and sales
documents. You may need to retrieve ID values for your Visual Studio Tools
integration. In many cases, you can use the lookups defined in Microsoft Dynamics
GP to retrieve ID values for fields on your Visual Studio Tools form. Information
about using lookups is divided into the following sections:

How lookups work


Available lookups
Lookup example

How lookups work


Lookup windows in Microsoft Dynamics GP are separate forms. The core Dynamics
dictionary contains lookups with basic lookup functionality. The lookup windows
that the user sees in Microsoft Dynamics GP are actually alternate versions of the
forms, and are defined in the SmartList dictionary. This means that your Visual
Studio Tools code will reference lookups from the SmartList dictionary.

The following steps describe the basic operation of a lookup for a Visual Studio
Tools integration:

1. Add code to track that your integration has opened the lookup.
Lookup forms can be opened by the core Microsoft Dynamics GP application,
and by other integrating products. Your Visual Studio Tools integration must
track that it has opened the lookup, so it will know to retrieve the value that
was selected by the user.

Typically, each lookup used by a Visual Studio Tools integration is tracked


using a static variable defined in the GPAddIn class. The variable must be set
when the lookup is opened, and cleared when the lookup returns a value.

2. Add code to open the lookup form.


Typically, the user clicks a lookup button that opens the lookup form. In your
Visual Studio Tools form, you will add code to the lookup button that will open
the lookup form.

3. Register the ClickBeforeOriginal event for the Select button.


A value is returned from the lookup when the user clicks the Select button in
the lookup form. You will register the ClickBeforeOriginal event on the Select
button to be notified when the button is clicked.

4. Return the ID of the selected item.


When the user clicks the Select button in the lookup, the ID of the selected item
is returned by the event handler for the ClickBeforeOriginal event. This event
handler also clears the static variable that is tracking that the lookup was
opened by the Visual Studio Tools integration.

PROGRAMMERS GUIDE 79
PA RT 2 D E V E L O PI N G I N TE G R A T I O N S

Available lookups
Several different patterns have been used to code the lookup forms in Microsoft
Dynamics GP. Each pattern requires a specific technique to use the lookup. To learn
what lookups are available and how to call them, refer to the document titled
Calling Lookup Forms from Dexterity in the Microsoft Dynamics GP SDK. The
link for this document is found in the Foundation group of the Procedures and
functions section of the Microsoft Dynamics GP SDK help file.

The Lookups sample, described in Chapter 34, Lookups, demonstrates how to use several
common lookup forms in a Visual Studio Tools integration.

In some cases, Visual Studio Tools cannot access all of the resources required to use
the lookup form. For example, some lookup forms are opened by calling procedures
that have reference parameters. Because Visual Studio Tools cannot call procedures
with reference parameters, these lookup forms cannot be used with Visual Studio
Tools integrations.

Lookup example
The following example shows how to use the Customers and Prospects lookup
form in Microsoft Dynamics GP to retrieve customer numbers for a Visual Studio
Tools integration.

1. Add a reference to the SmartList application assembly.


The Customers and Prospects lookup is one of the enhanced lookups for
Microsoft Dynamics GP that are contained in the SmartList dictionary.

2. Add a Lookup button to the Visual Studio Tools form.


Refer to Adding controls on page 27 for details about how to add a control to a
Visual Studio Tools form.

3. Add the flag to track that a lookup was opened.


In the GPAddIn class, add a static variable to track that a lookup was opened.
The following C# example shows code that does this.

// Flag to track that a lookup was opened


public static Boolean ReturnToLookup = false;

4. Add code to open the lookup form.


In the Click event for the Lookup button, add code that opens the lookup. The
actions that this code must perform will depend on the lookup that you are
using. Refer to the document Calling Lookup Forms from Dexterity in the
Microsoft Dynamics GP SDK for information about the available lookups. For
the Customers and Prospects lookup, the following actions must be performed:

The flag is set that indicates the lookup was opened by the Visual Studio
Tools integration.

The CustomerLookup form must be opened.

The Initialize procedure on the CustomerLookup form must be called. This


configures how data is displayed in the lookup.

80 P R O G R A M M E R S G U I D E
C H A P T E R 1 4 U S I N G L O O K U P S

The following C# example shows how the Customers lookup is opened.

private void CustomerLookup_Click(object sender, EventArgs e)


{
// Create a reference to the CustomerLookup form
Microsoft.Dexterity.Applications.SmartListDictionary.
CustomerLookupForm customerLookup = SmartList.Forms.CustomerLookup;

// Set the flag indicating that we opened the lookup


GPAddIn.ReturnToLookup = true;

// Open the CustomerLookup form


customerLookup.Open();

// Call the Initialize procedure to configure the Customer Lookup


customerLookup.Procedures.Initialize.Invoke(1, 0,
CustomerNumber.Text, "", "", "", "", "");
}

5. Register the ClickBeforeOriginal event for the Select button.


In the Initialize method of the GPAddIn class, register the ClickBeforeOriginal
event of the Select button on the CustomerLookup window. The following C#
example shows this registration.

// Select button on the Customers lookup window


Microsoft.Dexterity.Applications.SmartListDictionary.CustomerLookupForm
customerLookupForm = SmartList.Forms.CustomerLookup;
customerLookupForm.CustomerLookup.SelectButton.ClickBeforeOriginal +=
new System.ComponentModel.CancelEventHandler(
SelectButton_ClickBeforeOriginal);

6. Return the ID of the selected item.


In the event handler for the ClickBeforeOriginal event of the Select button,
check the flag that indicates whether the Visual Studio Tools add-in opened the
lookup. If it did, then return the customer number for the customer selected in
the scrolling window of the Customers and Prospects lookup. The following C#
example shows the event handler that performs these actions.

void SelectButton_ClickBeforeOriginal(object sender,


System.ComponentModel.CancelEventArgs e)
{
// Run this code only if the add-in opened the lookup.
if (GPAddIn.ReturnToLookup == true)
{
// Retrieve the customer number of the row selected in the
// scrolling window of the Customers lookup.
Microsoft.Dexterity.Applications.SmartListDictionary.
CustomerLookupForm customerLookupForm =
SmartList.Forms.CustomerLookup;
string customerNumber = customerLookupForm.CustomerLookup.
CustomerLookupScroll.CustomerNumber.Value;

// Display the value retrieved


LookupsWindow.CustomerNumber.Text = customerNumber;

PROGRAMMERS GUIDE 81
PA RT 2 D E V E L O PI N G I N TE G R A T I O N S

// Clear the flag that indicates a value is to be retrieved from


// the lookup.
GPAddIn.ReturnToLookup = false;
}
}

82 P R O G R A M M E R S G U I D E
Chapter 15: Helper Functions
Beginning with Microsoft Dynamics GP 2013 Service Pack 2, several functions are
available in the Dynamics dictionary that provide helpful functionality for a Visual
Studio Tools integration. Information about the helper functions is divided into the
following sections:

Helper function overview


Helper function reference

Helper function overview


The helper functions are part of the SyVisualStudioHelper form in the Dynamics
dictionary. You will use these functions to access specific functionality of the
Microsoft Dynamics GP runtime, such as reading from and writing to the Dex.ini
file.

The helper functions are also used to perform web client operations that cant be
done with standard .NET code. The functions for displaying modal dialog boxes are
an example of this. For Visual Studio Tools integrations for the desktop client, you
can use the MessageBox class from the .NET framework to display modal dialogs.
This class is not supported on the web client. Instead, you must use one of the
helper functions like DexError to display the modal dialog. This helper function
works for both the desktop client and the web client.

The following C# example shows how the DexWarning() helper function is used to
display a modal dialog.

Dynamics.Procedures.GetNextFormNoteToOpen.Invoke(out formNumber);
if (formNumber == 0)
{
// Too many notes already open
Dynamics.Forms.SyVisualStudioHelper.Functions.DexWarning.Invoke
("Too many note windows open");
}

Helper function reference


The following functions are available for the SyVisualStudioHelper form. A
detailed description of each function follows.

Modal dialogs
Use the following functions for modal dialogs.

DexAsk()
DexError()
DexWarning()
DexGetstring()

Message resources
Use the following function to retrieve message resources from the Dynamics
dictionary.

DexGetmsg()

PROGRAMMERS GUIDE 83
PA RT 2 D E V E L O PI N G I N TE G R A T I O N S

Dex.ini file
Use the following functions to read from and write to the Dex.ini file.

DexDefaultsRead()
DexDefaultsWrite()

File locations
Use the following functions to retrieve file locations for Microsoft Dynamics GP.

DexPathGetForApp()
DexFileGetTempDirectory()

File launching
Use the following functions for launching or displaying files and URLs.

DexFileLaunch()
DexUtilityLaunchUrl()
DexWinHelpLaunchUrl()

Web client
Use the following functions to perform tasks for the web client.

DexRuntimeGetClientType()
DexRuntimeGetWebClientTrustLevel()

84 P R O G R A M M E R S G U I D E
D E X A S K ()

DexAsk()
Description The DexAsk() function creates a dialog box containing a message and up to three
user-defined buttons. It returns a value indicating which button is clicked by the
user. Processing stops while the system waits for the user to respond.

Syntax DexAsk(prompt, button1, button2, button3)

Parameters prompt A string with the message to be displayed in the dialog box.

button1 A string containing the label for the first button in the dialog box.

button2 A string containing the label for the second button in the dialog box.

button3 A string containing the label for the third button in the dialog box.

Return value An integer indicating which button the user clicked. It corresponds to one of the
following values:

Value Description
1 Button 1
2 Button 2
3 Button 3

Comments If you want to use fewer than three buttons in the dialog box, use the empty string
("") for the buttons you dont want to use. For example, to display only two
buttons, supply the button text for the first two buttons and the empty string for the
third button.

Examples The following C# example shows the DexAsk() function being used to display a
question to the user asking whether to save changes. The value of the answer
variable depends on the button the user clicked.

Int16 answer;
answer = Dynamics.Forms.SyVisualStudioHelper.Functions.DexAsk.Invoke(
"Do you want to save the changes?", "Yes", "No", "Cancel");
if (answer == 1)
{
// Yes, save the changes
}

if (answer == 2)
{
// No, don't save the changes
}

if (answer == 3)
{
// Cancel was clicked
}

PROGRAMMERS GUIDE 85
D E X A S K ()

The following Visual Basic example shows the DexAsk() function being used to
display a question to the user asking whether to save changes. The value of the
answer variable depends on the button the user clicked.

Dim answer As Int16

answer = Dynamics.Forms.SyVisualStudioHelper.Functions.DexAsk _
.Invoke("Do you want to save the changes?", "Yes", "No", "Cancel")

If answer = 1 Then
'Yes, save the changes
End If

If answer = 2 Then
'No, don't save the changes
End If

If answer = 3 Then
'Cancel was clicked
End If

86 P R O G R A M M E R S G U I D E
D E X D E F A U L T S R E A D ()

DexDefaultsRead()
Description The DexDefaultsRead() function reads the value of a setting in the Microsoft
Dynamics GP defaults file (Dex.ini).

Syntax DexDefaultsRead(setting, target)

Parameters setting A string specifying the setting to read.

target An integer parameter that applies when the per-user defaults file is enabled.
The following values are used:

Value Description
1 Accesses the user-specific DEX.INI file, found in the users temporary folder.
2 Accesses the global DEX.INI file, found in the Data folder of the application.

When specifying the target parameter, you can add the values together (1 + 2) to
read the value from the user-specific DEX.INI file, and then from the global
DEX.INI file.

Return value A string indicating the value of setting. If the setting doesnt exist, the returned string
will be empty.

Examples The following C# example retrieves the value of the SampleSetting value of the
Dex.ini file. The user-specific Dex.ini file is examined first, and then the global file is
accessed. The value retrieved is displayed in a text box.

RetrievedValue.Text = Dynamics.Forms.SyVisualStudioHelper.Functions.
DexDefaultsRead.Invoke("SampleSetting", 1 + 2);

The following Visual Basic example retrieves the value of the SampleSetting
value of the Dex.ini file. The user-specific Dex.ini file is examined first, and then the
global file is accessed. The value retrieved is displayed in a text box.

RetrievedValue.Text = Dynamics.Forms.SyVisualStudioHelper.Functions. _
DexDefaultsRead.Invoke("SampleSetting", 1 + 2)

PROGRAMMERS GUIDE 87
D E X D E F A U L T S W R I T E ( )

DexDefaultsWrite()
Description The DexDefaultsWrite() function writes a setting to the Microsoft Dynamics GP
defaults file (Dex.ini).

Syntax DexDefaultsWrite(setting, value, target)

Parameters setting A string indicating the setting in the file you want to write to. If setting
doesnt exist, one is created.

value A string specifying a value for setting.

target An integer parameter that applies when the per-user defaults file is enabled.
The following values can be used:

Value Description
1 Accesses the user-specific DEX.INI file, found in the users temporary folder.
2 Accesses the global DEX.INI file, found in the Data folder of the application.

If the per-user defaults file is not enabled, the setting will be written to the global
DEX.INI file found in the Data folder of the application.

Return value The boolean value true.

Examples The following C# example writes the value from a text box to the SampleSetting
value of the global Dex.ini file.

Dynamics.Forms.SyVisualStudioHelper.Functions.DexDefaultsWrite.Invoke(
"SampleSetting", INIValue.Text.ToString(), 2);

The following Visual Basic example writes the value from a text box to the
SampleSetting value of the global Dex.ini file.

Dynamics.Forms.SyVisualStudioHelper.Functions.DexDefaultsWrite _
.Invoke("SampleSetting", INIValue.Text.ToString(), 2)

88 P R O G R A M M E R S G U I D E
D E X E R R O R ()

DexError()
Description The DexError() function creates an error dialog box displaying the specified string.
Processing stops while the system waits for the user to respond.

Syntax DexError(prompt)

Parameters prompt A string with the message to be displayed in the dialog box.

Return value The boolean value true.

Comments The dialog box has one button labeled OK. The icon displayed is the standard error
icon for the operating system.

Examples The following C# example uses the DexError() function to display any unexpected
exception that occurs when the Estimate Freight form is created.

static void OpenEstimateFreight(object sender, EventArgs e)


{
if (EstimateFreightForm == null)
{
try
{
EstimateFreightForm = new EstimateFreight();
}
catch (Exception ex)
{
Dynamics.Forms.SyVisualStudioHelper.Functions.DexError
.Invoke(ex.Message);
}
}

// Always show and activate the WinForm


EstimateFreightForm.Show();
EstimateFreightForm.Activate();
}

The following Visual Basic example uses the DexError() function to display any
unexpected exception that occurs when the Estimate Freight form is created.

Shared Sub OpenEstimateFreight(ByVal sender As Object, ByVal e As EventArgs)


If EstimateFreightForm Is Nothing Then
Try
EstimateFreightForm = New EstimateFreightForm()
Catch ex As Exception
Dynamics.Forms.SyVisualStudioHelper.Functions.DexError _
.Invoke(ex.Message)
End Try
End If

' Always show and activate the WinForm


EstimateFreightForm.Show()
EstimateFreightForm.Activate()
End Sub

PROGRAMMERS GUIDE 89
D E X F I L E G E T T E M P D I R E C T O R Y ()

DexFileGetTempDirectory()
Description The DexFileGetTempDirectory() function retrieves the complete path to the local
temporary folder for the current user.

Syntax DexFileGetTempDirectory()

Parameters None

Return value A string containing the complete path to the local temporary folder. The path is in
native format.

Comments For the web client, the path to the Temp folder for the users web client session on
the session host server is retrieved. This is the only location that an integrating
application can write a file to for the web client.

Examples The following C# example retrieves the location of the temporary folder for the
current user and displays the location in a modal dialog box.

string directory;

directory = Dynamics.Forms.SyVisualStudioHelper.Functions.
DexFileGetTempDirectory.Invoke();

Dynamics.Forms.SyVisualStudioHelper.Functions.DexWarning.
Invoke(directory);

The following Visual Basic example retrieves the location of the temporary folder
for the current user and displays the location in a modal dialog box.

Dim directory As String

directory = Dynamics.Forms.SyVisualStudioHelper.Functions _
.DexFileGetTempDirectory.Invoke()

Dynamics.Forms.SyVisualStudioHelper.Functions.DexWarning.Invoke(directory)

90 P R O G R A M M E R S G U I D E
D E X F I L E L A U N C H ()

DexFileLaunch()
Description The DexFileLaunch() function attempts to open or print the specified file. For the
web client, the function transfers the specified file from the server to the web client
before the launch action is performed.

Syntax DexFileLaunch(pathname, action)

Parameters pathname A string containing the native pathname indicating the file to launch.

action An integer that specifies the launch action to take for the file. The value
corresponds to one of the following constants:

Value Description
1 The file is opened and displayed on the client machine.
2 The file is opened and printed on the client machine.
0 This action is used only for the web client. After the file has been transferred
from the server to the web client, no further action is taken.

Return value A boolean. The value true indicates the file launch action was successful, while the
value false indicates that it was not.

Comments The client operating system will select the best application to view or print the file.

Examples The following C# example launches the file in the location indicated by the value of
the textBoxFile control. If the file indicated cannot be launched, an error dialog is
displayed.

bool result;

if (Dynamics.Forms.SyVisualStudioHelper.Functions.DexRuntimeGetClientType
.Invoke() == 1)
{
// Desktop client
result = Dynamics.Forms.SyVisualStudioHelper.Functions.DexFileLaunch
.Invoke(textBoxFile.Text, 1);

if (result == false)
{
Dynamics.Forms.SyVisualStudioHelper.Functions.DexError
.Invoke("Could not open file");
}
}
else
{
// Web client
Dynamics.Forms.SyVisualStudioHelper.Functions.DexError
.Invoke("Action not available");
}

PROGRAMMERS GUIDE 91
D E X F I L E L A U N C H ( )

The following Visual Basic example launches the file in the location indicated by the
value of the TextBoxFile control. If the file indicated cannot be launched, an error
dialog is displayed.

Dim result As Boolean

If (Dynamics.Forms.SyVisualStudioHelper.Functions.DexRuntimeGetClientType _
.Invoke() = 1) Then

'Desktop client
result = Dynamics.Forms.SyVisualStudioHelper.Functions.DexFileLaunch _
.Invoke(TextBoxFile.Text, 1)

If result = False Then


Dynamics.Forms.SyVisualStudioHelper.Functions.DexError _
.Invoke("Could not open file")
End If
Else
'Web client
Dynamics.Forms.SyVisualStudioHelper.Functions.DexError _
.Invoke("Action not available")
End If

92 P R O G R A M M E R S G U I D E
D E X G E T M S G ()

DexGetmsg()
Description The DexGetmsg() function returns a message string that is stored in the application
dictionary.

Syntax getmsg(message_ID)

Parameters message_ID An integer containing the message ID of the message you want to
retrieve.

Comments Message strings are often used for messages displayed to the user.

Return value String

Examples The following C# example shows how a message string is retrieved and displayed
to the user if the checkbook ID supplied is not valid. The message with message ID
397 says, The checkbook doesnt exist.

TableError err;
string message;

CmCheckbookMstrTable CheckbookMasterTable;
CheckbookMasterTable = Dynamics.Tables.CmCheckbookMstr;

// Set the key value


CheckbookMasterTable.CheckbookId.Value = textBoxID.Text;

// Set the key to use


CheckbookMasterTable.Key = 1;

// Try to retrieve the record


err = CheckbookMasterTable.Get();

if (err == TableError.NotFound)
{
// Could not find checkbook
message = Dynamics.Forms.SyVisualStudioHelper.Functions.DexGetmsg.
Invoke(397);

Dynamics.Forms.SyVisualStudioHelper.Functions.DexError.
Invoke(message);
}

if (err == TableError.NoError)
{
textBoxDescription.Text = CheckbookMasterTable.Description.Value;
}

// Close the table


CheckbookMasterTable.Close();

PROGRAMMERS GUIDE 93
D E X G E T M S G ( )

The following Visual Basic example shows how a message string is retrieved and
displayed to the user if the checkbook ID supplied is not valid. The message with
message ID 397 says, The checkbook doesnt exist.

Dim err As TableError


Dim message As String

Dim CheckbookMasterTable As CmCheckbookMstrTable


CheckbookMasterTable = Dynamics.Tables.CmCheckbookMstr

'Set the key value


CheckbookMasterTable.CheckbookId.Value = TextBoxID.Text

'Set the key to use


CheckbookMasterTable.Key = 1;

'Try to retrieve the record


err = CheckbookMasterTable.Get()

If err = TableError.NotFound Then


'Could not find checkbook
message = Dynamics.Forms.SyVisualStudioHelper.Functions.DexGetmsg _
.Invoke(397)
Dynamics.Forms.SyVisualStudioHelper.Functions.DexError _
.Invoke(message)
End If

If err = TableError.NoError Then


textBoxDescription.Text = CheckbookMasterTable.Description.Value
End If

'Close the table


CheckbookMasterTable.Close()

94 P R O G R A M M E R S G U I D E
D E X G E T S T R I N G ()

DexGetstring()
Description The DexGetstring() function creates a dialog box that allows the user to enter a
string, and returns a boolean value indicating whether the user clicked OK or
Cancel in the dialog box. When the dialog is closed, the string will be returned in
the variable named in the string_variable parameter.

Syntax DexGetstring(prompt, password, string_variable)

Parameters prompt A string with the message to be displayed in the dialog box.

password A boolean value indicating how the entry will be displayed. If set to true,
the characters typed will be obscured, preventing others from seeing what is being
entered. If set to false, the users entry will appear normally.

string_variable If this variable contains a value, it will appear as a default when the
dialog is displayed. When the user closes the dialog by clicking OK or Cancel, the
value in the dialog will be returned to this variable.

Return value A boolean. If OK was clicked, the value of true is returned, and the string entered by
the user is returned to the string_variable parameter. If Cancel was clicked, only the
boolean value false is returned.

Examples The following C# example shows the DexGetstring() function being used to ask for
a password. If the string supplied by the user matches the word magic then
access is granted. Notice how the string value must be passed in as a reference value
to this function.

string string_val = "";


bool result;

result = Dynamics.Forms.SyVisualStudioHelper.Functions.DexGetstring
.Invoke("Enter the password", true, ref string_val, 0);

if (result == true)
{
if (string_val == "magic")
{
Dynamics.Forms.SyVisualStudioHelper.Functions.DexWarning
.Invoke("Access granted");
}
}

The following Visual Basic example shows the DexGetstring() function being used
to ask for a password. If the string supplied by the user matches the word magic
then access is granted.
Dim string_val As String = ""
Dim result As Boolean

result = Dynamics.Forms.SyVisualStudioHelper.Functions.DexGetstring. _
Invoke("Enter the password", True, string_val, 0)

If result = True Then


If string_val = "magic" Then
Dynamics.Forms.SyVisualStudioHelper.Functions.DexWarning. _
Invoke("Access granted")
End If
End If

PROGRAMMERS GUIDE 95
D E X G E T S T R I N G ( )

96 P R O G R A M M E R S G U I D E
D E X P A T H G E T F O R A P P ()

DexPathGetForApp()
Description The DexPathGetForApp() function returns the path of various components of the
current installation, such as the runtime engine or launch file.

Syntax DexPathGetForApp(option)

Parameters option An integer indicating which path to return:

Value Description
1 The path of the folder containing the runtime engine (Dynamics.exe).
2 The path of the folder containing the launch file used to start the application.
3 The path to the Data folder for the installation. Files writable by the user are
stored in this folder.
4 The path of the user-specific Dex.ini file currently being used. If per-user defaults
files are not active, the path to the global Dex.ini is returned.
5 The path of the launch file (.set file) currently being used.
6 The path to the global Dex.ini file, found in the Data folder for the installation.

Return value A string containing the path requested in native format.

Examples The following C# example retrieves the location for the runtime engine in the
Microsoft Dynamics GP installation.

textBoxPath.Text =
Dynamics.Forms.SyVisualStudioHelper.Functions.DexPathGetForApp
.Invoke(1);

The following Visual Basic example retrieves the location for the Data folder in
the Microsoft Dynamics GP installation.

TextBoxPath.Text =
Dynamics.Forms.SyVisualStudioHelper.Functions.DexPathGetForApp _
.Invoke(1)

PROGRAMMERS GUIDE 97
D E X R U N T I M E G E T C L I E N T T Y P E ( )

DexRuntimeGetClientType()
Description The DexRuntimeGetClientType() function returns information about the runtime
engine that is processing the application.

Syntax DexRuntimeGetClientType()

Parameters None

Return value An integer value indicating the client type.

Value Description
1 The runtime engine for the desktop client.
2 The runtime engine for the web client.
0 The runtime engine that does not directly present a user interface, such as
the Process Server.

Comments This function is typically used when writing code that can be performed only for a
specific client type.

Examples The following C# example retrieves whether the code is being run on the desktop
client or the web client. If it is running on the desktop client, the code launches the
file in the location indicated by the value of the textBoxFile control. If the file
indicated cannot be launched, an error dialog is displayed.

bool result;

if (Dynamics.Forms.SyVisualStudioHelper.Functions.DexRuntimeGetClientType
.Invoke() == 1)
{
// Desktop client
result = Dynamics.Forms.SyVisualStudioHelper.Functions.DexFileLaunch
.Invoke(textBoxFile.Text, 1);

if (result == false)
{
Dynamics.Forms.SyVisualStudioHelper.Functions.DexError
.Invoke("Could not open file");
}
}
else
{
// Web client
Dynamics.Forms.SyVisualStudioHelper.Functions.DexError
.Invoke("Action not available");
}

The following Visual Basic example retrieves whether the code is being run on the
desktop client or the web client. If it is running on the desktop client, the code
launches the file in the location indicated by the value of the textBoxFile control. If
the file indicated cannot be launched, an error dialog is displayed.

Dim result As Boolean

If (Dynamics.Forms.SyVisualStudioHelper.Functions.DexRuntimeGetClientType _
.Invoke() = 1) Then

98 P R O G R A M M E R S G U I D E
D E X R U N T I M E G E T C L I E N T T Y P E ()

'Desktop client
result = Dynamics.Forms.SyVisualStudioHelper.Functions.DexFileLaunch _
.Invoke(TextBoxFile.Text, 1)

If result = False Then


Dynamics.Forms.SyVisualStudioHelper.Functions.DexError _
.Invoke("Could not open file")
End If
Else
'Web client
Dynamics.Forms.SyVisualStudioHelper.Functions.DexError _
.Invoke("Action not available")
End If

PROGRAMMERS GUIDE 99
D E X R U N T I M E G E T W E B C L I E N T T R U S T L E V E L ( )

DexRuntimeGetWebClientTrustLevel()
Description The DexRuntimeGetWebClientTrustLevel() function returns an integer indicating
the trust level of the Silverlight application for the web client.

Syntax DexRuntimeGetWebClientTrustLevel()

Parameters None

Return value An integer value indicating the trust level:

Value Description
0 The Silverlight application for the web client is running in sandboxed mode.
1 The Silverlight application for the web client is running in fully-trusted mode.

Comments By default, the Silverlight application for the web client runs in sandboxed mode.
This means it has restricted access to local system resources. When a user attempts
to perform an action (such as downloading a file that was created by a report) the
sandboxed mode may prevent them from doing so. The local system can be
configured to run the Silverlight application for the web client with enhanced trust
level, allowing these formerly restricted actions.

Examples The following C# example retrieves the trust level for the application.

if (Dynamics.Forms.SyVisualStudioHelper.Functions
.DexRuntimeGetWebClientTrustLevel.Invoke() == 1)
{
checkBoxTrust.Checked = true;
}
else
{
checkBoxTrust.Checked = false;
}

The following Visual Basic example retrieves the trust level for the application.

If Dynamics.Forms.SyVisualStudioHelper.Functions _
.DexRuntimeGetWebClientTrustLevel.Invoke() = 1 Then

CheckBoxTrust.Checked = True

Else

CheckBoxTrust.Checked = False

End If

100 P R O G R A M M E R S G U I D E
D E X U T I L I T Y L A U N C H U R L ()

DexUtilityLaunchUrl()
Description The DexUtilityLaunchUrl() function opens a web browser and displays the content
of the specified URL.

Syntax DexUtilityLaunchUrl(URL)

Parameters URL A string specifying the complete URL to launch.

Return value None

Examples The following C# example launches a web browser to display the Microsoft web
site.

Dynamics.Forms.SyVisualStudioHelper.Functions.DexUtilityLaunchUrl
.Invoke("http://www.microsoft.com");

The following Visual Basic example launches a web browser to display the
Microsoft web site.

Dynamics.Forms.SyVisualStudioHelper.Functions.DexUtilityLaunchUrl _
.Invoke("http://www.microsoft.com")

PROGRAMMERS GUIDE 101


D E X W A R N I N G ( )

DexWarning()
Description The DexWarning() function creates a warning dialog box displaying the specified
string. Processing stops while the system waits for the user to respond.

Syntax DexWarning(prompt)

Parameters prompt A string with the message to be displayed in the dialog box.

Return value The boolean value true.

Comments The dialog box has one button labeled OK. The icon displayed is the standard
warning icon for the operating system.

Examples The following C# example retrieves the number of the next note form that can
opened in Microsoft Dynamics GP. If the value returned is 0 (zero) then the
DexWarning() function is used to display the message indicating that no additional
note windows can be opened.

Dynamics.Procedures.GetNextFormNoteToOpen.Invoke(out formNumber);
if (formNumber == 0)
{
// Too many notes already open
Dynamics.Forms.SyVisualStudioHelper.Functions.DexWarning.Invoke
("Too many note windows open");
}

The following Visual Basic example retrieves the number of the next note form that
can opened in Microsoft Dynamics GP. If the value returned is 0 (zero) then the
DexWarning() function is used to display the message indicating that no additional
note windows can be opened.

Dynamics.Procedures.GetNextFormNoteToOpen.Invoke(formNumber)
If formNumber = 0 Then
' Too many notes alread open
Dynamics.Forms.SyVisualStudioHelper.Functions.DexWarning _
.Invoke("Too many note windows open")
End If

102 P R O G R A M M E R S G U I D E
D E X W I N H E L P L A U N C H U R L ()

DexWinHelpLaunchUrl()
Description The DexWinHelpLaunchUrl() function launches help content for the Microsoft
Dynamics GP web client. The content is displayed in a new web browser window.

Syntax DexWinHelpLaunchUrl(url)

Parameters url A string that specifies the URL of the content to be displayed in a new web
browser window. The URL can be a complete URL or a partial URL.

Return value None

Comments If you are specifying a complete URL, the URL should begin with http:// or https://
and contains the full path to the content to be displayed.

If you are specifying a relative URL, the relative URL should begin with a forward
slash (/) and provide the remaining path to the content after the server name. The
Microsoft Dynamics GP web client runtime will automatically prepend the server
name to the relative URL.

The content is displayed in new web browser window that has a special name
assigned to it. If this browser window is left open, subsequent calls to the
DexWinHelpLaunchUrl() function will replace the content of this browser
window.

Examples The following C# example shows a portion of the code that runs when the user
clicks the Help button in the form for the Estimate Freight sample. The
DexRuntimeGetClientType() function is used to ensure that code runs on only the
web client. The URL for the help content is assembled, including the server path,
help folder, and HTML file to display. The DexWinHelpLaunchURL() is used to
display the help content.

if (Dynamics.Forms.SyVisualStudioHelper.Functions.DexRuntimeGetClientType.
Invoke() == 2)
{
// Web client

// Is a different web client help server being used?


string server = Dynamics.Forms.SyVisualStudioHelper.Functions.
DexDefaultsRead.Invoke("WebClientHelpServer",2);

// Help folder
string helpFolder = "Help";

// File to access
string helpFile = "EstimateFreight.htm";

// Full URL to access


string url = server + "/" + helpFolder + "/" + helpFile;

// Launch the help


Dynamics.Forms.SyVisualStudioHelper.Functions.DexWinHelpLaunchUrl.
Invoke(url);
}

PROGRAMMERS GUIDE 103


The following Visual Basic example shows a portion of the code that runs when the
user clicks the Help button in the form for the Estimate Freight sample. The
DexRuntimeGetClientType() function is used to ensure that code runs on only the
web client. The URL for the help content is assembled, including the server path,
help folder, and HTML file to display. The DexWinHelpLaunchURL() is used to
display the help content.

If Dynamics.Forms.SyVisualStudioHelper.Functions.DexRuntimeGetClientType _
.Invoke() = 1 Then

' Web client

' Is a different web client help server being used?


Dim server As String = Dynamics.Forms.SyVisualStudioHelper.Functions _
.DexDefaultsRead().Invoke("WebClientHelpServer", 2)

' Help folder


Dim helpFolder As String = "Help"

' File to access


Dim helpFile As String = "EstimateFreight.htm"

' Full URL to access


Dim url As String = server + "/" + helpFolder + "/" + helpFile

' Launch the help


Dynamics.Forms.SyVisualStudioHelper.Functions.DexWinHelpLaunchUrl _
.Invoke(url)
End If

104 P R O G R A M M E R S G U I D E
PART 3: WEB CLIENT
Part 3: Web Client
This portion of the documentation describes how you can develop a Visual Studio
Tools integration that works with the Microsoft Dynamics GP web client. The
following topics are discussed:

Chapter 16, Web Client Overview, describes what additional steps you need
to take so that your Visual Studio Tools integration can work on the Microsoft
Dynamics GP web client.

Chapter 17, Dynamic Rendering, explains how to use dynamic rendering for
the Microsoft Dynamics GP web client.

Chapter 18, Custom Rendering, explains how to use custom rendering for the
Microsoft Dynamics GP web client.

Chapter 19, Developing for the Web Client, describes development


techniques that you will use when creating a Visual Studio Tools integration
that works with the Microsoft Dynamics GP web client.

106 P R O G R A M M E R S G U I D E
Chapter 16: Web Client Overview
When you develop an integrating application with Visual Studio Tools, you must
do some additional development work so that the integration will work on the
Microsoft Dynamics GP web client. The following sections introduce the steps you
need to take to support the web client.

Enabling integrations for the web client


Form rendering in the web client
Code for the web client

Enabling integrations for the web client


In most cases, additional development work and testing are needed so that a Visual
Studio Tools integration will work properly for the Microsoft Dynamics GP web
client. For this reason, Visual Studio Tools integrations are not loaded by default for
the web client. To have an integration load on the Microsoft Dynamics GP web
client, you must add the SupportedDexPlatforms attribute to the class that
implements the IDexterityAddIn interface to indicate that the integration works for
the web client.

When you enable a Visual Studio Tools integration to work on the web client, be sure that
you thoroughly test it to be sure that it is working properly.

Enabling a C# integration
The following example shows how to enable a C# integration for both the desktop
client and the web client. The SupportedDexPlatforms attribute takes one
parameter that indicates which platform or platforms are supported by the
integration. In this example, the logical-or operation is used to indicate that both the
desktop client and the web client are supported.

namespace CSharpSample
{
[SupportedDexPlatforms(DexPlatforms.DesktopClient |
DexPlatforms.WebClient)]
public class GPAddIn : IDexterityAddIn
{
// IDexterityAddIn interface

public void Initialize()


{
}
}
}

Enabling a Visual Basic integration


The following example shows how to enable a Visual Basic integration for both the
desktop client and the web client. The SupportedDexPlatforms attribute takes one
parameter that indicates which platform or platforms are supported by the
integration. In this example, the logical-or operation is used to indicate that both the
desktop client and the web client are supported.

PROGRAMMERS GUIDE 107


PA RT 3 W E B C L I E N T

<SupportedDexPlatforms(DexPlatforms.DesktopClient Or DexPlatforms.WebClient)>
Public Class GPAddIn
Implements IDexterityAddIn

' IDexterityAddIn interface

Sub Initialize() Implements IDexterityAddIn.Initialize

End Sub

End Class

Form rendering in the web client


To be displayed in the Microsoft Dynamics GP web client, each form in your Visual
Studio Tools integration must be rendered as a Silverlight form. There are two
techniques that are used to render the .NET form: dynamic rendering and custom
rendering. It is the developers responsibility to indicate which type of rendering a
.NET form will use in the web client.

Dynamic rendering
With dynamic rendering, the Microsoft Dynamics GP web client automatically
creates and displays a Silverlight form, based on the definition of the .NET form in
the Visual Studio Tools integration. For dynamic rendering to work, the .NET form
must use controls only from the supported list. The supported controls are:

Button
CheckBox
ComboBox
GroupBox
Label
ListBox
RadioButton
TextBox

If a Visual Studio Tools integration uses controls that arent supported, those
controls wont be rendered in the Microsoft Dynamics GP web client. Refer to
Chapter 17, Dynamic Rendering, for detailed information using dynamic
rendering in your integration.

Custom rendering
You must use custom rendering when your Visual Studio Tools forms contain
controls that arent supported by dynamic rendering. With custom rendering, you
are responsible for creating the Silverlight form that displays in the web client. You
must also handle the messages that are sent between the Visual Studio Tools add-in
(running on the server) and the Silverlight application (running in the web client).
Refer to Chapter 18, Custom Rendering, for detailed information.

Code for the web client


Most of the code that you write for a Visual Studio Tools integration designed for
the desktop client will work in the web client without needing any changes.
However, there are some areas that will require changes to work correctly in the
web client.

108 P R O G R A M M E R S G U I D E
C H A P T E R 1 6 W EB C L I E N T O V E R V I E W

For example, modal dialogs in a typical Visual Studio Tools integration may not
work on the web client. Typically, the MessageBox class from the .NET framework
is used to display modal dialogs. However, this class isnt supported by the
Microsoft Dynamics GP web client. The common solution is to replace calls to the
MessageBox class with calls to helper functions, like DexAsk() or DexError(), in the
Dynamics dictionary.

In some cases, you may have one set of code that runs on the desktop client, and
another set of code that runs on the web client. You would use the
DexRuntimeGetClientType() function to determine which set of code to run.

Refer to Chapter 19, Developing for the Web Client, for detailed information
about common development issues you will encounter as you prepare your Visual
Studio Tools integration to work with the web client.

PROGRAMMERS GUIDE 109


110 P R O G R A M M E R S G U I D E
Chapter 17: Dynamic Rendering
Dynamic rendering is the simplest technique for implementing a Visual Studio
Tools form that works on the Microsoft Dynamics GP web client. With dynamic
rendering, the web client does the necessary work to display the Visual Studio
Tools form in the web client. It also handles the communication between the web
client machine and the web client server. Information about dynamic rendering is
contained in the following sections.

When to use dynamic rendering


Enabling dynamic rendering
Supported properties and events
Form and control reference

When to use dynamic rendering


To use dynamic rendering, your Visual Studio Tools form must use controls from
the supported list. The following controls are automatically rendered:

Button
CheckBox
ComboBox
GroupBox
Label
ListBox
RadioButton
TextBox

If the form uses controls that arent included in this list, those controls wont be
rendered on the form when it is displayed in the web client. In those cases, you
must use custom rendering. We recommend that you use dynamic rendering
whenever it can meet all of the needs of your Visual Studio Tools integration.

Enabling dynamic rendering


To enable dynamic rendering for a form, the form must derive from DexUIForm.
You must add the WCCompliantWindow attribute to the class that defines the
form. This attribute indicates that the form should be automatically rendered by the
web client. If this attribute isnt found on the form, the form will not be displayed in
the web client.

Enabling a form in C#
The following example shows how dynamic rendering is enabled for the
EstimateFreight form of the C# version of the Estimate Freight sample integration.
The WCCompliantWindow attribute takes one boolean parameter that indicates
whether dynamic rendering is supported for the form.

namespace EstimateFreight
{
[WCCompliantWindow(true)]
public partial class EstimateFreight : DexUIForm
{

PROGRAMMERS GUIDE 111


PA RT 3 W E B C L I E N T

Enabling a form in Visual Basic


The following example shows how dynamic rendering is enabled for the
EstimateFreight form of the Visual Basic version of the Estimate Freight sample
integration. The WCCompliantWindow attribute takes one boolean parameter that
indicates whether dynamic rendering is supported for the form.

<WCCompliantWindow(True)>
Public Class EstimateFreightForm
Inherits DexUIForm

Supported properties and events


Forms and controls in a .NET application have an extensive set of properties and
events. Dynamic rendering for the Microsoft Dynamics GP web client supports a
subset of these properties and events for the form and supported controls. The
tables in the following section list the properties and events that are supported.

If your integrating application relies on properties or events that arent in the supported list,
you may have to re-work your integration to get the desired functionality for the web client.

Property support
The properties for the .NET form and controls are accessed in three situations
during the lifetime of the form or control:

At the time the form or control is created. The values of supported properties
are transferred from the server to the Silverlight form on the web client.

When the property for the form or control is updated on the server. For some of
the supported properties, the property value is transferred from the server to
the Silverlight form on the web client.

When the property for the form or control is updated on the web client. For a
limited number of the supported properties, the property value is transferred
from the Silverlight form to the server.

Event support
The supported events for the .NET form and controls are accessed in two situations
during the lifetime of the form or control:

When the event occurs on the server. The event may be invoked on the
Silverlight form on the web client.

When the event occurs on the web client. The event may be invoked on the
server.

Form and control reference


The following tables list the properties and events that are supported by dynamic
rendering in the Microsoft Dynamics GP web client. An X in the column indicates
that the property or event is supported for the situation indicated.

112 P R O G R A M M E R S G U I D E
C H A P T E R 1 7 D Y N A M I C R E N D E R I N G

Form
The following properties are supported for forms:

Property Creation Changed on Server Changed on Client


(Server to Client) (Server to Client) (Client to Server)
Name X
AutoSetDexColor X
BackColor X X
ControlArea X
ControlBox X
Location X X
MaximizeBox X
MinimizeBox X
ShowIcon X
Size X X X
StatusArea X
Text X X
WindowState X X X

The following events are supported for forms:

Event Server Initiated Client Initiated


(Server to Client) (Client to Server)
Activated X X
Closed X
Closing X

Button
The following properties are supported for buttons:

Property Creation Changed on Server Changed on Client


(Server to Client) (Server to Client) (Client to Server)
Name X
AutoSetDexColor X
BackColor X X
ButtonType X X
Enabled X X
ForeColor X X
ImageAlign X X
Location X X
Size X X
TabIndex X X
TabStop X X
Text X X
TextAlign X X
TextImageRelation X X
Visible X X

PROGRAMMERS GUIDE 113


PA RT 3 W E B C L I E N T

The following events are supported for buttons:

Event Server Initiated Client Initiated


(Server to Client) (Client to Server)
Click X

CheckBox
The following properties are supported for check boxes:

Property Creation Changed on Server Changed on Client


(Server to Client) (Server to Client) (Client to Server)
Name X
BackColor X X
CheckedState X X X
Enabled X X
ForeColor X X
Location X X
Size X X
TabIndex X X
TabStop X X
Text X X
ThreeState X X
Visible X X

ComboBox
The following properties are supported for combo boxes:

Property Creation Changed on Server Changed on Client


(Server to Client) (Server to Client) (Client to Server)
Name X
AutoSetDexColors X
BackColor X X
DropDownStyle X X
Enabled X X
ForeColor X X
Items X X
Location X X
Size X X
TabIndex X X
TabStop X X
Text X X X
Visible X X

114 P R O G R A M M E R S G U I D E
C H A P T E R 1 7 D Y N A M I C R E N D E R I N G

GroupBox
The following properties are supported for group boxes:

Property Creation Changed on Server Changed on Client


(Server to Client) (Server to Client) (Client to Server)
Name X
BackColor X X
Enabled X X
ForeColor X X
Location X X
Size X X
TabIndex X X
TabStop X X
Text X X
Visible X X

Label
The following properties are supported for labels:

Property Creation Changed on Server Changed on Client


(Server to Client) (Server to Client) (Client to Server)
Name X
BackColor X X
Enabled X X
ForeColor X X
LinkField X
Location X X
Size X X
TabIndex X X
TabStop X X
Text X X
Visible X X

ListBox
The following properties are supported for list boxes:

Property Creation Changed on Server Changed on Client


(Server to Client) (Server to Client) (Client to Server)
Name X
BackColor X X
Enabled X X
ForeColor X X
Items X X
Location X X
SelectedIndex X X X
SelectedIndices X X X
Size X X
TabIndex X X
TabStop X X
Visible X X

PROGRAMMERS GUIDE 115


PA RT 3 W E B C L I E N T

RadioButton
The following properties are supported for radio buttons:

Property Creation Changed on Server Changed on Client


(Server to Client) (Server to Client) (Client to Server)
Name X
BackColor X X
Checked X X X
Enabled X X
ForeColor X X
Location X X
Size X X
TabIndex X X
TabStop X X
Text X X
Visible X X

TextBox
The following properties are supported for text boxes:

Property Creation Changed on Server Changed on Client


(Server to Client) (Server to Client) (Client to Server)
Name X
AutoSetDexColors X
BackColor X X
Enabled X X
ForeColor X X
Location X X
Multiline X X
PasswordChar X
Size X X
TabIndex X X
TabStop X X
Text X X X
Visible X X
WordWrap X X

116 P R O G R A M M E R S G U I D E
Chapter 18: Custom Rendering
You will use custom rendering when your Visual Studio Tools integration has
controls that are not supported by dynamic rendering. Custom rendering is a more
flexible, but also more complex way to implement a Visual Studio Tools integration
that works with the web client. For this reason, we recommend that you use
dynamic rendering whenever possible.

In addition to the assembly (.dll) you normally create for a Visual Studio Tools add-
in, you must also create a Silverlight .xap file that defines the forms that your
integration is displaying in the web client. You are also responsible for all of the
messaging that is sent between your Silverlight windows that appear in the web
client and your Visual Studio Tools add-in that is running on the server.

Before you implement custom rendering in your Visual Studio Tools project, we recommend
that you have the add-in working correctly in the Microsoft Dynamics GP desktop client.

Information about custom rendering is contained in the following sections:

Implementing the custom messaging interface


Requirements for developing with Silverlight
Silverlight project
Adding a Silverlight window to the project
Sending messages
Receiving messages
Message examples
Session recovery
Message rejection
Writing to the trace log
Building and deploying the Silverlight component

Implementing the custom messaging interface


In your Visual Studio Tools add-in that runs on the server, you will implement
methods for the IWCCustomMessagingAddIn interface. These additional methods
provide support for the messaging that is used for custom rendering.

Implementing the interface


To implement this interface, use the following procedure.

1. Open the solution for your Visual Studio Tools integration.


If it isnt already open, use Visual Studio to open the solution for your add-in.

2. Open the file that implements the IDexterityAddIn interface.


Typically, this will be the GpAddIn.cs or GpAddIn.vb file for a standard Visual
Studio Tools project.

3. Add code for the IWCCustomMessagingAddIn interface.


For a C# integration, add the IWCCustomMessagingAddIn interface to the
same class that implements the IDexterityAddIn interface. This is shown in the
following illustration:

PROGRAMMERS GUIDE 117


PA RT 3 W E B C L I E N T

After you have added the interface name, right-click the interface name in the
code editor, point to Implement Interface, and then choose Implement Interface.
The methods for the interface are automatically added to the class. This is
shown in the following illustration.

For a Visual Basic integration, add the IWCustomMessagingAddIn interface to


the Implements statement for the same class that implements the
IDexterityAddIn interface. When you press Enter at the end of the Implements
statement, the methods for the interface are automatically added to the class.
This is shown in the following illustration.

118 P R O G R A M M E R S G U I D E
C H A P T E R 1 8 C U S T O M R E N D E R I N G

Adding code to the methods


You will add code to the methods for the interface as you develop the integration.

First, you will initialize messaging, which is described later in this section.

Later in the development process you will add code to the ProcessMessage()
method to handle messages that the add-in receives from the web client.
Information about this is found in Receiving messages on page 126.

Near the end of the development process you will add code to the Recover()
method, which is responsible for restoring the state of the Visual Studio Tools
add-in when a user reconnects to a web client session. Information about
implementing this method is found in Session recovery on page 127.

Initializing messaging
The first method to implement in the IWCCustomMessagingAddIn interface is
InitializeMessaging(). This method establishes the communication that allows the
server-side Visual Studio Tools add-in to send and receive messages from the
Silverlight component.

If you are using C# for your integration, begin by adding a static variable to the
class that contains the InitializeMessaging() method. This static variable will store
the proxy that is used to send and receive messages. The following example shows
the static variable for the proxy:

// The proxy for communication between the web client and the server
public static IWCCustomMessagingProxy proxy;

In the InitializeMessaging() method, add the following code to create an instance


of the proxy:

public void InitializeMessaging(IWCCustomMessagingProxy proxy)


{
GPAddIn.proxy = proxy;
}

PROGRAMMERS GUIDE 119


PA RT 3 W E B C L I E N T

If you are using Visual Basic for your integration, the code is similar. Begin by
adding a public shared variable to the class that contains the InitializeMessaging()
method. The following example shows the shared variable for the proxy:

Public Shared proxy As IWCCustomMessagingProxy

In the IntializeMessaging() method, add the following code to create an instance of


the proxy:

Public Sub InitializeMessaging(proxy As


Microsoft.Dexterity.Bridge.IWCCustomMessagingProxy) Implements
Microsoft.Dexterity.Bridge.IWCCustomMessagingAddIn.InitializeMessaging

GPAddIn.proxy = proxy

End Sub

Requirements for developing with Silverlight


To develop the Silverlight component for a Visual Studio Tools integration that
supports custom rendering, you must have several Silverlight components
installed. The following is the list of the components that are required, and
information about how to obtain them.

Silverlight 5 SDK
This component provides libraries and tools for developing Silverlight 5
applications. You can download this component from the following location:

http://www.microsoft.com/en-us/download/details.aspx?id=28359

Silverlight 5 Tools for Visual Studio 2010


If you are using Visual Studio 2010 to develop your Visual Studio Tools integration,
you need the Silverlight 5 Tools for Visual Studio 2010. You can download this
component from the following location:

http://www.microsoft.com/en-us/download/details.aspx?id=28358

Silverlight 5 Toolkit
The Silverlight Toolkit is required to use the graphic designer in Visual Studio to
design the layout of the Silverlight application. You can download this component
from the following location:

http://silverlight.codeplex.com/releases/view/78435

Silverlight 5 Developer Runtime


To view the Silverlight project in Visual Studio 2010, you must have the Silverlight 5
Developer Runtime. To install this runtime on your development machine, you will
need to uninstall the standard Silverlight 5 runtime first. You can download the
Silverlight 5 Developer Runtime from the following location:

http://go.microsoft.com/fwlink/?LinkId=146060

120 P R O G R A M M E R S G U I D E
C H A P T E R 1 8 C U S T O M R E N D E R I N G

Silverlight project
A separate project is required for the Silverlight component of a Visual Studio Tools
integration that uses custom rendering. You can include this project in an existing
solution for your Visual Studio Tools integration, or you can use a separate
solution.

Creating the Web Client add-in project


Use the following procedure to create a new Visual Studio project for the Silverlight
component of a Microsoft Dynamics GP add-in.

1. Start Visual Studio.


If it isnt already running, start Visual Studio.

2. Create a new project.


In the File menu, point to New and choose Project.

3. Select the project type.


Choose either a Visual Basic project or a Visual C# project. Under the type you
have selected, choose Dynamics GP.

4. Choose the Microsoft Dynamics GP Web Client Add-in template.


In the list of available templates, choose the Microsoft Dynamics GP Web Client
Add-in project template.

If the Microsoft Dynamics GP templates are not listed, you may need to register them
manually. Refer to Template registration on page 8 for details about doing this.

5. Specify the name and location of the project.


Click OK to create the project.

PROGRAMMERS GUIDE 121


PA RT 3 W E B C L I E N T

Referencing web client assemblies


The Silverlight project must reference the following assemblies that are part of the
web client:

Microsoft.Dynamics.GP.Web.Silverlight
Microsoft.Dynamics.GP.Web.UI.Silverlight
Microsoft.Dynamics.GP.Web.UI.Silverlight.Controls

These assemblies are found in the Microsoft.Dynamics.GP.Web.Silverlight.xap file


that is located in the ClientBin folder of the Microsoft Dynamics GP installation
on the web client server machine. To reference these assemblies in your Silverlight
project, you must extract them from the .xap file and then re-reference them in the
Silverlight project. To do this, complete the following procedure.

1. Locate the Microsoft.Dynamics.GP.Web.Silverlight.xap file.


This file is found in the ClientBin folder of the Microsoft Dynamics GP
installation on the web client server machine.

2. Make a copy of the file.


Copy the Microsoft.Dynamics.GP.Web.Silverlight.xap file to a location where
you have write privileges.

3. Add the .zip file extension.


Add the .zip file extension to the copy of the .xap file so that the file has the
name Microsoft.Dynamics.GP.Web.Silverlight.xap.zip.

4. Open the .zip archive.


You will see the assemblies that are contained in the .xap file.

5. Copy the needed assemblies from the .zip archive.


Copy the following assemblies from the archive into a location where you will
be able to access them from the Silverlight project:

Microsoft.Dynamics.GP.Web.Silverlight
Microsoft.Dynamics.GP.Web.UI.Silverlight
Microsoft.Dynamics.GP.Web.UI.Silverlight.Controls

122 P R O G R A M M E R S G U I D E
C H A P T E R 1 8 C U S T O M R E N D E R I N G

6. Re-reference the assemblies in the Silverlight project.


When you view the references for the Silverlight project, you will see that the
three assemblies are referenced, but that the reference path is incorrect. You
must delete the references for these three assemblies, and then re-add the
references to the three assemblies that you just extracted from the .zip archive.

7. Set the Copy Local property for each assembly to False.


In Visual Studio, you must set the Copy Local property to False for each of the
three referenced assemblies. This is important, because it prevents an additional
copy of the assemblies from being included in the .xap file for your Visual
Studio Tools solution.

If there are multiple copies of these assemblies in the .xap files for the web client, the web
client will not work properly.

Adding a Silverlight window to the project


When you are using custom rendering for your integration, you must create the
Silverlight window that is displayed on the web client. You also create the entire
layout for the window. To make this process easier, a Microsoft Dynamics GP
Silverlight Window can be added to your Silverlight project. To add one of these
windows to your project, complete the following procedure.

1. Add a new item.


In Visual Studio, choose Add New Item from the Project menu.

2. Select the Microsoft Dynamics GP Silverlight Window.


In the list of template, choose a Microsoft Dynamics GP Silverlight Window.

3. Name the new window.


Give the window a name that is appropriate for how it will be used.

4. Add the new window.


Click Add to add the new window to the project.

PROGRAMMERS GUIDE 123


PA RT 3 W E B C L I E N T

5. Specify the window properties.


Set the necessary properties for the new window. You will want to set the
following properties:

Title This property specifies the title that is displayed in the window.

Height This is the height of the window. It should be explicitly set, and
should match the value of the DesignHeight property.

Width This is the width of the window. It should be explicitly set, and should
match the value of the DesignWidth property.

6. Create the layout for the window.


Using standard Silverlight design practices, create the layout for the window.

Sending messages
Messages sent between the web client and the server are used to keep the Silverlight
application synchronized with the Visual Studio Tools add-in that is running on the
server. With the custom rendering, you are responsible for all of the messages that
are sent between the web client and the server for your add-in.

How messages are used


The messages that keep the Silverlight application synchronized with the Visual
Studio Tools add-in are used in several ways:

Some messages will contain the data that is retreived by the add-in running on
the server and then sent to the web client to be displayed in the Silverlight
windows.

Some messages will contain data that is entered by the user on the web client,
and then transferred to the server to be processed by the add-in.

Some messages indicate actions to be performed within the integration, such as


opening or closing a window.

Some messages will indicate actions the user performed in the web client, such
as clicking a button in a window.

For a specific example of the messages used in an integration, see Chapter 35, Salesperson
Analysis, which lists the messages that the Salesperson Analysis sample application uses to
implement custom rendering.

Message structure
Each message that is sent between the web client and server has the type
WCVstCustomMessage. It has the following parameters:

Source This is a string value that must contain the namespace and class of the
sender.

Destination This is a string value that must contain the namespace and class for
the message processor method in the destination.

124 P R O G R A M M E R S G U I D E
C H A P T E R 1 8 C U S T O M R E N D E R I N G

Description This is a string that contains a description of the message. It is used


to help identify the message. In some cases, it can contain the information to be sent
by the message.

Data This is a byte stream value that contains the data for the message. Typically,
this is a serialized value. The contents of the byte stream is automatically
compressed to make the data transfer more efficient.

Message proxy
A message proxy is used to send messages between the Silverlight code that is
running on the web client and the Visual Studio Tools add-in that is running on the
server. In the Visual Studio Tools add-in, you added code to create this proxy when
you implemented support for custom messages as described in Implementing the
custom messaging interface on page 117. The Microsoft Dynamics GP Web Client
(Silverlight) project template already contains code that implements the message
proxy.

The proxy has two methods that are used to send messages. The SendMessage()
method sends a single message from the web client to the server, or from the server
to the web client. The SendMessages() method sends a collection of messages in a
single operation. In some cases, its more efficient to send messages as a collection,
rather than sending several messages separately. For example, if youre sending a
large number of fields to be displayed in a window, it may be more efficient to send
all of the fields at one time using the SendMessages() method.

Its important that your Visual Studio Tools add-in uses the message proxy only
when it is being used in for the web client. If you make calls to the message proxy
and the desktop client is being used, runtime errors will occur. We recommend that
you use the DexRuntimeGetClientType() helper function to determine whether
the web client is being used before you send messages with the message proxy.

The Source and Destination properties are very important when sending messages.
The values of these properties are used by Microsoft Dynamics GP to direct the
message to the correct Visual Studio Tools add-in or Silverlight application. The
combination of the root namespace and the class define a unique indentifier,
helping to ensure that message can be routed properly. The following table lists the
namespace and class that contains the ProcessMessage() method for the Visual
Stuio Tools add-in and the Silverlight component of the Salesperson Analysis
sample. It also lists the Source and Destination values that are used when sending
messages from the component. Notice the period (.) that is included to separate the
namespace and class.

Visual Studio Tools add-in Silverlight component


Namespace SalespersonAnalysis SalespersonAnalysisSL
Class GPAddIn GPWCAddIn
Source SalespersonAnalysis.GPAddIn SalespersonAnalysisSL.GPWCAddIn
Destination SalespersonAnalysisSL.GPWCAddIn SalespersonAnalysis.GPAddIn

PROGRAMMERS GUIDE 125


PA RT 3 W E B C L I E N T

Receiving messages
The ProcessMessage() method is called automatically when a message is received
by the Visual Studio Tools add-in or the Silverlight component. Typically, your
code will examine the Description property from the message that was received to
determine what action your code needs to take. If the Data property is used to send
additional data with the message, your code must convert the data from a byte
stream to a format that can be used by your integration.

If messages are not being received by either the Silverlight application on the web client or
the Visual Studio Tools add-in on the server, be sure that the Source and Destination
parameters are being set correctly.

Message examples
The following examples show how messages are sent between the Visual Studio
Tools add-in and the Silverlight code running on the web client. These examples are
messages used for the Salesperson Analysis sample.

Sending a string value from the server


This example shows a message that sends a string value for the Salesperson ID from
the Visual Studio Tools add-in on the server to the Silverlight application running
on the client. The first line of the example checks a variable that was set based on
whether the web client is being used. Notice how the value was encoded so that it
can be sent as a byte array.

The following code is the C# version of this example.


if (IsWebClient == true)
{
// Send the selected salesperson ID to the web client
// Convert the string value to encoded bytes to send
byte[] bytedata;
System.Text.UTF8Encoding val = new UTF8Encoding();
bytedata = val.GetBytes(SalespersonMaintenanceForm.RmSalesperson.
SalespersonId.Value);

// Send the byte data to the web client


proxy.SendMessage(new WCVstCustomMessage("SalespersonAnalysis.GPAddIn",
"SalespersonAnalysisSL.GPWCAddIn", "TransferSalespersonID", bytedata));
}

The following code is the Visual Basic version of this example.


If IsWebClient = True Then
' Send the selected salesperson ID to the web client
' Convert the string value to encoded bytes to send
Dim bytedata() As Byte
Dim val As System.Text.UTF8Encoding = New UTF8Encoding()
bytedata = val.GetBytes(SalespersonMaintenanceForm.RmSalesperson. _
SalespersonId.Value)

' Send the byte data to the web client


proxy.SendMessage(New WCVstCustomMessage("SalespersonAnalysis.GPAddIn", _
"SalespersonAnalysisSL.GPWCAddIn", "TransferSalespersonID", bytedata))
End If

126 P R O G R A M M E R S G U I D E
C H A P T E R 1 8 C U S T O M R E N D E R I N G

Receiving a string value on the web client


This example shows how the string message sent from the server is processed in the
Silverlight code on the web client. Notice how the Description property of the
message is examine to determine whether the message should be processed. The
byte stream from the Data property is converted back into a string value, and the
string is used to set the value of a text box in the Silverlight application.

The following code is the C# version of this example.

public void ProcessMessage(WCVstCustomMessage message)


{
if (message.Description == "TransferSalespersonID")
{
// Convert the byte array data back into a string
string s = System.Text.Encoding.UTF8.GetString(message.Data, 0,
message.Data.Length);

// Set the window field value


saWindow.textBoxSalespersonID.Text = s;
}
}

The following code is the Visual Basic version of this example.


Public Sub ProcessMessage(message As WCVstCustomMessage) Implements
IWCCustomAddIn.ProcessMessage

If message.Description = "TransferSalespersonID" Then


' Convert the byte array data back into a string
Dim s As String = System.Text.Encoding.UTF8.GetString(message.Data, _
0, message.Data.Length)

' Set the window field value


saWindow.textBoxSalespersonID.Text = s
End If
End If

Session recovery
When a Microsoft Dynamics GP web client session is disconnected, the session
remains active on the server. The user can reconnect to the session and restore the
condition of the windows that were open. As part of the session restore process, the
Recover() method for your Visual Studio Tools add-in on the server is called. We
recommend that you implement the Recover() method so that your Visual Studio
Tools integration participates in the restore action.

The code that you include in the Recover() method must send messages to the
Silverlight application running on the web client to restore the application state so
that it matches the condition of the add-in on the server. When restoring the
application on the web client, consider things like the following:

Which Silverlight windows are open for your integration

Whether the Silverlight window are visible or hidden

What data values appear in the controls in each window

Have specific selections been made in any of the controls in each window

PROGRAMMERS GUIDE 127


PA RT 3 W E B C L I E N T

In most cases, you will need to implement specific messages that are used only for
the Recover() method. For example, in the normal course of development, you will
implement messages that send user selections and input from the Silverlight
application on the web client to the Visual Studio Tools add-in on the server. This
seems logical, because the user is providing input on the web client that needs to be
transferred to the server. When a restore action is performed, these same values
must be sent from the Visual Studio Tools add-in on the server to the Silverlight
application on the web client. Thats why additional messages are required.

The following C# example is the Recover() method for the Salesperson Analysis
sample add-in that runs on the server. Four messages are used to restore the state of
the Silverlight application on the web client. The first message opens the
Salesperson Analysis form. The second message reloads the data for the window.
The third message sets the selection in the data grid. The fourth message displays
the window if it had previously been visible.
public void Recover()
{
// Code for recovering a session

// Is the Salesperson Maintenance form open?


if (SalespersonMaintenanceForm.IsOpen == true)
{
// Open the Salesperson Analysis form
proxy.SendMessage(new WCVstCustomMessage(this.GetType().FullName,
"SalespersonAnalysisSL.GPWCAddIn", "OpenSalespersonAnalysisForm",
new byte[0]));

// Load the data


SalespersonId_Change(null, null);

// Set the selection, if there is one.


if(GPAddIn.SalespersonAnalysisForm.customerListView.
SelectedIndices.Count != 0)
{
// Get the first item in the list, since this is a single-select
// list view
int selection = GPAddIn.SalespersonAnalysisForm.customerListView.
SelectedIndices[0];

// Convert the string value to encoded bytes to send


byte[] bytedata;
System.Text.UTF8Encoding val = new UTF8Encoding();
bytedata = val.GetBytes(selection.ToString());

// Send the selection


proxy.SendMessage(new WCVstCustomMessage(this.GetType().FullName,
"SalespersonAnalysisSL.GPWCAddIn", "SetCustomerSelection",
bytedata));
}

// Show the form?


if (GPAddIn.SalespersonAnalysisForm.Visible == true)
{
proxy.SendMessage(new WCVstCustomMessage("SalespersonAnalysis.
GPAddIn","SalespersonAnalysisSL.GPWCAddIn",
"ShowSalespersonAnalysisForm", new byte[0]));

128 P R O G R A M M E R S G U I D E
C H A P T E R 1 8 C U S T O M R E N D E R I N G

}
}
}

Message rejection
When your Silverlight application that is running on the web client sends a message
to the server, such as a user updating the value of a control, there is a remote
possibility that the message will be rejected by the server. A message could be
rejected if the server is in a state that doesnt allow it to process messages. When the
message is rejected, the message is sent back to the Silverlight application where it
can be handled by the Revert() method that you implement.

When a message is rejected by the server, the web client will be out of synch with
the status of the application on the server. When the Revert() method receives the
message that was rejected by the server, the code in the method must set the state of
the Silverlight application back to the way it was before the message had been sent.

To be able to restore the previous state of the application, your Silverlight


application will need to keep track of the value or values as they existed before you
sent the message to update the server. For example, if you sent a message to update
the server when the user changes a value in a text box control, you should keep
track of the previous value of the text box control. If the message is rejected, you can
restore the text box control to its previous value.

The following C# example shows the SelectionChanged event for the data grid
control in the Silverlight component of the Salesperson Analysis sample. This event
occurs when the user selects a row in the data grid. Notice how the previous
selection is stored so that it can be used if needed.

private void dataGrid1_SelectionChanged(object sender,


SelectionChangedEventArgs e)
{
// The user changed the selected customer. Send the updated selection
// back to the server.

// Store the object that indicates the previous selection, in case the
// message is rejected
if (e.RemovedItems.Count != 0)
{
// Save the previous selection
GPWCAddIn.prevSelection = e.RemovedItems;
}
else
{
// No item was previously selected
GPWCAddIn.prevSelection = null;
}

// Get the selection


int selection = GPWCAddIn.saWindow.dataGrid1.SelectedIndex;

// Convert the string value to encoded bytes to send


byte[] bytedata;
System.Text.UTF8Encoding val = new UTF8Encoding();
bytedata = val.GetBytes(selection.ToString());

PROGRAMMERS GUIDE 129


PA RT 3 W E B C L I E N T

// Send the value to the server


GPWCAddIn.Proxy.SendMessage(new WCVstCustomMessage(
"SalespersonAnalysisSL.GPWCAddIn", "SalespersonAnalysis.GPAddIn",
"SetSelectedCustomer", bytedata));
}

The following C# example shows the Revert() method for the Silverlight component
of the Salesperson Analysis sample. If the SetSelectedCustomer message was
rejected by the server, the previous value for the data grid is restored.

void IWCCustomAddIn.Revert(WCVstCustomMessage message)


{
// A message was rejected by the server. Examine the message returned,
// and if necessary, revert the Silverlight application back to the way it
// was before the message was sent.

// The user selected a customer, but the message was rejected by the
// server.
if (message.Description == "SetSelectedCustomer")
{
// Reset the selection back to the previous value
if (GPWCAddIn.prevSelection != null)
{
saWindow.dataGrid1.SelectedItem = GPWCAddIn.prevSelection[0];
}
else
{
saWindow.dataGrid1.SelectedIndex = (-1);
}
}
}

Writing to the trace log


A Visual Studio Tools integration that is being used with the Microsoft Dynamics
GP web client can write messages to the web client runtime log. The content of these
messages can help when troubleshooting the integration. Only the Visual Studio
Tools add-in running on the server can write messages to the log. The Silverlight
component running on the web client cannot.

To write to the web client runtime log, use the TraceInformation() method for the
message proxy that you added to your Visual Studio Tools add-in. This method has
a single string parameter that will be written into the log. The following C# example
shows a message that was written to the log.
if (IsWebClient == true)
{
// Send the message to the web client to open the form
proxy.SendMessage(new WCVstCustomMessage(this.GetType().FullName,
"SalespersonAnalysisSL.GPWCAddIn", "OpenSalespersonAnalysisForm",
new byte[0]));

// Write to the trace log


proxy.TraceInformation("Sending the OpenSalespersonAnalysisForm
message");
}

130 P R O G R A M M E R S G U I D E
C H A P T E R 1 8 C U S T O M R E N D E R I N G

When the runtime log for the web client is examined, the message will be included
as shown in the following portion of the log:

10:47:30.191 | TryReleaseOutgoingMessages :: Reason:[Unknown]


10:47:30.191 | VST:{Sending the OpenSalespersonAnalysisForm message}
10:47:30.191 | #GetDexServerMessages [End] :: Reason:[NonZeroMessageCount]

Building and deploying the Silverlight component


After most of the code has been added to the Silverlight component for your Visual
Studio Tools integration, you will want to build and deploy it so it can be tested.
The build process creates a .xap file that you will deploy to a web client installation.

Web client extension information


In the Microsoft Dynamics GP web client, you can view information about the
Silverlight components that have been loaded. To do this, choose About Microsoft
Dynamics GP from the Help menu. In the Additional menu for the About Box,
choose About Web Client. A window listing the client extensions will be displayed.

We recommend that you add the ExtensionInformation attribute to the


GPWCAddIn class for the Silverlight component of your integration to configure
the name that is displayed in this window. The following C# example shows how
the ExtensionInformation attribute is used to specify the name for the Silverlight
component of the Salesperson Analysis sample:

namespace SalespersonAnalysisSL
{
[ExtensionInformation("Salesperson Analysis")]
public class GPWCAddIn : IWCCustomAddIn
{

PROGRAMMERS GUIDE 131


PA RT 3 W E B C L I E N T

Optimizing the .xap file size


When you build the Silverlight component (.xap file) for your Visual Studio Tools
integration, all of the assemblies that you referenced in your project that dont have
the CopyLocal property set to False will be included in the .xap file. You can
optimize the size of the .xap file by not include assemblies that are already included
in the .xap file used by the Microsoft Dynamics GP web client. A smaller .xap file
will load more quickly on each web client machine.

Using the technique described in Referencing web client assemblies on page 122, you
can view the set of assemblies that are included in the .xap file for the Microsoft
Dynamics GP web client. Your project doesnt need to include any of the assemblies
that you see in the Microsoft Dynamics GP web client .xap file.

Building and deploying


To build the Silverlight component, complete the following procedure:

1. Set the solution configuration.


If youre building a test version of the integration, set the solution configuration
to Debug. If you are building a final version of the integration, set the
solution configuration to Release.

2. Build the solution.


Choose Build Solution from the Build menu.

3. Verify there were no build warnings.


If there were build warnings, fix them and build again.

4. Copy the .xap to the ClientBin folder.


Open the Debug or Release folder for your project and find the .xap file
that was built. Copy the .xap into the \WebClient\ClientBin folder in the
Microsoft Dynamics GP installation on the web client server.

Be sure that you have also copied the Visual Studio Tools assembly for your
integration into the AddIns folder for the Microsoft Dynamics GP installation
on the web client server.

5. Start the Microsoft Dynamics GP web client.


When Microsoft Dynamics GP web client starts, your Visual Studio Tools add-
in will be loaded on the server. The Silverlight .xap assembly will be transferred
to the web client machine and loaded into the browser. Verify that your
integration is working properly.

132 P R O G R A M M E R S G U I D E
Chapter 19: Developing for the Web Client
As you are developing Visual Studio Tools integrations that will be used on the web
client, there are some standard development practices that you should be aware of
and follow. The following sections discuss them:

Determining where code is running


Modal dialogs on the web client
Closing forms on the web client
Local file access
Debugging with the web client

Determining where code is running


As you are developing a Visual Studio Tools integration that will be used with the
Microsoft Dynamics GP web client, you will encounter cases where you will want
one block of code to run on the desktop client and a different block of code to run on
the web client. Use the DexRuntimeGetClientType() helper function to do this.

If you will be calling DexRuntimeGetClientType() frequently, consider calling it one time


in the Initialize method for your add-in, and then storing the result in a variable. This is
more efficient, and simplifies the code in your add-in.

As an example, the technique to display online help is different on the desktop


client and the web client. On the desktop client, an integrating application can make
a direct call to the HTML Help engine in Windows. But HTML Help isnt available
on the web client, so a different technique must be used. The following C# example
shows the code that runs when the user clicks the Help button in the form for the
Estimate Freight sample. The client type is determined, and the appropriate help
processing code is run.

private void buttonHelp_Click(object sender, EventArgs e)


{
// Help is processed differently, depending on whether it is being
// accessed from the desktop client or the web client.

if (Dynamics.Forms.SyVisualStudioHelper.Functions.
DexRuntimeGetClientType.Invoke() == 1)
{
// Desktop client
// Display a help file for this window
Help.ShowHelp(this, "EstimateFreight.chm");
}

if (Dynamics.Forms.SyVisualStudioHelper.Functions.
DexRuntimeGetClientType.Invoke() == 2)
{
// Web client
// Is a different web client help server being used?
string server = Dynamics.Forms.SyVisualStudioHelper.Functions.
DexDefaultsRead.Invoke("WebClientHelpServer",2);

// Help folder
string helpFolder = "Help";

PROGRAMMERS GUIDE 133


PA RT 3 W E B C L I E N T

// File to access
string helpFile = "EstimateFreight.htm";

// Full URL to access


string url = server + "/" + helpFolder + "/" + helpFile;

// Launch the help


Dynamics.Forms.SyVisualStudioHelper.Functions.DexWinHelpLaunchUrl.
Invoke(url);
}
}

Modal dialogs on the web client


In a Visual Studio Tools integration that works with the Microsoft Dynamics GP
desktop client, its common to use the MessageBox class from the .NET framework
to display modal dialogs. This class is not supported on the Microsoft Dynamics GP
web client. Instead, you should use calls to the appropriate helper functions in the
Dynamics dictionary to display modal dialogs. The following functions are
available to display modal dialogs:

DexAsk()
DexError()
DexWarning()
DexGetstring()

Closing forms on the web client


As you are coding your Visual Studio Tools integration, its important to watch how
you close forms you created. Always use the Close() method on the form class to
close the form. This method will send the appropriate messages between the web
client and server, and allow the form to be properly garbage-collected by the .NET
runtime.

Dont use methods like Dispose() to close a form in your integration, because you
will likely encounter errors in the web client. This happens because the form is
garbage-collected but the web client runtime engine doesnt know that the form has
been closed.

Local file access


When your Visual Studio Tools add-in is running on the Microsoft Dynamics GP
desktop client, it has access to any location in the local file system for which the user
has permissions. With the Microsoft Dynamics GP web client, a Visual Studio Tools
add-in running on the server has access to only the temporary folder for the current
web client session. If your Visual Studio Tools integration will run on the web
client, and will perform file operations such as writing to temporary files, it must do
these actions in this temporary location. To retrieve the temporyary file location for
a session, use the DexFileGetTempDirectory() helper function from the Dynamics
dictionary.

If you need to transfer a file from the temporary file location on the server to the
web client, you can use the DexFileLaunch() helper function. This function will
transfer the file from the server to the web client, allowing the user to select a
location where it can be saved. After the the file has been transferred, it can be
opened, printed, or have no action taken.

134 P R O G R A M M E R S G U I D E
C H A P T E R 1 9 D E V E L O P I N G F O R T H E W E B C L I E N T

Debugging with the web client


When you are developing a Visual Studio Tools integration that works with the
web client, you may want to debug code when user action is started from the web
client. The process is similar to debugging a Visual Studio Tools add-in for the
Microsoft Dynamics GP desktop client, which is described in Chapter 11,
Debugging.

There are two key differences when debugging with the web client:

When debugging the Visual Studio add-in, instead of attaching to the


Dynamics.exe process, you must attach the Visual Studio debugger to this
process:

Microsoft.Dynamics.GP.Web.Services.Runtime.Process.exe

Be sure that you are attaching to the process for the web client sesssion that you
are using for your testing.

If you are debugging the Silverlight application, you must attached to the
Internet Explorer instance (iexplore.exe) that you are using for the web client.

PROGRAMMERS GUIDE 135


136 P R O G R A M M E R S G U I D E
PART 4: RESOURCE REFERENCE
Part 4: Resource Reference
This portion of the documentation provides detailed information about each type of
resource you can access with Visual Studio Tools for Microsoft Dynamics GP. Each
resource has the following:

Information about accessing the resource


A list of methods
A list of properties
A list of events

The following resources are discussed:

Chapter 20, Forms, describes form resources.

Chapter 21, Windows, describes window resources.

Chapter 22, Scrolling Windows, describes scrolling window resources.

Chapter 23, Window Fields, describes window field resources.

Chapter 24, Tables, describes table resources.

Chapter 25, Table Fields, describes table field resources.

Chapter 26, Commands, describes command resources.

Chapter 27, Globals, describes global variable resources.

Chapter 28, Procedures, describes procedure resources.

Chapter 29, Functions, describes function resources.

Chapter 30, Composites, describes composite resources.

138 P R O G R A M M E R S G U I D E
Chapter 20: Forms
Forms are the basic resource of the Microsoft Dynamics GP application. They
provide the organization for the interface presented to the user. The following items
for forms are discussed:

Accessing forms
Form methods
Form properties
Form events

Accessing forms
Forms for an application dictionary are accessed through the dictionary class. This
class has a Forms property that provides access to the collection of forms in the
dictionary. The dictionary class for the application dictionary is located in the
following namespace:

Microsoft.Dexterity.Applications

For instance, to access the collection of forms in the Dynamics dictionary, use the
following syntax:

Microsoft.Dexterity.Applications.Dynamics.Forms

To access a specific form, such as the Sales Transaction Entry form (SopEntry), use
the following syntax:

Microsoft.Dexterity.Applications.Dynamics.Forms.SopEntry

Form methods
Forms provide the following methods:

AddMenuHandler()
Close()
Dispose()
Open()

AddMenuHandler()
The AddMenuHandler() method adds a menu item to the Additional menu that
appears in windows in Microsoft Dynamics GP. The menu item will be available
when the form is open. This method takes three parameters:

EventHandler The function that will be run when the menu item is chosen in
Microsoft Dynamics GP.

MenuItemName A string containing the text that will be displayed for the menu
item.

AcceleratorKey A string containing a single character that will be used as the


accelerator key for the menu item. Be sure this accelerator key does not conflict with
any existing accelerator keys. If you dont want an accelerator key, use the empty
string.

PROGRAMMERS GUIDE 139


PA RT 4 R E S O U R C E R E F E R E N C E

The following C# example shows how a menu handler for the Estimate Freight
menu item is added to the SopEntry form in Microsoft Dynamics GP:

Dynamics.Forms.SOPEntry.AddMenuHandler(OpenEstimateFreight,
"Estimate Freight", "F");

This code is the event handler for the menu item. Notice that it takes two arguments
like standard event handlers.

static void OpenEstimateFreight(object sender, EventArgs e)


{
if (EstimateFreightForm == null)
{
EstimateFreightForm = new EstimateFreight();
}
else
{
if (EstimateFreightForm.Created == false)
{
EstimateFreightForm = new EstimateFreight();
}
}

// Always show and activate the WinForm


EstimateFreightForm.Show();
EstimateFreightForm.Activate();
}
}

The following Visual Basic example shows how the same menu handler for the
Estimate Freight menu item is added to the SopEntry form in Microsoft Dynamics
GP.

Dim EstimateFreightHandler as System.EventHandler

EstimateFreightHandler = New System.EventHandler(AddressOf


OpenEstimateFreight)
Dynamics.Forms.SOPEntry.AddMenuHandler(EstimateFreightHandler, "Estimate
Freight", "F")

This code is the event handler for the menu item. Notice that it also takes two
arguments like standard event handlers.

Shared Sub OpenEstimateFreight(ByVal sender As Object, ByVal e As EventArgs)


If EstimateFreightForm Is Nothing Then
Try
EstimateFreightForm = New EstimateFreightForm()
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
Else
If EstimateFreightForm.Created = False Then
EstimateFreightForm = New EstimateFreightForm()
End If
End If

140 P R O G R A M M E R S G U I D E
C H A P T E R 2 0 F O R M S

' Always show and activate the WinForm


EstimateFreightForm.Show()
EstimateFreightForm.Activate()
End Sub

Close()
The Close() method closes the form.

Dispose()
The Dispose() method releases the memory used for the form after it is no longer
needed.

Open()
The Open() method attempts to open the form.

Form properties
Forms provide the following properties:

Commands
Functions
IsOpen
IsChanged
Procedures

Commands
The Commands property provides access to the list of commands that are defined
by the form. Refer to Chapter 26, Commands, to learn more about using
commands in your application.

Functions
The Functions property provides access to the list of form-level functions that are
defined by the form. Refer to Chapter 29, Functions, for more information about
functions.

IsChanged
The IsChanged property has the value true if the change flag for the form is set, and
false if it is not. The change flag is automatically set to true when any field value for
the form has changed.

IsOpen
The IsOpen property has the value true if the form is open, and false if it is not.

Procedures
The Procedures property provides access to the list for form-level procedures that
are defined by the form. Refer to Chapter 28, Procedures, to learn more about
using procedures.

Tables
The Tables property provides access to the list of tables that are attached to the
form. Refer to Chapter 9, Working with Tables, and Chapter 24, Tables, for
more information about using the tables attached to forms.

PROGRAMMERS GUIDE 141


PA RT 4 R E S O U R C E R E F E R E N C E

Form events
Forms provide the following events:

OpenBeforeOriginal
OpenAfterOriginal
CloseBeforeOriginal
CloseAfterOriginal

OpenBeforeOriginal
This event occurs when the form is opened, but before the forms open event is run.
This event can be canceled.

OpenAfterOriginal
This event occurs when the form is opened, but after the forms open event is run.

CloseBeforeOriginal
This event occurs when the form is closed, before the forms close event is run. This
event can be canceled.

CloseAfterOriginal
This event occurs when the form is closed, after the forms close event is run.

142 P R O G R A M M E R S G U I D E
Chapter 21: Windows
Windows are a part of form in Microsoft Dynamics GP. They display the user
interface for the application. The following items are discussed:

Accessing windows
Window methods
Window properties
Window events

Accessing windows
Windows for an application dictionary are accessed as properties of the form that
they are contained in. For example, the Sales Transaction Entry window (SopEntry)
is part of the SopEntry form. To access it, you would use the following syntax:

Dynamics.Forms.SopEntry.SopEntry

The IntelliSense in Visual Studio will tell you what form and window in Microsoft
Dynamics GP are being referred to by the expression.

Window methods
Windows provide the following methods:

Close()
Open()
PullFocus()

Close()
The Close() method closes the window.

Open()
The Open() method attempts to open the window.

PullFocus()
The PullFocus() method will remove the focus from the current window. No item
in the window will be focused. Any pending validate or leave events for the
currently-focused field will be run. Use this method in situations where you want
all of the pending actions to be run before your integrating application performs its
processing.

Window properties
Windows provide the following properties:

IsChanged
IsOpen

IsChanged
The IsChanged property has the value true if the change flag for the form is set, and
false if it is not. The change flag is automatically set to true when any field value for
the window has changed.

IsOpen
The IsOpen property has the value true if the window is open, and false if it is not.

PROGRAMMERS GUIDE 143


PA RT 4 R E S O U R C E R E F E R E N C E

Window events
Windows provide the following events:

OpenBeforeOriginal
OpenAfterOriginal
ActivateBeforeOriginal
ActivateAfterOriginal
CloseBeforeOriginal
CloseAfterOriginal
PrintBeforeOriginal
PrintAfterOriginal
BeforeModalDialog
AfterModalDialog

OpenBeforeOriginal
This event occurs when the window is opened, but before the windows open event
is run. This event can be canceled.

OpenAfterOriginal
This event occurs when the window is opened, but after the windows open event is
run.

ActivateBeforeOriginal
This event occurs each time the window becomes active, before the windows
activate event is run. The activate event occurs every time the window is opened or
brought to the front by the user. It occurs after the Open event.

The Activate event must be used cautiously. It shouldnt perform any actions that can cause
dialogs to appear because the application can become suspended in an endless loop.

ActivateAfterOriginal
This event occurs each time the window becomes active, after the windows activate
event is run.

CloseBeforeOriginal
This event occurs when the window is closed, but before the windows close event
is run. This event can be canceled.

CloseAfterOriginal
This event occurs when the window is closed, but after the windows close event is
run.

PrintBeforeOriginal
This event occurs when the print action for the window is chosen, but before the
windows print event is run. The print action for a window occurs when the user
chooses the Print menu item from the File menu, or clicks the Print button on the
window. This event can be canceled.

PrintAfterOriginal
This event occurs when the print action for the window is chosen, but after the
windows print event is run.

144 P R O G R A M M E R S G U I D E
C H A P T E R 2 1 W I N D O W S

BeforeModalDialog
This event occurs when the a modal dialog is displayed by a window, but before the
dialog is actually shown to the user. The event arguments allow access the
properties of the modal dialog:

DialogType Indicates the type of modal dialog that is being displayed. The
DialogType enumeration defines the following available types:

Type Description
Ask A modal dialog generated by the error, warning, or ask()
script commands.
GetString A modal dialog generated by the getstring() command.

Message Contains the text that is displayed in the modal dialog. Setting the value
of this property in the BeforeModalDialog event allows you to change the text
displayed in the modal dialog. Typically, the value of this parameter is examined to
find out what message is going to be displayed to the user.

Button1Text Contains the text that is displayed in button 1 of the modal dialog.
Setting the value of this property in the BeforeModalDialog event allows you to
change the text displayed in the button.

Button2Text Contains the text that is displayed in button 2 of the modal dialog.
Setting the value of this property in the BeforeModalDialog event allows you to
change the text displayed in the button.

Button3Text Contains the text that is displayed in button 3 of the modal dialog.
For getstring() dialogs, this is the editable string in the dialog. Setting the value of
this property in the BeforeModalDialog event allows you to change the text
displayed in the button or the editable field.

Response Indicates the response to the modal dialog. The DialogResponse


enumeration defines the available responses:

Response type Description


Button1 Button 1 in the modal dialog is clicked.
Button2 Button 2 in the modal dialog is clicked.
Button3 Button 3 in the modal dialog is clicked.
Ok The OK button in the getstring() modal dialog is clicked.
Cancel The Cancel button in the getstring() modal dialog is
clicked.
None No response was made.

Setting this property in the BeforeModalDialog event allows your code to respond
to the dialog, and prevents the dialog from being displayed to the user. Setting the
response to None will allow the dialog to be displayed.

The following Visual Basic example creates references to the Sales Transction Entry
form and window, and then registers a BeforeModalDialog event for the Sales
Transaction Entry window.

' Create a reference to the Sales Transtion Entry form


Shared SOPEntryForm As SopEntryForm = Dynamics.Forms.SopEntry

PROGRAMMERS GUIDE 145


PA RT 4 R E S O U R C E R E F E R E N C E

' Create a reference to the Sales Transaction Entry window


Shared SOPEntryWindow As SopEntryForm.SopEntryWindow = SOPEntryForm.SopEntry

Sub Initialize() Implements IDexterityAddin.Initialize

AddHandler SOPEntryWindow.BeforeModalDialog, AddressOf _


SopEntryWindow_BeforeModalDialog

End Sub

The following example is the BeforeModalDialog event handler for the event
registered inthe previous example. When a modal dialog is to be displayed, the
code examines the text of the message to determine whether it is the message that
asks the user whether they want to add a new customer or a new prospect. If it is,
the Response parameter of the event arguments is set to Button1, indicating that a
new customer should be created. This prevents the modal dialog from being
displayed.

Private Sub SopEntryWindow_BeforeModalDialog(ByVal sender As Object, ByVal e


As BeforeModalDialogEventArgs)

' Examine the dialog to determine whether it is the one to respond do


If e.DialogType = DialogType.Ask Then
If e.Message.Contains("want to add a customer") Then
' Click the Customer button in the modal dialog
e.Response = DialogResponse.Button1
End If
End If

End Sub

AfterModalDialog
This event occurs when the user has acted on a modal dialog displayed by a
window. This event allows you to retrieve the choice that the user made in the
modal dialog. Typically, you will examine the DialogType and Message properties
in the event arguments to find out what dialog is being displayed. Then you can
examine the Response property in the event arguments to learn how the user
responded to the dialog.

The following C# example creates references to the Item Maintenance form and the
Item Maintenance window, and then registers for the AfterModalDialog event for
the Item Maintenance window.

// Create a reference to the Item Maintenance form


public static IvItemMaintenanceForm ItemMaintenanceForm =
Dynamics.Forms.IvItemMaintenance;

// Create a reference to the Item Maintenance window


public static IvItemMaintenanceForm.IvItemMaintenanceWindow
ItemMaintenanceWindow = ItemMaintenanceForm.IvItemMaintenance;

public void Initialize()


{
ItemMaintenanceForm.IvItemMaintenance.AfterModalDialog +=
new EventHandler<AfterModalDialogEventArgs>
(IvItemMaintenance_AfterModalDialog);
}

146 P R O G R A M M E R S G U I D E
C H A P T E R 2 1 W I N D O W S

The following C# example is the AfterModalDialog event handler for the event
registered inthe previous example. When a modal dialog is to be displayed, the
code examines the text of the message to determine whether it is the message that
asks the user whether they want to delete the current item. The Response property
of the event arguments is examined to find out whether the user clicked Delete in
the modal dialog. If the user did, the additional information stored for the item is
also deleted.

void IvItemMaintenance_AfterModalDialog(object sender,


AfterModalDialogEventArgs e)
{
// Is it an 'ask' dialog?
if (e.DialogType == DialogType.Ask)
{
// It it verifying a delete action?
if (e.Message.Contains("want to delete"))
{
// Did the user click Delete (button 1)?
if (e.Response == DialogResponse.Button1)
{
// Delete the environmental details for the current item.
DataAccessHelper.DeleteEnvironmentalDetails();
}
}
}
}

PROGRAMMERS GUIDE 147


148 P R O G R A M M E R S G U I D E
Chapter 22: Scrolling Windows
Scrolling windows are a special type of window in Microsoft Dynamics GP that are
used to display or access data directly from a database table. The following items
are discussed:

Accessing scrolling windows


Scrolling window methods
Scrolling window properties
Scrolling window events

Accessing scrolling windows


Scrolling windows for an application dictionary are accessed as properties of the
window that they are contained in. For example, the Line Scroll scrolling window in
the Sales Transaction Entry window of Microsoft Dynamics GP is accessed using
the following syntax:

Dynamics.Forms.SopEntry.SopEntry.LineScroll

The IntelliSense in Visual Studio will tell you what scrolling window in Microsoft
Dynamics GP is being referred to by the expression.

Scrolling window methods


There are no additional methods for scrolling windows.

Scrolling window properties


There are no additional properties for scrolling windows.

Scrolling window events


Scrolling windows provide the following events:

LineFillBeforeOriginal
LineFillAfterOriginal
LineEnterBeforeOriginal
LineEnterAfterOriginal
LineChangeBeforeOriginal
LineChangeAfterOriginal
LineLeaveBeforeOriginal
LineLeaveAfterOriginal
LineInsertBeforeOriginal
LineInsertAfterOriginal
LineDeleteBeforeOriginal
LineDeleteAfterOriginal

LineFillBeforeOriginal
This event occurs before the line fill event for the scrolling window. The line fill
event occurs each time a new line is added to the scrolling window from the linked
table, such as when the user scrolls to a new line. When the scrolling window first
fills, the line fill event occurs repeatedly until the scrolling window is full. The line
fill event also occurs each time the user moves the focus to an existing line in the
scrolling window. The line fill event occurs before the line enter event.

PROGRAMMERS GUIDE 149


PA RT 4 R E S O U R C E R E F E R E N C E

To find out what data will be added to the current row of the scrolling window,
examine the current row of the form-level table buffer for the table linked to the
scrolling window.

When using this event, you cannot examine the window fields for the scrolling window to
determine what row is being added. The values of the window fields will not have been set
yet.

The LineFillBeforeOriginal event can be cancelled. If the event is cancelled, the


current row in the table linked to the scrolling window will not be added to the
scrolling window.

For example, the following C# code registers the LineFillBeforeOriginal event for
the scrolling window in the Customers and Prospects window in Microsoft
Dynamics GP.

public void Initialize()


{
Dynamics.Forms.CustomerLookup.CustomerLookup.CustomerLookupScroll.
LineFillBeforeOriginal += new System.ComponentModel.CancelEventHandler
(CustomerLookupScroll_LineFillBeforeOriginal);
}

The following is the C# code that runs in response to this event. It allows only
customers in the TERRITORY 2 sales territory to be displayed. The
RmCustomerMstr table is linked to the scrolling window, so the values for the
scrolling window come from this table. Notice how the code is accessing the current
row of the form-level table buffer for the RmCustomerMstr table to find out what
row is being added to scrolling window. The SalesTerritory field in the current row
of the table is examined. If it is not TERRITORY 2, the event is cancelled. This
prevents the row from being displayed in the scrolling window.

void CustomerLookupScroll_LineFillBeforeOriginal(object sender,


System.ComponentModel.CancelEventArgs e)
{
if(Dynamics.Forms.CustomerLookup.Tables.RmCustomerMstr.SalesTerritory.
Value != "TERRITORY 2")
{
// Not in TERRITORY 2, so do not display the line
e.Cancel = true;
}
}

LineFillAfterOriginal
This event occurs after the line fill event for the scrolling window.

LineEnterBeforeOriginal
This event occurs when the focus moves to a line in the scrolling window, but
before the scrolling windows line enter event is run. This event can be canceled.

LineEnterAfterOriginal
This event occurs when the focus moves to a line in the scrolling window, but after
the scrolling windows line enter event is run.

150 P R O G R A M M E R S G U I D E
C H A P T E R 2 2 S C R O L L I N G W I N D O W S

LineChangeBeforeOriginal
This event occurs when the focus leaves a line in the scrolling window, and the
contents of the line has been modified. The event runs before the scrolling
windows line change event is run. This event can be canceled.

LineChangeAfterOriginal
This event occurs when the focus leaves a line in the scrolling window, and the
contents of the line has been modified. The event runs after the scrolling windows
line change event is run.

LineLeaveBeforeOriginal
This event occurs when the focus leaves a line in the scrolling window, but before
the scrolling windows line leave event is run. This event can be canceled.

LineLeaveAfterOriginal
This event occurs when the focus leaves a line in the scrolling window, but after the
scrolling windows line leave event is run.

LineInsertBeforeOriginal
This event occurs when a new line is added to the scrolling window, but before the
scrolling windows line insert event is run. This event can be canceled.

LineInsertAfterOriginal
This event occurs when a new line is added to the scrolling window, but after the
scrolling windows line insert event is run.

LineDeleteBeforeOriginal
This event occurs when a line is removed from the scrolling window, but before the
scrolling windows line delete event is run. This event can be canceled.

LineDeleteAfterOriginal
This event occurs when a line is removed from the scrolling window, but after the
scrolling windows line delete event is run.

PROGRAMMERS GUIDE 151


152 P R O G R A M M E R S G U I D E
Chapter 23: Window Fields
Window fields display individual data items on a window. The following items are
discussed:

Accessing window fields


Window field methods
Window field properties
Window field events

Accessing window fields


Windows fields for an application dictionary are accessed as properties of the
window or scrolling window that they are contained in. For example, the SOP
Number (SopNumber) field is available on the Sales Transaction Entry window
(SopEntry). To access it, you would use the following syntax:

Dynamics.Forms.SopEntry.SopEntry.SopNumber

As another example, the QTY To Backorder (QtyToBackOrder) field is available on


the Line Scroll (LineScroll) scrolling window of the Sales Transaction Entry
window(SopEntry). To access this field, you would use the following syntax:

Dynamics.Forms.SopEntry.SopEntry.LineScroll.QtyToBackOrder

The IntelliSense in Visual Studio will tell you what field in Microsoft Dynamics GP is being
referred to by the expression.

Some fields in windows are called local fields, because they are used only within a
specific form. For instance, the Sales Transaction Entry window (SopEntry) contains
a local field named (L) BillTo Address 1. The (L) in the name is the standard way
local fields are identified in Microsoft Dynamics GP. In a Visual Studio Tools for
Microsoft Dynamics GP project, the names of these fields are prefixed with the
Local to indicate they are local fields. For example, to access the BillTo Address 1
local field, you would use the following syntax:

Dynamics.Forms.SopEntry.SopEntry.LocalBillToAddress1

Window field methods


Window fields provide the following methods:

Clear()
Disable()
Enable()
Fill()
Focus()
ForceValidate()
Hide()
Lock()
RunValidate()
Show()
Unlock()

PROGRAMMERS GUIDE 153


PA RT 4 R E S O U R C E R E F E R E N C E

Clear()
The Clear() method sets the field to its cleared value. The following table lists the
cleared value for standard datatypes:

Datatype Cleared value


Date 0/0/0
Currency 0
Integer 0
Long 0
String Empty string
Time 000000 which corresponds to 12:00:00 AM

Disable()
The Disable() method makes the field appear in a disabled state, and prevents the
user from making changes to the field.

Enable()
The Enable() method allows a previously disabled field to receive user input.

Fill()
The Fill() method sets the field to its filled value. The following table lists the filled
value for standard datatypes:

Datatype Filled value


Date 12/31/9999
Currency 99999999999999.99999
Integer 32,767
Long 2,147,483,647
String The length byte (first byte) of the string is set to the
storage size of the string minus 1. Each of the
remaining bytes is set to string equivalent of ASCII 255.
Time 23:59:59

Focus()
The Focus() method moves the focus to the field.

ForceValidate()
The ForceValidate() method controls whether the validate event will occur when
the focus leaves the field. If the validate event occurs, any validation code for the
field will be run. This method takes one boolean parameter. Supplying the value
true forces the validate event to occur. Supplying the value false clears any previous
call to force the validate event to occur.

Hide()
The Hide() method causes the field to become invisible and inaccessible to the user.

Lock()
The Lock() method causes a field to become inaccessible to the user. The fields
appearance will not change.

154 P R O G R A M M E R S G U I D E
C H A P T E R 2 3 W I N D O W F I E L D S

RunValidate()
The RunValidate() method causes any validation code for the window field to be
run.

Show()
The Show() method causes a previously hidden field to become visible and
accessible to the user.

Unlock()
The Unlock() method causes a previously locked field to become accessible to the
user.

Window field properties


Window fields have the following properties:

IsEmpty
IsFilled
Value

IsEmpty
The IsEmpty property returns the value true when the value of the field is empty
for the specific field type. The following table lists the empty value for standard
datatypes:

Datatype Empty value


Date 0/0/0
Currency 0
Integer 0
Long 0
String Empty string
Time 000000 which corresponds to 12:00:00 AM

IsFilled
The IsFilled property returns the value true when the value of the field is set to the
maximum value for the specific field type. The following table lists the filled value
for standard datatypes:

Datatype Filled value


Date 12/31/9999
Currency 99999999999999.99999
Integer 32,767
Long 2,147,483,647
String The length byte (first byte) of the string is set to the
storage size of the string minus 1. Each of the
remaining bytes is set to string equivalent of ASCII 255.
Time 23:59:59

Value
The Value property is used to set or retrieve the value of the field. The IntelliSense
in Visual Studio will tell you what type of value is used for the field.

PROGRAMMERS GUIDE 155


PA RT 4 R E S O U R C E R E F E R E N C E

Window field events


Window fields provide the following events:

Change
EnterBeforeOriginal
EnterAfterOriginal
LeaveBeforeOriginal
LeaveAfterOriginal
ValidateBeforeOriginal
ValidateAfterOriginal

Change
This event occurs when the value of the field changes, such as being set by the user
or changed by other code in Microsoft Dynamics GP.

ClickAfterOriginal
This event occurs when the user clicks a button, but after the buttons click event is
run.

ClickBeforeOriginal
This event occurs when the user clicks a button, but before the buttons click event
is run. This event can be canceled.

EnterBeforeOriginal
This event occurs when the focus moves to the field, but before the fields enter
event is run. This event can be canceled.

EnterAfterOriginal
This event occurs when the focus moves to the field, but after the fields enter event
is run.

LeaveBeforeOriginal
This event occurs when the focus moves from the field, but before the fields leave
event is run. This event can be canceled.

LeaveAfterOriginal
This event occurs when the focus moves from the field, but after the fields leave
event is run.

ValidateBeforeOriginal
This event occurs when the focus is to move from the field, and the field has been
set to be validated. A field will be validated when its value has been changed, or the
validation has been forced, such as with the ForceValidate() method. This event
occurs before the fields validate event. It can be canceled.

ValidateAfterOriginal
This event occurs when the focus is to move from the field, and the field has been
set to be validated. This event occurs after the fields validate event.

156 P R O G R A M M E R S G U I D E
Chapter 24: Tables
Tables are the basic resource of the Microsoft Dynamics GP application that
provides access to the database. Methods provided for each table allow creating,
retrieving, updating, or deleting rows from the table in the database. The following
items for tables are discussed:

Accessing tables
Table methods
Table properties

Accessing tables
A table buffer provides access to one row of a specific table. Your code will interact
with the table buffer when you perform operations on the table. There are two types
of table buffers: global and form-level.

Global table buffers


A global table buffer is created when a table is accessed directly through the global list
of tables. Global table buffers are accessed through the dictionary class. This class
has a Tables property that provides access to the collection of tables defined in the
dictionary. The dictionary class for the application dictionary is located in the
following namespace:

Microsoft.Dexterity.Applications

For instance, to access the collection of tables in the Dynamics dictionary, use the
following syntax:

Microsoft.Dexterity.Applications.Dynamics.Tables

To access a specific table, such as the RM_Customer_MSTR table


(RmCustomerMstr), use the syntax shown below. (This example assumes the
namespace mentioned above has been referenced.)

Dynamics.Tables.RmCustomerMstr

The IntelliSense in Visual Studio will tell you what table in Microsoft Dynamics GP is
being referred to by the expression.

By default, a global table buffer for a table is shared with all of the other Visual
Studio Tools add-ins that are accessing that same table. If you want your integration
to create a global table buffer that is not shared, use the Clone() method when
creating the instance of the global table buffer.

Form-level table buffers


A form-level table buffer is created when a table is attached to a form in Microsoft
Dynamics GP. There is one table buffer for each table that is attachd to the form.
Each form-level table buffer is shared by the code that is part of the form, as well as
any code outside of the form that accesses the table through that form. The Tables
property for the form allows access to the table buffers for the tables that are
attached to the form. For example, to access the form-level procedures for Sales
Transaction Entry Form (SopEntryForm) in Microsoft Dynamics GP, you would use
the following syntax:

PROGRAMMERS GUIDE 157


PA RT 4 R E S O U R C E R E F E R E N C E

Dynamics.Forms.SopEntry.Tables

The IntelliSense in Visual Studio will tell you what form-level table in Microsoft Dynamics
GP is being referred to by the expression.

Table methods
Tables provide the following methods:

Change()
ChangeFirst()
ChangeLast()
ChangePrevious()
Clear()
Clone()
Close()
Fill()
Get()
GetFirst()
GetLast()
GetNext()
GetPrevious()
RangeClear()
RangeEnd()
RangeRemove()
RangeStart()
Release()
Remove()
Save()

Change()
The Change() method retrieves a row from the table and passively or actively locks
the row, allowing changes to be made to it. The row retrieved is determined by the
key specified for the table and the values that were specified for the key segments.
The Change() method has one parameter:

ActiveLock A optional boolean. The value true specifies that an active lock will be
applied to the row. The value false (the default value) specifies that a passive lock
will be applied.

ChangeFirst()
The ChangeFirst() method retrieves the first row from the table and passively or
actively locks the row, allowing changes to be made to it. The row retrieved is
determined by the key specified for the table. The ChangeFirst() method has one
parameter:

ActiveLock A optional boolean. The value true specifies that an active lock will be
applied to the row. The value false (the default value) specifies that a passive lock
will be applied.

158 P R O G R A M M E R S G U I D E
C H A P T E R 2 4 T A B LE S

ChangeLast()
The ChangeLast() method retrieves the last row from the table and passively or
actively locks the row, allowing changes to be made to it. The row retrieved is
determined by the key specified for the table. The ChangeLast() method has one
parameter:

ActiveLock A optional boolean. The value true specifies that an active lock will be
applied to the row. The value false (the default value) specifies that a passive lock
will be applied.

ChangeNext()
The ChangeNext() method retrieves the next row from the table and passively or
actively locks the row, allowing changes to be made to it. The row retrieved is
determined by the key specified for the table and the values of the key fields for the
row currently in the table buffer. The ChangeNext() method has one parameter:

ActiveLock A optional boolean. The value true specifies that an active lock will be
applied to the row. The value false (the default value) specifies that a passive lock
will be applied.

ChangePrevious()
The ChangePrevious() method retrieves the previous row from the table and
passively or actively locks the row, allowing changes to be made to it. The row
retrieved is determined by the key specified for the table and the values of the key
fields for the row currently in the table buffer. The ChangePrevious() method has
one parameter:

ActiveLock A optional boolean. The value true specifies that an active lock will be
applied to the row. The value false (the default value) specifies that a passive lock
will be applied.

Clear()
The Clear() method sets all of the fields in the table buffer to their cleared values.
The following table lists the cleared value for standard datatypes:

Datatype Cleared value


Date 0/0/0
Currency 0
Integer 0
Long 0
String Empty string
Time 000000 which corresponds to 12:00:00 AM

Clone()
The Clone() method creates a new instance of a global table buffer for a table. This
new table buffer instance is not shared, so it is not accessible by other Visual Studio
Tools add-ins. The Clone() method has no effect when when with form-level table
buffers.

Close()
The Close() method closes the table buffer.

PROGRAMMERS GUIDE 159


PA RT 4 R E S O U R C E R E F E R E N C E

Fill()
The Fill() method sets all of the fields in the table buffer to their maximum values.
The following table lists the filled value for standard datatypes:

Datatype Filled value


Date 12/31/9999
Currency 99999999999999.99999
Integer 32,767
Long 2,147,483,647
String The length byte (first byte) of the string is set to
the storage size of the string minus 1. Each of the
remaining bytes is set to string equivalent of
ASCII 255.
Time 23:59:59

Get()
The Get() method retrieves a row from the table. No lock is applied to the row. The
row retrieved is determined by the key specified for the table and the values that
were specified for the key segments.

GetFirst()
The GetFirst() method retrieves the first row from the table. No lock is applied to
the row. The row retrieved is determined by the key specified for the table.

GetLast()
The GetLast() method retrieves the last row from the table. No lock is applied to the
row. The row retrieved is determined by the key specified for the table.

GetNext()
The GetNext() method retrieves the next row from the table. No lock is applied to
the row. The row retrieved is determined by the key specified for the table and the
values of the key fields for the row currently in the table buffer.

GetPrevious()
The GetPrevious() method retrieves the previous row from the table. No lock is
applied to the row. The row retrieved is determined by the key specified for the
table and the values of the key fields for the row currently in the table buffer.

RangeClear()
The RangeClear() method removes the range that was specified for the table.

RangeEnd()
The RangeEnd() method specifies the current values of the key segments in the
table buffer as the end of the range of rows in the table. The Key property specifies
which key will be used for the range.

RangeRemove()
The RangeRemove() method attempts to delete all of the rows in the current range
from the table.

RangeStart()
The RangeStart() method specifies the current values of the key segments in the
table buffer as the beginning of the range of rows in the table. The Key property
specifies which key will be used for the range.

160 P R O G R A M M E R S G U I D E
C H A P T E R 2 4 T A B LE S

Release()
The Release() method releases any passive or active lock for a row in the table
buffer. The row values remain in the table buffer.

Remove()
The Remove() method deletes the current row in the table buffer from the table. The
row must be passivly or actively locked before it can be deleted.

Save()
The Save() method saves the values currently in the table buffer to the table. If the
row is locked in the table buffer, it will be updated. If no row in the table is locked, a
new row will be added.

Table properties
Tables have the following property:

Key

Key
The Key property is used to set or retrieve the key currently being used by the table
buffer to access the table. The keys for a table are identified by number, beginning
with the value 1. When you specify the key you want to use for a table, you will
supply the corresponding integer. The Table Descriptions window in Microsoft
Dynamics GP lists the keys for each table, and the key segments (fields) that each
key contains.

PROGRAMMERS GUIDE 161


162 P R O G R A M M E R S G U I D E
Chapter 25: Table Fields
Table fields represent individual data items in a row of a table. The following items
are discussed:

Accessing table fields


Table field methods
Table field properties

Accessing table fields


Table fields for an application dictionary are accessed as properties of the table that
they are contained in. For example, the Item Number (ItemNumber) field is
available in the Inventory Item Master (IvItemMstr) table. To access it, you would
use the following syntax:

Dynamics.Tables.IvItemMstr.ItemNumber

The IntelliSense in Visual Studio will tell you what field in Microsoft Dynamics GP is being
referred to by the expression.

Table field methods


Table fields provide the following methods:

Clear()
Fill()

Clear()
The Clear() method sets the field to its cleared value. The following table lists the
cleared value for standard datatypes:

Datatype Cleared value


Date 0/0/0
Currency 0
Integer 0
Long 0
String Empty string
Time 000000 which corresponds to 12:00:00 AM

Fill()
The Fill() method sets the field to its filled value. The following table lists the filled
value for standard datatypes:

Datatype Filled value


Date 12/31/9999
Currency 99999999999999.99999
Integer 32,767
Long 2,147,483,647
String The length byte (first byte) of the string is set to the
storage size of the string minus 1. Each of the
remaining bytes is set to string equivalent of ASCII 255.
Time 23:59:59

PROGRAMMERS GUIDE 163


PA RT 4 R E S O U R C E R E F E R E N C E

Table field properties


Table fields have the following properties:

IsEmpty
IsFilled
Value

IsEmpty
The IsEmpty property returns the value true when the value of the field is empty
for the specific field type. The following table lists the empty value for standard
datatypes:

Datatype Empty value


Date 0/0/0
Currency 0
Integer 0
Long 0
String Empty string
Time 000000 which corresponds to 12:00:00 AM

IsFilled
The IsFilled property returns the value true when the value of the field is set to the
maximum value for the specific field type. The following table lists the filled value
for standard datatypes:

Datatype Filled value


Date 12/31/9999
Currency 99999999999999.99999
Integer 32,767
Long 2,147,483,647
String The length byte (first byte) of the string is set to the
storage size of the string minus 1. Each of the
remaining bytes is set to string equivalent of ASCII 255.
Time 23:59:59

Value
The Value property is used to set or retrieve the value of the field. The IntelliSense
in Visual Studio will tell you what type of value is used for the field.

164 P R O G R A M M E R S G U I D E
Chapter 26: Commands
In Microsoft Dynamics GP, commands are used to encapsulate a small piece of
functionality for the application. They are typically used for navigation. Commands
can appear in menus and also in toolbars in Microsoft Dynamics GP. The following
items are discussed:

Command types
Accessing commands
Command methods

Command types
A command can be one of the following types:

Form A form command opens the specified form.

Script A script command runs the script code that is defined for it.

Command list A command list command is a container for other commands. A


command list can be used as a menu, submenu, or a toolbar.

Accessing commands
Commands for an application dictionary are accessed using the Commands
property of the form that they are contained in. Most commands in Microsoft
Dynamics GP are contained in forms that are used specifically for commands. The
names of these forms begin with Command and include the module for which
the commands are used. For example, to access the command used to open the
SmartList window in Microsoft Dynamics GP, you would use the following syntax:

Dynamics.Forms.CommandSystem.Commands.SmartList

The IntelliSense in Visual Studio will tell you what command in Microsoft Dynamics GP is
being referred to by the expression.

Command methods
Commands provide the following methods:

Check()
Disable()
Enable()
Hide()
Run()
Show()
Uncheck()

Check()
The Check() method causes the command to appear checked if it is displayed in a
menu or on a toolbar.

Disable()
The Disable() method causes the command to appear disabled if it is displayed in a
menu or on a toolbar. Once disabled, the command cannot be run.

PROGRAMMERS GUIDE 165


PA RT 4 R E S O U R C E R E F E R E N C E

Enable()
The Enable() method causes a previously disabled command to become enabled. It
will appear enabled if it is displayed in a menu or on a toolbar.

Hide()
The Hide() method causes a command to be hidden in any menu or toolbar in
which it appears. The command can still be run.

Run()
The Run() method performs the action of the command. For form commands, it
opens the corresponding form. For script commands, it executes the script code that
is attached to the command.

Show()
The Show() method causes a previously hidden command to be displayed in any
menu or toolbar in which it appears.

Uncheck()
The Uncheck() method causes the command to appear unchecked if it is displayed
in a menu or on a toolbar.

166 P R O G R A M M E R S G U I D E
Chapter 27: Globals
Globals are used to hold values accessible to the entire Microsoft Dynamics GP
application. The following items are discussed:

Accessing globals
Global properties

Accessing globals
Globals for an application dictionary are accessed through the dictionary class. This
class has a Globals property that provides access to the collection of globals in the
dictionary. The dictionary class for the application dictionary is located in the
following namespace:

Microsoft.Dexterity.Applications

For instance, to access the collection of globals in the Dynamics dictionary, use the
following syntax:

Microsoft.Dexterity.Applications.Dynamics.Globals

To access a specific global value, such as the current users ID (UserId), use the
following syntax:

Microsoft.Dexterity.Applications.Dynamics.Globals.UserId

Global properties
Globals have the following properties available:

IsEmpty
IsFilled
Value

IsEmpty
The IsEmpty property returns the value true when the value of the field is empty
for the specific field type. The following table lists the empty value for standard
datatypes:

Datatype Empty value


Date 0/0/0
Currency 0
Integer 0
Long 0
String Empty string
Time 000000 which corresponds to 12:00:00 AM

PROGRAMMERS GUIDE 167


PA RT 4 R E S O U R C E R E F E R E N C E

IsFilled
The IsFilled property returns the value true when the value of the field is set to the
maximum value for the specific field type. The following table lists the filled value
for standard datatypes:

Datatype Filled value


Date 12/31/9999
Currency 99999999999999.99999
Integer 32,767
Long 2,147,483,647
String The length byte (first byte) of the string is set to the
storage size of the string minus 1. Each of the
remaining bytes is set to string equivalent of ASCII 255.
Time 23:59:59

Value
The Value property is used to retrieve the value of the global. The IntelliSense in
Visual Studio will tell you what type of value is used for the field. Global values
cannot be set from a Visual Studio Tools for Microsoft Dynamics GP project.

168 P R O G R A M M E R S G U I D E
Chapter 28: Procedures
There are two types of procedures in a Dynamics GP application dictionary. Global
procedures are blocks of code that are accessed from various places throughout the
application. Parameters are used to send values to a procedure and also to return
values from it. Form-level procedures are like global procedures, with the exception
that they are defined as part of a specific form. Typically, they perform some action
specific to the form they are defined for. The following items are discussed:

Accessing global procedures


Accessing form-level procedures
Procedure methods
Procedure events
Parameters for procedures
Invokable procedures

Accessing global procedures


Global procedures for an application dictionary are accessed through the dictionary
class. This class has a Procedures property that provides access to the collection of
global procedures in the dictionary. The dictionary class for the application
dictionary is located in the following namespace:

Microsoft.Dexterity.Applications

For instance, to access the collection of global procedures in the Dynamics


dictionary, use the following syntax:

Microsoft.Dexterity.Applications.Dynamics.Procedures

To access a specific global procedure, such as the Get_Next_Form_Note_To_Open


procedure (GetNextFormNoteToOpen), use the syntax shown below. (This example
assumes the namespace mentioned above has been referenced.)

Dynamics.Procedures.GetNextFormNoteToOpen

The IntelliSense in Visual Studio will tell you what global procedure in Microsoft Dynamics
GP is being referred to by the expression.

Accessing form-level procedures


Form-level procedures for an application dictionary are accessed through the form
they are contained in. The Procedures property for the form allows access to the
form-level procedures. For example, to access the form-level procedures for Sales
Transaction Entry Form (SopEntryForm) in Microsoft Dynamics GP, you would use
the following syntax:

Dynamics.Forms.SopEntry.Procedures

The IntelliSense in Visual Studio will tell you what form-level procedure in Microsoft
Dynamics GP is being referred to by the expression.

Procedure methods
Procedures provide the following method:

Invoke()

PROGRAMMERS GUIDE 169


PA RT 4 R E S O U R C E R E F E R E N C E

Invoke()
The Invoke() method is used to run the specified procedure. The parameters for this
method will depend on the procedure that is being run. The following table lists the
types of parameters for procedures:

Type Description
in Parameters of type in are used only to pass values into the procedure.
out Parameters of type out are used only to pass values out of the
procedure.
inout Parameters of type inout are used to pass values into the procedure,
and to pass values out of the procedure.

The IntelliSense in Visual Studio will tell you the type of each parameter for a procedure. It
will also tell you the datatype of each parameter, such as decimal or string.

For example, the following C# code calls the CheckNoteIdString global procedure.
This procedure has one in parameter and two out parameters. Notice that the
out keyword is required for the parameters to which values are returned.

Dynamics.Procedures.CheckNoteIdString.Invoke("Estimate Freight", out


isPresent, out formNumber);

You can refer to the Microsoft Dynamics GP SDK for details about the procedures
available to invoke. Some procedures in Microsoft Dynamics GP have optional
parameters defined. Visual Studio Tools does not support optional parameters. You
must supply all parameters for a procedure when you invoke it from Visual Studio
Tools.

Procedure events
Procedures provide the following events:

InvokeBeforeOriginal
InvokeAfterOriginal

InvokeBeforeOriginal
This event occurs when the procedure is invoked, but before the original procedure
is run. The event arguments allow access the parameters of the procedure. Refer to
Parameters for procedures on page 171 to learn more about working with parameters
in procedure events.

InvokeAfterOriginal
This event occurs when the procedure is invoked, but after the original procedure is
run.The event arguments allow access the parameters of the procedure. Refer to
Parameters for procedures on page 171 to learn more about working with parameters
in procedure events.

The following C# example registers the InvokeAfterOriginal event for the


AddSuccessfulLoginRecord procedure in Microsoft Dynamics GP.
Dynamics.Procedures.AddSuccessfulLoginRecord.InvokeAfterOriginal +=
new AddSuccessfulLoginRecordProcedure.InvokeEventHandler(
AddSuccessfulLoginRecord_InvokeAfterOriginal);

170 P R O G R A M M E R S G U I D E
C H A PT E R 2 8 P R O C ED U R E S

The following C# example is the event handler for the event registered in the
previous example. The event handler for the AddSuccessfulLoginRecord procedure
is typically used to perform setup operations, because the user has successfully
logged into a company.

void AddSuccessfulLoginRecord_InvokeAfterOriginal(object sender,


AddSuccessfulLoginRecordProcedure.InvokeEventArgs e)
{
// Setup code is placed here
}

Parameters for procedures


When you invoke a procedure or use procedure events, you will need to work with
the parameters of the procedure.

Learning about the parameters


There are several ways you can learn about the parameters for a procedure:

When invoking a procedure, the IntelliSense lists the parameters and their data
types.

The event arguments passed to the event handler for procedure events will list
the available parameters and their data types.

The Parameters for Microsoft Dynamics GP section of the Microsoft Dynamics GP


SDK contains a complete listing of the parameters for the procedures in
Microsoft Dynamics GP and several integrating dictionaries. The parameter
documents in this section of the SDK also list the parameter names, which can
be helpful when determining how the parameters are used.

Accessing parameter values


In the InvokeBeforeOriginal and InvokeAfterOriginal event handlers, you can use
the event arguments to access the values of the parameters that were passed into the
procedure. Be aware that other applications that integrate with Microsoft Dynamics
GP may have changed the values of the parameters.

Changing parameter values


In the InvokeBeforeOriginal and InvokeAfterOriginal event handlers, you can
change the values of out and inout parameters. The values of in parameters
cannot be changed.

We recommend that you avoid changing parameter values in Microsoft Dynamics GP


procedures. Changing the parameter values can signficantly alter the operation of Microsoft
Dynamics GP.

If a procedure is being processed in the background queue in Microsoft Dynamics


GP, the event handler will be passed a copy of the original parameters for the
procedure. This means that any changes you make to the parameters will be
ignored.

PROGRAMMERS GUIDE 171


PA RT 4 R E S O U R C E R E F E R E N C E

Invokable procedures
With this release of Visual Studio Tools for Microsoft Dynamics GP, not all
procedures can be invoked. Procedures with the following characteristics cannot be
invoked:

The procedure uses anonymous parameters. These parameter types arent


known at the time the application is compiled.

The procedure uses reference parameters. These parameter types contain a


link to a specific resource in the application dictionary.

If a composite field used as a procedure parameter contains a reference value,


that procedure cannot be invoked.

If a procedure cannot be run by this version of Visual Studio Tools, it will not be
included in the procedure lists displayed by the IntelliSense in Visual Studio.

172 P R O G R A M M E R S G U I D E
Chapter 29: Functions
There are two types of functions in a Dynamics GP application dictionary. Global
functions are blocks of code that are accessed from various places throughout the
application. Parameters are used to send values to a function and also to return
values from it. In addition, functions always return a value. Form-level functions are
like global functions, with the exception that they are defined as part of a specific
form. Typically, they perform some action specific to the form they are defined for.
The following items are discussed:

Accessing global functions


Accessing form-level functions
Function methods
Function events
Parameters for functions
Invokable functions

Accessing global functions


Global functions for an application dictionary are accessed through the dictionary
class. This class has a Functions property that provides access to the collection of
global functions in the dictionary. The dictionary class for the application dictionary
is located in the following namespace:

Microsoft.Dexterity.Applications

For instance, to access the collection of global functions in the Dynamics dictionary,
use the following syntax:

Microsoft.Dexterity.Applications.Dynamics.Functions

To access a specific global function, such as the GetCurrentDirectory function


(GetCurrentDirectory), use the following syntax shown below. (This example
assumes the namespace mentioned above has been referenced.)

Dynamics.Functions.GetCurrentDirectory

The IntelliSense in Visual Studio will tell you what global function in Microsoft Dynamics
GP is being referred to by the expression.

Accessing form-level functions


Form-level functions for an application dictionary are accessed through the form
they are contained in. The Functions property for the form allows access to the
form-level functions. For example, to access the form-level functions for Sales
Transaction Entry Form (SopEntryForm) in Microsoft Dynamics GP, you would use
the following syntax:

Dynamics.Forms.SopEntry.Functions

The IntelliSense in Visual Studio will tell you what form-level function in Microsoft
Dynamics GP is being referred to by the expression.

PROGRAMMERS GUIDE 173


PA RT 4 R E S O U R C E R E F E R E N C E

Function methods
Functions provide the following method:

Invoke()

Invoke()
The Invoke() method is used to run the specified function. The parameters for this
method will depend on the procedure that is being run. The following table lists the
types of parameters for functions:

Type Description
in Parameters of type in are used only to pass values into the function.
out Parameters of type out are used only to pass values out of the
function.
inout Parameters of type inout are used to pass values into the function,
and to pass values out of the function.

The Invoke() method will have a return value to which the return value of the
function will be returned.

The IntelliSense in Visual Studio will tell you the type of each parameter and the return
value for a function. It will also tell you the datatype of each parameter and the return value,
such as decimal or string.

For example, the following C# code calls the GetCurrentDirectory global function.
This procedure has no parameters and returns a string value.
string currentDirectory;
currentDirectory = Dynamics.Functions.GetCurrentDirectory.Invoke();

You can refer to the Microsoft Dynamics GP SDK for details about the functions
available to invoke. Some functions in Microsoft Dynamics GP have optional
parameters defined. Visual Studio Tools does not support optional parameters. You
must supply all parameters for a function when you invoke it from Visual Studio
Tools.

Function events
Functions provide the following events:

InvokeBeforeOriginal
InvokeAfterOriginal

InvokeBeforeOriginal
This event occurs when the function is invoked, but before the original function is
run. The event arguments allow access the parameters and return value of the
function. Refer to Parameters for functions on page 175 to learn more about working
with parameters and return value in function events.

InvokeAfterOriginal
This event occurs when the function is invoked, but after the original function is
run.The event arguments allow access the parameters and return value of the
function. Refer to Parameters for functions on page 175 to learn more about working
with parameters and return value in function events.

174 P R O G R A M M E R S G U I D E
C H A P T E R 2 9 F U N C T I O N S

The following C# example registers the InvokeAfterOriginal event for the


GetAutoComplete function of the UserDefaultsForm in Microsoft Dynamics GP.

UserDefaultsForm.Functions.GetAutoComplete.InvokeAfterOriginal +=
new SyUserDefaultsForm.GetAutoCompleteFunction.InvokeEventHandler(
GetAutoComplete_InvokeAfterOriginal);

The following C# example is the event handler for the event registered in the
previous example. The event handler uses the event arguments to examine the first
parameter passed into the function. If the parameter value is DYNSA, the return
value of the function is set to false. This will turn off the auto-complete functionality
for the DYNSA user.

void GetAutoComplete_InvokeAfterOriginal(object sender,


SyUserDefaultsForm.GetAutoCompleteFunction.InvokeEventArgs e)
{
// Set the return value to always turn off auto-complete for DYNSA user
if (e.inParam1 == "DYNSA")
{
e.result = false;
}
}

Parameters for functions


When you invoke a function or use function events, you will need to work with the
parameters and return value of the function.

Learning about the parameters and return value


There are several ways you can learn about the parameters and return value for a
function:

When invoking a function, the IntelliSense lists the parameters and return
value, along with their data types.

The event arguments passed to the event handler for function events will list
the available parameters and return value, along with their data types.

The Parameters for Microsoft Dynamics GP section of the Microsoft Dynamics GP


SDK contains a complete listing of the parameters and return values for the
functions in Microsoft Dynamics GP and several integrating dictionaries. The
parameter documents in this section of the SDK also list the parameter and
return value names, which can be helpful when determining how the
parameters and return value are used.

Accessing parameter and return values


In the InvokeBeforeOriginal and InvokeAfterOriginal event handlers, you can use
the event arguments to access the values of the parameters that were passed into the
function. You can also access the value returned from the function. Be aware that
other applications that integrate with Microsoft Dynamics GP may have changed
the values of the parameters or the return value.

PROGRAMMERS GUIDE 175


PA RT 4 R E S O U R C E R E F E R E N C E

Changing parameter and return values


In the InvokeBeforeOriginal and InvokeAfterOriginal event handlers, you can
change the values of out and inout parameters. The values of in parameters
cannot be changed. You can also change the value returned from the function.

We recommend that you avoid changing parameter and return values in Microsoft
Dynamics GP functions. Changing the parameter and return values can signficantly alter
the operation of Microsoft Dynamics GP.

Invokable functions
With this release of Visual Studio Tools for Microsoft Dynamics GP, not all
functions can be invoked. Functions with the following characteristics cannot be
invoked:

The function uses anonymous parameters. These parameter types arent


known at the time the application is compiled.

The function uses reference parameters. These parameter types contain a link
to a specific resource in the application dictionary.

If a composite field used as a function parameter contains a reference value,


that function cannot be invoked.

If a function cannot be run by this version of Visual Studio Tools, it will not be
included in the function lists displayed by the IntelliSense in Visual Studio.

176 P R O G R A M M E R S G U I D E
Chapter 30: Composites
In Microsoft Dynamics GP, a composite is a group of fields and their associated data
types which form a single data type. Each part of the composite is called a
component. In Microsoft Dynamics GP, composites are used to store data that
consists of several parts, such as the account number. Composites are also used to
group together the parameters that are passed to procedures and functions. The
following items are discussed:

Composite types
Accessing composites
Composite field methods
Composite field properties
Composite field events

Composite types
When you access composite resources from a dictionary, each composite will have
several types defined for it. Each type is used in specific situations in Microsoft
Dynamics GP. The following table describes the composite types.

Type Example Description


Base AccountNumberComposite The base implementation of the
composite type.
Data AccountNumberCompositeData The base implementation of the
composite type, but with
properties that provide access to
the components of the
composite.
Read-only AccountNumberCompositeReadOnly A read-only version of the
composite. It is used in cases
such as passing the composite
value as a parameter for a
procedure or function.
With events AccountNumberCompositeWithEvents The composite with the standard
window field events.
With full events AccountNumberCompositeWithFullEvents The composite with the standard
window field events, and the
same field events for each
component of the composite.

In most cases, the IntelliSense will tell you what composite type is required for a specific
situation.

Accessing composites
Composites can be displayed as fields on windows, and are accessed as properties
of the window or scrolling window they are contained in. Composites can also be
used to create variables that are passed as parameters for procedures and functions.

Window fields
Composite fields are accessed as properties of the window or scrolling window
they are contained in. For example, to access the Account Number CS field in the
Account Maintenance window of Microsoft Dynamics GP, you would use the
following syntax:

Dynamics.Forms.GlAccountMaintenance.GlAccountMaintenance.AccountNumberCs

PROGRAMMERS GUIDE 177


PA RT 4 R E S O U R C E R E F E R E N C E

Variables
In some cases, you may want to retrieve the value of a composite and use it as a
variable in your Visual Studio Tools integration. You can create an instance of the
composite, and then set the value of the composite variable.

For example, the following C# code creates an instance of the AccountNumberCs


composite, which appears in the Account Maintenance window in Microsoft
Dynamics GP. The value of this window field is retrieved. The value of each
component is combined into a string and displayed in a message.

// Create an instance of the AccountNumberCs composite


Microsoft.Dexterity.Applications.DynamicsDictionary.AccountNumberCsComposite
Data accountNumber = new AccountNumberCsCompositeData();

// Reference the Account Maintenance form


Microsoft.Dexterity.Applications.DynamicsDictionary.GlAccountMaintenanceForm
AccountMaintenance = Dynamics.Forms.GlAccountMaintenance;

// Retrieve the Account Number value


accountNumber = AccountMaintenance.GlAccountMaintenance.AccountNumberCs;
string accountNumberString = "";

// Retrieve the individual components


for (int i = 0; i < accountNumber.Length; i++)
{
accountNumberString = accountNumberString + accountNumber[i] + " ";
}

// Display the account number


System.Windows.Forms.MessageBox.Show("Account number: " +
accountNumberString);

Parameters
You can create composite variables and pass them as parameters for procedures
and functions. A variable based on the read-only composite type must be used as
the parameter. To create a read-only composite variable, you must first create a
variable based on the data composite type.

For example, the following C# code creates a variable of the type


AccountNumberCompositeData, and sets its component values. A variable of the
type AccountNumberCompositeReadOnly is created. Its constructor uses the
data composite variable to supply the composites value. The read-only version
of the composite value is passed as a parameter to the ConvertAcctToAliasStr
function.
Microsoft.Dexterity.Applications.DynamicsDictionary.AccountNumberComposite
Data accountNumberData = new AccountNumberCompositeData();
accountNumberData[0] = "000";
accountNumberData[1] = "1100";
accountNumberData[2] = "00";
accountNumberData[3] = "";

// Create the read-only composite that is used for the function call
Microsoft.Dexterity.Applications.DynamicsDictionary.AccountNumberComposite
ReadOnly accountNumber = new AccountNumberCompositeReadOnly
(accountNumberData);

178 P R O G R A M M E R S G U I D E
C H A P T E R 3 0 C O M P O S IT E S

// Convert the account number to its account alias


string alias = Dynamics.Forms.GlAcctBase.Functions.ConvertAcctToAliasStr.
Invoke(accountNumber);

// Display the account alias


System.Windows.Forms.MessageBox.Show("Account alias: " + alias);

Components
To access the individual components for most composites, you can use the
properties of the composite. The composite will have a property for each
component of the composite.

Some composites, such as the AccountNumberComposite, are defined dynamically


by Microsoft Dynamics GP. These composites do not have the named properties to
access the individual components of the composite. To access components for these
composites, you must use the components index. For instance, the following C#
code creates an instance of the AccountNumber composite and sets the value of
each component.

AccountNumberCompositeData accountNumberData = new


AccountNumberCompositeData();
accountNumberData[0] = "000";
accountNumberData[1] = "1100";
accountNumberData[2] = "00";
accountNumberData[3] = "";

Composite field methods


Composite fields provide the following methods:

Clear()
Disable()
Enable()
Fill()
Focus()
ForceValidate()
Hide()
Lock()
RunValidate()
Show()
Unlock()

Clear()
The Clear() method sets each component of the composite to its cleared value. The
following table lists the cleared value for standard datatypes:

Datatype Cleared value


Date 0/0/0
Currency 0
Integer 0
Long 0
String Empty string
Time 000000 which corresponds to 12:00:00 AM

PROGRAMMERS GUIDE 179


PA RT 4 R E S O U R C E R E F E R E N C E

Disable()
The Disable() method makes the composite field appear in a disabled state, and
prevents the user from making changes to the field.

Enable()
The Enable() method allows a previously disabled composite field to receive user
input.

Fill()
The Fill() method sets each component of the composite to its filled value. The
following table lists the filled value for standard datatypes:

Datatype Filled value


Date 12/31/9999
Currency 99999999999999.99999
Integer 32,767
Long 2,147,483,647
String The length byte (first byte) of the string is set to the
storage size of the string minus 1. Each of the
remaining bytes is set to string equivalent of ASCII 255.
Time 23:59:59

Focus()
The Focus() method moves the focus to the composite field.

ForceValidate()
The ForceValidate() method controls whether the validate event will occur when
the focus leaves the composite field. If the validate event occurs, any validation
code for the composite field will be run. This method takes one boolean parameter.
Supplying the value true forces the validate event to occur. Supplying the value
false clears any previous call to force the validate event to occur.

Hide()
The Hide() method causes the composite field to become invisible and inaccessible
to the user.

Lock()
The Lock() method causes a composite field to become inaccessible to the user. The
fields appearance will not change.

RunValidate()
The RunValidate() method causes any validation code for the composite field to be
run.

Show()
The Show() method causes a previously hidden composite field to become visible
and accessible to the user.

Unlock()
The Unlock() method causes a previously locked composite field to become
accessible to the user.

180 P R O G R A M M E R S G U I D E
C H A P T E R 3 0 C O M P O S IT E S

Composite field properties


Composite fields have the following properties:

IsEmpty
IsFilled
Length
Value

IsEmpty
The IsEmpty property returns the value true when the value of the composite field
is empty for the specific field type. The following table lists the empty value for
standard datatypes:

Datatype Empty value


Date 0/0/0
Currency 0
Integer 0
Long 0
String Empty string
Time 000000 which corresponds to 12:00:00 AM

IsFilled
The IsFilled property returns the value true when the value of the composite field is
set to the maximum value for the specific field type. The following table lists the
filled value for standard datatypes:

Datatype Filled value


Date 12/31/9999
Currency 99999999999999.99999
Integer 32,767
Long 2,147,483,647
String The length byte (first byte) of the string is set to the
storage size of the string minus 1. Each of the
remaining bytes is set to string equivalent of ASCII 255.
Time 23:59:59

Length
The Length property is used to retrieve the number of components in the composite
field.

Value
The Value property is used to set or retrieve the value of the composite field. The
IntelliSense in Visual Studio will tell you what type of value is used for the field.

PROGRAMMERS GUIDE 181


PA RT 4 R E S O U R C E R E F E R E N C E

Composite field events


Composite fields provide the following events:

Change
EnterBeforeOriginal
EnterAfterOriginal
LeaveBeforeOriginal
LeaveAfterOriginal
ValidateBeforeOriginal
ValidateAfterOriginal

Composites of the type with events supply these events for the composite as a
single field. Composites of the type with full events supply these events for the
composite as a single field, and also for each of the components of the composite.

Change
This event occurs when the value of the composite or component changes, such as
being set by the user or changed by other code in Microsoft Dynamics GP.

EnterBeforeOriginal
This event occurs when the focus moves to the composite field or component, but
before the field or component enter event is run. This event can be canceled.

EnterAfterOriginal
This event occurs when the focus moves to the composite field or component, but
after the field or component enter event is run.

LeaveBeforeOriginal
This event occurs when the focus moves from the composite field or component,
but before the fields leave event is run. This event can be canceled.

LeaveAfterOriginal
This event occurs when the focus moves from the composite field or component,
but after the fields leave event is run.

ValidateBeforeOriginal
This event occurs when the focus is to move from the composite field or component,
and the composite field or component has been set to be validated. A field or
component will be validated when its value has been changed, or the validation has
been forced, such as with the ForceValidate() method. This event occurs before the
composite field or component validate event. It can be canceled.

ValidateAfterOriginal
This event occurs when the focus is to move from the composite field or component,
and the composite field or component has been set to be validated. This event
occurs after the composite field or component validate event.

182 P R O G R A M M E R S G U I D E
PART 5: INTEGRATION EXAMPLES
Part 5: Integration Examples
This portion of the documentation describes integration examples that show how to
use Visual Studio Tools for Microsoft Dynamics GP. The following examples are
discussed:

Chapter 31, Field Defaulter, describes an example that uses events to default
field values in Microsoft Dynamics GP.

Chapter 32, Estimate Freight, describes an example that estimates freight


amounts for sales documents in Microsoft Dynamics GP.

Chapter 33, Environmental Details,describes an example that stores


additional environmental detail information for items in Microsoft Dynamics
GP.

Chapter 34, Lookups, describes an example the shows how six common
lookups are implemented for a Visual Studio Tools integration.

Chapter 35, Salesperson Analysis, describes an example that analizes the


customers for a selected salesperson. This example shows how to implement
custom rendering so that the integration can be used in the Microsoft Dynamics
GP web client.

The following table indicates which features of Visual Studio Tools for Microsoft
Dynamics GP features are implemented in each sample.

Field Estimate Environ. Lookups Salesperson


Defaulter Freight Details Analysis
Visual Studio Tools form X X X X
Access to Dynamics GP fields X X X X
Field events X X X X X
Form events X X X
Modal dialog events X
Procedure/function access X X
Table access X X X
DUOS integration X
Note integration X
Lookups X
Online help X
Macro support X
Works on web client X X X X X
Web client dynamic rendering X X X X
Web client custom rendering X

184 P R O G R A M M E R S G U I D E
Chapter 31: Field Defaulter
This sample application demonstrates how events in Microsoft Dynamics GP can be
used to default field values. The sample defaults the City and State fields when a
user enters a value for the ZIP code field in the Customer Maintenance window.
The following topics are discussed:

Overview
Running the sample application
How Visual Studio Tools was used

Overview
This sample application integrates with the Customer Maintenance window in
Microsoft Dynamics GP. It automatically defaults values for the City and State
fields when the user supplies a known ZIP Code.

The City and State fields


are set based on the ZIP
Code value entered.

This sample uses a fixed set of ZIP Codes and correspond City and State values. An
actual application would use a more extensive set.

Running the sample application


To run this sample application, perform the following steps:

1. Extract the .zip archive containing the samples.


In the folder where Visual Studio Tools was installed, locate the Samples.zip
archive. This archive contains both the C# and Visual Basic versions of the
samples. Extract this archive to a location that you have permissions to access.

2. Open the Field Defaulter sample solution.


Using Visual Studio, open the solution file FieldDefaulter.sln for the C# or
Visual Basic version of the sample.

3. Verify the references for the sample solution.


Use Visual Studio to view the references for the project. The Estimate Freight
sample should include references to the following assemblies:

Application.Dynamics
Microsoft.Dexterity.Bridge

If any of these references for the project are not valid, re-add them to the project.

4. Set the Solution Configuration.


Set the Solution Configuration to Release to build the release version of the
application.

PROGRAMMERS GUIDE 185


PA RT 5 IN T E G R A TI O N E XA M P LE S

5. Build the application.


From the Build menu, choose Build Solution. If there are no build errors, the
assembly for the Field Defaulter application will be built.

6. Install the Field Defaulter assembly.


Copy the FieldDefaulter.dll from the Release folder for the project to the AddIns
folder in the Microsoft Dynamics GP installation.

7. Start Microsoft Dynamics GP.


The Field Defaulter sample application will be loaded.

8. Open the Customer Maintenance window.


In Microsoft Dynamics GP, open the Customer Maintenance window.

9. Enter a ZIP Code.


For demonstration purposes, this sample application recognizes only a small
number of ZIP codes. You can enter any of the follow ZIP codes and have the
corresponding City and State filled in:

02109 58104
53151 58474
55111 60605
56560 85012
58078 95014
58102 98052
58103

When you have finished, close Microsoft Dynamics GP.

How Visual Studio Tools was used


This sample application uses the eventing and resource access features of Visual
Studio Tools for Microsoft Dynamics GP.

Resources accessed
The Field Defaulter sample uses the following resources in the Dynamics
dictionary:

Forms
RmCustomerMaintenance

Windows
RmCustomerMaintenance

Events
The Field Defaulter sample registers the following event in Microsoft Dynamics GP:

A change event for the ZipCode field in the Customer Maintenance window,
used to look up the value entered. If the city and state can be found for the ZIP
code value entered, their value are automatically set in the window.

186 P R O G R A M M E R S G U I D E
Chapter 32: Estimate Freight
This sample application demonstrates several techniques useful when creating
Microsoft Dynamics GP integrations. The sample integrates with the Sales
Transaction Entry window. The following topics are discussed:

Overview
Running the sample application
How Visual Studio Tools was used

Overview
This sample application integrates with the Sales Transaction Entry window in
Microsoft Dynamics GP. It retrieves shipping weight information about the items in
the current sales document, calculates an estimated shipping weight for all of the
items, and then estimates the freight cost. The estimated freight value is placed into
the Freight field of the Sales Transaction Entry window.

The Estimate Freight


window estimates freight
for the current sales
document.

This sample uses a fixed set of shipping methods and shipping rates. An actual
application would use a more extensive rate table, and possibly a web service to
access freight rates.

The Estimate Freight sample uses the table access capabilities of Visual Studio Tools
to access data in Microsoft Dynamics GP.

Running the sample application


To run this sample application, perform the following steps:

1. Extract the .zip archive containing the samples.


In the folder where Visual Studio Tools was installed, locate the Samples.zip
archive. This archive contains both the C# and Visual Basic versions of the
samples. Extract this archive to a location that you have permissions to access.

2. Open the Estimate Freight sample solution.


Using Visual Studio, open the solution file EstimateFreight.sln for the C# or
Visual Basic version of the sample.

3. Verify the references for the sample solution.


Use Visual Studio to view the references for the project. The Estimate Freight
sample should include references to the following assemblies:

Application.Dynamics
Microsoft.Dexterity.Bridge
Microsoft.Dexterity.Shell

If any of these references for the project are not valid, re-add them to the project.

PROGRAMMERS GUIDE 187


PA RT 5 IN T E G R A TI O N E XA M P LE S

4. Set the Solution Configuration.


Set the Solution Configuration to Release to build the release version of the
application.

5. Build the application.


From the Build menu, choose Build Solution. If there are no build errors, the
assembly for the Estimate Freight application will be built.

6. Install the Estimate Freight assembly.


Copy the EstimateFreight.dll from the Release folder for the project to the
AddIns folder in the Microsoft Dynamics GP installation.

7. Install the Estimate Freight help file.


Copy the EstimateFreight.chm help file from the EstimateFreight folder into the
Dynamics GP installation folder. The help file should be placed in the same
folder as the GreatPlains.chm help file.

8. Start Microsoft Dynamics GP.


The Estimate Freight sample application will be loaded.

9. Open the Sales Transaction Entry window.


In Microsoft Dynamics GP, open the Sales Transaction Entry window.

10. Display a sales document.


You can display an existing sales document or create a new sales document.

11. Add items to the sales document.


Be sure the sales document has inventory items for which the estimated
shipping weight has been specified.

12. Display the Estimate Freight window.


In the Additional menu, choose Estimate Freight. The Estimate Freight window
will appear.

13. Choose a shipping method and calculate the freight.


Choose either Air or Ground as the shipping method, and then click Calculate
to calculate the estimated freight.

14. Return the Freight amount to the sales document.


Click Save to return the estimated freight amount to the Freight field for the
sales document.

How Visual Studio Tools was used


This sample application uses several features of Visual Studio Tools for Microsoft
Dynamics GP to implement this integration.

User interface
The special WinForm available for Dynamics GP add-ins was used when creating
the Estimate Freight window. The customized buttons and images were also used.
The sample illustrates technique that can be used to implement window-level notes
and the online help link.

188 P R O G R A M M E R S G U I D E
C H A P T E R 3 2 E S T IM AT E FR EI G HT

Resources accessed
The Estimate Freight sample uses many resources in the Dynamics dictionary:

Forms
SOPEntry
FormNote1
FormNote2
FormNote3
FormNote4
FormNote5

Windows
SOPEntry

Global procedures
CheckForNote
CheckNoteIdString
GetNextFormNoteToOpen

Tables
Data from the following tables is accessed to compute the estimated freight for the
current sales document:

IvItemMstr (Inventory Item Master)


SopLineWork (SOP Line Work)

Form-level functions
DexDefaultsRead of the SyVisualStudioHelper form
DexAsk of the SyVisualStudioHelper form
DexError of the SyVisualStudioHelper form
DexWarning of the SyVisualStudioHelper form
DexRuntimeGetClientType of the SyVisualStudioHelper form
DexWinHelpLaunchUrl of the SyVisualStudioHelper form

Events
The Estimate Freight sample registers the following events in Microsoft Dynamics
GP:

A menu handler event for the Sales Transaction Entry form, used to open the
Estimate Freight window.

A form close event on the Sales Transaction Entry form, used to indicate when
the Sales Transaction Entry window has been closed.

A watch event for the SOP Number field in the Sales Transaction Entry
window, used to keep the Estimate Freight window updated with the current
sales document.

An enter event for the Freight field in the Sales Transaction Entry window, used
to ask the user whether they want to estimate the freight amount if a value
hasnt been supplied.

Several form close events for the various Note forms in Microsoft Dynamics
GP, used to keep the Note button on the Estimate Freight window updated.

PROGRAMMERS GUIDE 189


PA RT 5 IN T E G R A TI O N E XA M P LE S

Web client
The Estimate Freight sample uses dynamic rendering to work in the web client.

190 P R O G R A M M E R S G U I D E
Chapter 33: Environmental Details
This sample application demonstrates several techniques useful when creating
Microsoft Dynamics GP integrations. The sample integrates with the Item
Maintenance window. The following topics are discussed:

Overview
Running the sample application
How Visual Studio Tools was used

Overview
This sample application integrates with the Item Maintenance window in Microsoft
Dynamics GP. It stores environmental information about the item. The additional
data is stored in the DUOS (Dynamics User Object Store) table for the current
company.

The Environmental Details


window tracks environmental
information for the current
inventory item.

This sample also implements support for the macro system, allowing macros to be
recorded and played back for this window.

Running the sample application


To run this sample application, perform the following steps:

1. Extract the .zip archive containing the samples.


In the folder where Visual Studio Tools was installed, locate the Samples.zip
archive. This archive contains both the C# and Visual Basic versions of the
samples. Extract this archive to a location that you have permissions to access.

2. Open the Environmental Details sample solution.


Using Visual Studio, open the solution file EnvironmentalDetails.sln for the C#
or Visual Basic version of the sample.

3. Verify the references for the sample solution.


Use Visual Studio to view the references for the project. The Environmental
Details sample should include references to the following assemblies:

Application.Dynamics
Microsoft.Dexterity.Bridge
Microsoft.Dexterity.Shell

If any of these references for the project are not valid, re-add them to the project.

4. Set the Solution Configuration.


Set the Solution Configuration to Release to build the release version of the
application.

PROGRAMMERS GUIDE 191


PA RT 5 IN T E G R A TI O N E XA M P LE S

5. Build the application.


From the Build menu, choose Build Solution. If there are no build errors, the
assembly for the Environmental Details application will be built.

6. Install the Environmental Details assembly.


Copy the EnvironmentalDetails.dll from the Release folder for the project to the
AddIns folder in the Microsoft Dynamics GP installation.

7. Start Microsoft Dynamics GP.


The Estimate Freight sample application will be loaded.

8. Open the Item Maintenance window.


In Microsoft Dynamics GP, open the Item Maintenance window.

9. Display an item.
You can display an existing item or create a new item.

10. Display the Environmental Details window.


In the Additional menu, choose Environmental Details. The Environmental
Details window will appear.

11. Supply the environmental details for the item.


Enter the following environmental details:

Yearly energy cost


Notes
Recyclable
Energy Star Rated

12. Save the changes to the item.


Click Save in the Item Maintenance window to save the changes for the item.

How Visual Studio Tools was used


This sample application uses several features of Visual Studio Tools for Microsoft
Dynamics GP to implement this integration.

User interface
The special WinForm available for Dynamics GP add-ins was used when creating
the Environmental Details window.

Resources accessed
The Estimate Freight sample uses many resources in the Dynamics dictionary:

Forms
IvItemMaintenanceForm

Windows
IvItemMaintenanceWindow

Tables
Data for the integration is stored in the following table:

SyUserObjectStoreTable (DUOS)

192 P R O G R A M M E R S G U I D E
C H A P T E R 3 3 E N V IR O N M EN T A L D E T AIL S

This is the same table used by VBA to store data. The DUOSHelper class of the
Environmental Details sample contains methods that are used to write, retrieve,
and delete rows from the DUOS table.

Form-level functions
DexError of the SyVisualStudioHelper form

Events
The Environmental Details sample registers the following events in Microsoft
Dynamics GP:

A menu handler event for the Item Maintenance form, used to display the
Environmental Details form.

A form open event on the Item Maintenance form, used to create an instance of
the Environmental Details form.

A form close event on the Item Maintenance form, used to indicate when the
Item Maintenance window has been closed. This event closes the
Environmental Details form and removes it from memory.

A change event for the Item Number field in the Item Maintenance window,
used to keep the Environmental Details window updated with the current item
being displayed.

A change event for the Item Description field in the Item Maintenance window,
used to keep the Environmental Details window updated with the current item
being displayed.

A change event for the Save Record field in the Item Maintenance window,
used to save the environmental details when the user saves the item.

An after modal dialog event for the Item Maintenance window, used to retrieve
the response when the user confirms whether to delete the current item. If the
user chooses to delete the current item, the corresponding environmental
details information is also deleted.

Macro support
Calls to the RecordMacroItem() method have been added to the controls in the
Environmental Details form to support recording macro statements. The
PlayMacroItem() method from the DexUIForm base class has been overridden to
support playback of the macro statements that have been recorded.

Web client
The Environmental Details sample uses dynamic rendering to work in the web
client.

PROGRAMMERS GUIDE 193


194 P R O G R A M M E R S G U I D E
Chapter 34: Lookups
This sample application demonstrates how to use several common lookup forms in
Microsoft Dynamics GP. The following topics are discussed:

Overview
Running the sample application
How Visual Studio Tools was used

Overview
This sample application demonstrates how to implement common lookup forms in
a Visual Studio Tools integration. Refer to Chapter 14, Using Lookups, for details
about how to implement lookups.

This sample implements the following lookups:

Customer Number
Vendor ID
Item Number
GL Account Number
SOP Document Number
POP Document Number
.
Running the sample application
To run this sample application, perform the following steps:

1. Extract the .zip archive containing the samples.


In the folder where Visual Studio Tools was installed, locate the Samples.zip
archive. This archive contains both the C# and Visual Basic versions of the
samples. Extract this archive to a location that you have permissions to access.

2. Open the Lookups sample solution.


Using Visual Studio, open the solution file Lookups.sln for the C# or Visual
Basic version of the sample.

3. Verify the references for the sample solution.


Use Visual Studio to view the references for the project. The Lookups sample
should include references to the following assemblies:

Application.Dynamics
Application.SmartList
Microsoft.Dexterity.Bridge
Microsoft.Dexterity.Shell

If any of these references for the project are not valid, re-add them to the project.

PROGRAMMERS GUIDE 195


PA RT 5 IN T E G R A TI O N E XA M P LE S

4. Set the Solution Configuration.


Set the Solution Configuration to Release to build the release version of the
application.

5. Build the application.


From the Build menu, choose Build Solution. If there are no build errors, the
assembly the for the Lookups application will be built.

6. Install the Lookups assembly.


Copy the Lookups.dll from the Release folder for the project to the AddIns
folder in the Microsoft Dynamics GP installation.

7. Start Microsoft Dynamics GP.


The Lookups sample application will be loaded.

8. Open the About Box window.


In Microsoft Dynamics GP, open the About Box window. It is accessed from the
Help menu in the main Microsoft Dynamics GP window.

9. Display the Lookups window.


In the Additional menu, choose Lookups. The Lookups window will appear.

10. Use the sample lookups.


Use the sample lookups, just as you would any other lookups in Microsoft
Dynamics GP.

How Visual Studio Tools was used


This sample application uses the basic features of Visual Studio Tools for Microsoft
Dynamics GP.

User interface
The special WinForm available for Dynamics GP add-ins was used when creating
the Lookups window.

Resources accessed
The Lookups sample uses the following resources in the Dynamics and SmartList
dictionaries:

Forms
AboutBox
CustomerLookupForm
VendorLookupForm
IvItemNumberLookupForm
AccountLookupForm
SopDocumentLookupForm
PopDocumentLookupForm

Composites
AccountNumberCompositeData

Form-level functions
ConvertAcctToStr of the GlAcct form

196 P R O G R A M M E R S G U I D E
C H A P T E R 3 4 L O O K U P S

Events
The Lookups sample registers the following events in Microsoft Dynamics GP:

A menu handler event for the AboutBox form, used to open the Lookups
window.

A click event for the SelectButton field in each of the lookup windows, to notify
the Lookups sample that the user clicked the Select button.

A validate event for the PopPoLookup field in the PopDocumentLookup


window, to prevent the validation from running when the POP Number lookup
is opened from a Visual Studio Tools integration. This is a work-around for an
issue that causes the POP Number lookup to be closed immediately after being
opened.

Web client
The Lookups sample uses dynamic rendering to work in the web client.

PROGRAMMERS GUIDE 197


198 P R O G R A M M E R S G U I D E
Chapter 35: Salesperson Analysis
This sample application demonstrates how to use a listview control in a Visual
Studio Tools form. The listview control is not one of the standard controls
supported by automatic rendering in the Microsoft Dynamics GP web client.
Custom rendering was implemented so this application could be used on the web
client. The following topics are discussed:

Overview
Running the sample application
How Visual Studio Tools was used

Overview
The Salesperson Analysis sample integrates with the Salesperson Maintenance
window in Microsoft Dynamics GP. It displays a list of the customers that have the
currently-selected salesperson assigned to them. It also lists the year-to-date sales
for each customer.

The Salesperson Analysis


window displays information
for customers assigned to a
salesperson.

This sample uses a listview control, which is not supported by dynamic rendering
in the Microsoft Dynamics GP web client. This sample implements custom
rendering so that it can be used in the web client.

A Silverlight window that


implements custom
rendering is used in the
web client.

Running the sample application


The Salesperson Analysis sample application is composed of two assemblies. The
Visual Studio Tools assembly is the standard .NET assembly that is created for all
add-ins. The sample also has a Silverlight .xap file that contains the Silverlight
application that runs on the web client. Regardless of the type of client you are
using, you must build the .NET assembly. If you are going to run the sample in a
Microsoft Dynamics GP web client installation, you must also build the Silverlight
application.

PROGRAMMERS GUIDE 199


PA RT 5 IN T E G R A TI O N E XA M P LE S

Building the .NET assembly


To build and run the .NET assembly for the Salesperson Analysis sample, perform
the following steps:

1. Extract the .zip archive containing the samples.


In the folder where Visual Studio Tools was installed, locate the Samples.zip
archive. This archive contains both the C# and Visual Basic versions of the
samples. Extract this archive to a location that you have permissions to access.

2. Open the Salesperson Analysis sample solution.


Using Visual Studio, open the solution file SalespersonAnalysis.sln for the C#
or Visual Basic version of the sample.

3. Verify the references for the sample solution.


Use Visual Studio to view the references for the project. The Salesperson
Analysis sample should include references to the following assemblies:

Application.Dynamics
Microsoft.Dexterity.Bridge
Microsoft.Dexterity.Shell

If any of these references for the project are not valid, re-add them to the project.

4. Set the Solution Configuration.


Set the Solution Configuration to Release to build the release version of the
application.

5. Build the application.


From the Build menu, choose Build Solution. If there are no build errors, the
assembly the for the Lookups application will be built.

6. Install the Salesperson Analysis assembly.


Copy the SalespersonAnalysis.dll from the Release folder for the project to the
AddIns folder in the Microsoft Dynamics GP installation.

7. Start the Microsoft Dynamics GP desktop client.


The Salesperson Analysis sample application will be loaded. Log in to
Microsoft Dynamics GP and select a company.

8. Open the Salesperson Maintenance window.


In Microsoft Dynamics GP, open the Salesperson Maintenance window.

9. Select a salesperson.
In the Salesperson Maintenance window, select a salesperson.

10. Display the Salesperson Analysis window.


In the Additional menu, choose Salesperson Analysis. The Salesperson Analysis
window will appear.

11. Examine the customers for the salesperson.


The customers for the selected salesperson will be listed, along with the year-to-
date sales information. You can select a customer in the list and then click View
Customer to display the Customer Inquiry window to view detailed
information about the customer.

200 P R O G R A M M E R S G U I D E
C H A P T E R 3 5 S A L E S P E R S O N A N A LY S I S

Silverlight application
To build and install the Silverlight application for the Salesperson Analysis sample,
perform the following steps:

1. Install the Silverlight prerequisites.


Follow the guidelines in Requirements for developing with Silverlight on page 120
to install the prerequisites needed for doing Silverlight development.

2. Retrieve the Microsoft Dynamics GP web client assemblies.


Using the procedure described in Referencing web client assemblies on page 122,
obtain the following three assemblies:

Microsoft.Dynamics.GP.Web.Silverlight
Microsoft.Dynamics.GP.Web.UI.Silverlight
Microsoft.Dynamics.GP.Web.UI.Silverlight.Controls

Copy the assemblies to a folder named GP Silverlight Assemblies that you


created at the root of the C: drive.

3. Open the Salesperson Analysis SL sample solution.


Using Visual Studio, open the solution file SalespersonAnalysisSL.sln for the C#
or Visual Basic version of the sample. This is the solution for the Silverlight
component of the sample.

4. Verify the references for the sample solution.


Use Visual Studio to view the references for the project. The Salesperson
Analysis SL sample should include references to the three assemblies that you
extracted from the .xap file for the web client:

Microsoft.Dynamics.GP.Web.Silverlight
Microsoft.Dynamics.GP.Web.UI.Silverlight
Microsoft.Dynamics.GP.Web.UI.Silverlight.Controls

If any of these references for the project are not valid, re-add them to the project
by referencing the assemblies that you extracted.

Be sure that you set the CopyLocal property for the assembly references to False. This
is important so that the .xap file you are creating will be loaded correctly.

5. Set the Solution Configuration.


Set the Solution Configuration to Release to build the release version of the
Silverlight .xap file.

6. Build the solution.


From the Build menu, choose Build Solution. If there are no build errors, the
.xap file for the Salesperson Analysis sample will be built.

7. Install the Salesperson Analysis .xap file.


Copy the SalespersonAnalysisSL.xap from the Release folder for the project to
the \WebClient\ClientBin folder in the Microsoft Dynamics GP installation on
the web client server.

8. Start the Microsoft Dynamics GP web client.


The Salesperson Analysis assembly will be loaded, along with the Silverlight
.xap file. Log in to Microsoft Dynamics GP and select a company.

PROGRAMMERS GUIDE 201


PA RT 5 IN T E G R A TI O N E XA M P LE S

9. Open the Salesperson Maintenance window.


In Microsoft Dynamics GP, open the Salesperson Maintenance window. Select a
salesperson and then choose Salesperson Analysis from the Additional menu.
The web client version of the Salesperson Analysis window will be displayed.
You can use this window just as you would the version in the Microsoft
Dynamics GP desktop client.

How Visual Studio Tools was used


This sample application uses the several features of Visual Studio Tools for
Microsoft Dynamics GP.

User interface
The special WinForm available for Dynamics GP add-ins was used when creating
the Salesperson Analysis window that is displayed on the Microsoft Dynamics GP
desktop client.

Resources accessed
The Salesperson Analysis sample uses the following resources in the Dynamics
dictionary:

Forms
RmSalespersonForm

Windows
RmSalespersonWindow

Tables
RmCustomerMstr
RmCustomerMstrSum

Form-level functions
DexError of the SyVisualStudioHelper form
DexWarning of the SyVisualStudioHelper form
DexRuntimeGetClientType of the SyVisualStudioHelper form

Events
The Salesperson Analysis sample registers the following events in Microsoft
Dynamics GP:

A menu handler event for the Salesperson Maintenance form, used to open the
Salesperson Analysis window.

A form open event on the Salesperson Maintenance form, used to create an


instance of the Salesperson Analysis form.

A form close event on the Salesperson Maintenance form, used to indicate when
the Salesperson Maintenance window has been closed. This event closes the
Salesperson Analysis form and removes it from memory.

A change event for the Salesperson ID field in the Salesperson Maintenance


window, used to keep the Salesperson Analysis window updated with the
customers for the current salesperson.

202 P R O G R A M M E R S G U I D E
C H A P T E R 3 5 S A L E S P E R S O N A N A LY S I S

Web client
The Salesperson Analysis sample uses custom rendering to work in the web client.
This means it has a separate Silverlight .xap file that defines the Salesperson
Analysis window that is displayed on the web client.

Events sent from the server


The following events are sent from the add-in running on the server to the
Silverlight component running on the web client:

TransferSalespersonID - Transfers the values in the Salesperson ID control to


the web client.

TransferCustomerData - Transfers the customer data in the listview control to


the web client.

OpenSalespersonAnalysisForm - Opens the Salesperson Analysis form in the


Silverlight application on the web client.

ShowSalespersonAnalysisForm - Causes the Salesperson Analysis form in the


Silverlight application to become visible.

CloseSalespersonAnalysisForm - Closes the Salesperson Analysis form in the


Silverlight application on the web client.

SetCustomerSelection - Sends the index of the item selected in the customers list
on server so that the corresponding item is selected in the web client.

Events sent from the client


The following events are sent from the Silverlight component running on the web
client to the add-in running on the server:

SetSelectedCustomer - Sends the index of the item selected in the customers list
on the web client so that the corresponding item is selected on the server.

ViewSelectedCustomer - Causes the View Customer button to be activated on


the server.

CloseSalespersonAnalysis - Closes the Salesperson Analysis window on the


server.

PROGRAMMERS GUIDE 203


204 P R O G R A M M E R S G U I D E
Glossary Forms dictionary
The dictionary in a Microsoft Dynamics GP
installation that contains the modified forms
Active lock for an application. Each application
A method of locking that ensures only one dictionary can have a forms dictionary.
user can change or delete the contents of a
row at one time. The data in the locked row Global fields
cant be changed or deleted by another user A type of field that can be used in any form
until the lock is released. or any table in Microsoft Dynamics GP.

Alternate forms Global variables


Forms from the core Dynamics dictionary A variable available the entire time the
that have been changed by a third-party Microsoft Dynamics GP application is open.
developer, and are stored in a third-party Visual Studio Tools code can read the value
dictionary. of global variables.

Application assembly Key


A .NET assembly used by Visual Studio A field or combination of fields within a row
Tools to provide access to the resources in that is used as the basis by which to store,
Microsoft Dynamics GP dictionary. Each retrieve, and sort the row in a table.
application dictionary can have one Launch file
corresponding application assembly.
A file that is used to start an application with
Buffer the Dynamics GP runtime engine. This file
A temporary storage area in a computers stores the location of the main application
memory. The Microsoft Dynamics GP dictionary, the name and location of any
runtime uses several types of buffers, such as forms and reports dictionaries, and the name
table buffers and window buffers. and location of any integrating dictionaries.

Control area Local fields


A band drawn at the top of a Microsoft Special fields that are defined for and used
Dynamics GP window. Controls such as only within a specific form in Microsoft
Save, Clear, and Delete buttons are placed in Dynamics GP.
the control area. Modified forms
Custom rendering Forms in the Microsoft Dynamics GP
application that contain modifications made
with the Modifier.
Dictionary Assembly Generator
The tool (DAG.exe) used to build application Passive lock
assemblies for dictionaries. A method of locking that allows other users
to access and make changes to the row.
Dexterity Bridge assembly
The assembly Microsoft.Dexterity.Bridge.dll Product ID
that provides the access to events in An integer ID that is used to uniquely
Microsoft Dynamics GP, as well as the identify an application dictionary. The
resources in the application dictionaries. Dictionary Assembly Generator refers to
dictionaries based on their product ID.
Dictionary class
A class used to reference the resources in an Segments
application dictionary. The class is available One field of the group of fields that compose
after a reference to the application assembly a key for a table.
for a dictionary has been added to the Visual Status area
Studio project.
An area at the bottom of a Microsoft
Dexterity Shell assembly Dynamics GP window created by a divider
The assembly Microsoft.Dexterity.Shell. line drawn across the window. Controls like
UI.dll that provides the drawing capabilities browse buttons, note buttons, and help
that allow an integrating application to buttons are placed in the status area.
match the appearance of Microsoft Table buffer
Dynamics GP A buffer that acts as an intermediate storage
Dynamic rendering area to hold one row from a table.
A form of rendering where the Microsoft .Xap file
Dynamics GP web client automatically
A packaged version of a Silverlight
creates and displays a Silverlight form,
application, with the .xap file extension.
based on the definition of the .NET form.

PROGRAMMERS GUIDE 205


206 P R O G R A M M E R S G U I D E
Index buttons (continued)
standard 29
commands (continued)
types of 165
status area 30 components, installed with Visual Studio
A toolbar 29 Tools 9
Accessing Dictionary Resources, chapter toolbar with separator 30 components of composites
37-40 types of 29 accessing through code 179
ActivateAfterOriginal, window event 144 ButtonType property, for button controls defined 177
ActivateBeforeOriginal, window event 29 retrieving number of components 181
144 composite fields
active locks C events for 182
defined 205 C# methods for 179
described 59 registering events 41 properties for 181
releasing 59 setting assembly information 65 composites
add-ins unregistering events 44 accessing components 179
enabling for web client 107 upgrading integrations 15 accessing through code 177
specifying supported client types 66 cancelling events 44 as procedure and function
AddIns folder, described 12 Change parameters 178
Additional menu, adding items to 139 composite field event 182 as variables 178
AddMenuHandler(), form method 139 window field event 156 as window fields 177
AfterModalDialog, window event 146 Change(), table method 158 chapter 177-182
alternate forms ChangeFirst(), table method 158 defined 177
accessing with code 72 ChangeLast(), table method 159 resource reference 177
creating application assembly for 72 ChangeNext(), table method 159 retrieving number of components 181
defined 205 ChangePrevious(), table method 159 types of 177
guidelines for accessing 73 Check(), command method 165 control area
using try...catch with 73 Clear() defined 205
application assemblies composite field method 179 described 26
creating 33 table field method 163 Control Reference, chapter 29-32
defined 205 table method 159 ControlArea, WinForms property 26
described 12 window field method 154 controls
installing 7 ClickAfterOriginal, window field event adding to forms 27
naming convention 33 156 buttons 29
overriding name 36 ClickBeforeOriginal, window field event combo boxes 32
references to 37 156 control reference 29
referencing main application client labels 32
assembly 36 retrieving type of 97 list boxes 32
shipped with Visual Studio Tools 12 specifying add-in support 66 supported for dynamic rendering 108
signing 35 client type, determining 133 text boxes 31
which to use 33 Clone(), table method 159 conventions, in documentation 3
architecture, for Visual Studio Tools 11 Close() Copy Local property, described 123
Ask() function, see DexAsk() function form method 141 custom messaging interface, for custom
assembly information, for integrations 65 table method 159 rendering 117
asynchronous processes, handling for window method 143 custom rendering
macro playback 78 CloseAfterOriginal adding a Silverlight window 123
attributes, using to specify supported form event 142 chapter 117-132
clients 66, 107 window event 144 custom messagng interface 117
AutoSetDexColors CloseBeforeOriginal described 108, 117
control property 29 form event 142 initializing messaging 119
WinForms property 26 window event 144 message examples 126
combo box controls, described 32 message proxy 125
B command-line, for Dictionary Assembly message rejection 129
background process error, when not Generator 34 messages used for 124
closing tables 49 Commands, form property 141 receiving messages 126
BeforeModalDialog, window event 145 commands session recovery 127
buffers, defined 205 accessing through code 165 when to use 117
building a Silverlight project 132 chapter 165-166 writing to trace log 130
Building and Deploying, chapter 65-68 command list commands 165 Customization Status window 70
building integrations 67 form commands 165
buttons methods for 165 D
field 30 resource reference 165 DAG.exe, see Dictionary Assembly
pictures for 30 script commands 165 Generator

PROGRAMMERS GUIDE 207


IN DEX

Data folder, returning path to 96 Dictionary Assembly Generator Error() function, see DexError() function
Debug, solution configuration 67, 132 (continued) errors, for table operations 54
debugging using 34 Estimate Freight
attaching to a process 69 when to use 33 overview 187
chapter 69-70 where installed 34 running 187
examining application 70 dictionary class sample integration 187
integrations 69 defined 205 use of Visual Studio Tools 188
preparations for 69 examples 38 event arguments, when playing macros 76
when using web client 135 for alternate forms 72 events
defaults file, returning path to 96 for modified forms 71 cancelling events 44
deleting, rows from tables 53 resource types to access 38 chapter 41-45
deploying integrations 68 using to access dictionary resources disabling 70
desktop client 38 event arguments 43
determining if being used 133 dictionary resources overview 41
specifying support for 66 accessing 37 registering 41
Developing for the Web Client, chapter accessing through dictionary class 38 registering with C# code 41
133-135 additional resources 39 registering with Visual Basic code 42
Developing Integrations, part 24-73 list of 138 responding to 43
devenv.exe, using to register templates 8 lists in IntelliSense 38 supported by dynamic rendering 112
Dex.ini namespace for accessing 38, 39 unregistering 44
reading values from 87 variable for 39 unregistering with C# code 44
returning path to 96 working with 138 unregistering with Visual Basic code
writing values to 88 Disable() 45
DexAsk() function 85 command method 165 exceptions
DexDefaultsRead() function 87 composite field method 180 example 73
DexDefaultsWrite() function 88 window field method 154 handling for modified and alternate
DexError() function 89 disabling events 70 forms 73
DexFileGetTempDirectory() function 90 Dispose(), form method 141
DexFileLaunch() function 91 documentation, symbols and conventions F
DexGetmsg() function 93 3 field, buttons 30
DexGetstring() function 95 dynamic rendering Field Defaulter
DexPathGetForApp() function 96 chapter 111-116 overview 185
DexPlatforms attribute value 66, 107 defined 205 sample integration 185
DexRuntimeGetClientType() function 97 described 108, 111 use of Visual Studio Tools 186
DexRuntimeGetWebClientTrustLevel() enabling 111 fields
function 99 form and control reference 112 global 205
Dexterity Bridge assembly properties and events supported 112 local 205
defined 205 supported controls 108, 111 table fields 163
described 11 WCCompliantWindow attribute 111 window fields 153
Dexterity Shell assembly when to use 111 file access, for web client 134
defined 205 Dynamics.exe, application process when files
described 11 debugging 69 see also tables
DexUtilityLaunchUrl() function 100 Dynamics.exe.config, using to register launching from code 91
DexWarning() function 101 add-ins 67 Fill()
DexWinHelpLaunchUrl() 102 composite field method 180
dialog boxes E table field method 163
DexAsk() function 85 Enable() table method 160
DexError() function 89 command method 166 window field method 154
DexGetstring() function 95 composite field method 180 focus, removing from current window 143
DexWarning() function 101 window field method 154 Focus()
Dictionary Assembly Generator EnterAfterOriginal composite field method 180
application assembly 33 composite field event 182 window field method 154
chapter 33-36 window field event 156 ForceValidate()
commands for 34 EnterBeforeOriginal composite field method 180
creating application assemblies 33 composite field event 182 window field method 154
defined 205 window field event 156 form-level functions
described 12, 33 Environmental Details accessing through code 173
IntelliSense data file 34 overview 191 described 173
launch file used 35 running 191 form-level procedures
optimizing processing 36 sample integration 191 accessing through code 169
output from 33 use of Visual Studio Tools 192 described 169

208 P R O G R A M M E R S G U I D E
I N D E X

form-level table buffers H L


accessing 157 help content, displaying in web client 102 label controls
described 48, 157 helper functions described 32
forms chapter 83-103 linked field 32
accessing through code 139 overview 83 launch file
chapter 139-142 reference 83 defined 205
closing when using web client 134 using with an integration 83 returning path to 96
events for 142 Hide() used by Dictionary Assembly
methods for 139 command method 166 Generator 35
properties for 141 composite field method 180 launching files through code 91
resource reference 139 window field method 154 LeaveAfterOriginal
forms dictionaries composite field event 182
application assemblies for 33, 71 I window field event 156
defined 205 Implementing Macro Support, chapter LeaveBeforeOriginal
generating application assembly for 75-78 composite field event 182
35 Initialize() method, for registering events window field event 156
function, events for 174 41 Length, composite field property 181
Functions, form property 141 initializng messaging 119 light bulb symbol 3
functions installation LineChangeAfterOriginal, scrolling
changing parameter values 176 chapter 7-10 window event 151
changing return values 176 Visual Studio Tools SDK 7 LineChangeBeforeOriginal, scrolling
chapter 173-176 Integration Basics, chapter 11-13 window event 151
invokable procedures 176 Integration Examples, part 184-203 LineDeleteAfterOriginal, scrolling
learning parameters 175 integrations window event 151
learning return value 175 building 67 LineDeleteBeforeOriginal, scrolling
methods for 174 debugging 69 window event 151
optional parameters 174 deploying 68 LineEnterAfterOriginal, scrolling window
parameter types 174 setting assembly information 65 event 150
parameters for 175 IntelliSense, table information in 48 LineEnterBeforeOriginal, scrolling
resource reference 173 IntelliSense XML files window event 150
return value 174 described 12 LineFillAfterOriginal, scrolling window
generating 34 event 150
G installing 7 LineFillBeforeOriginal, scrolling window
Get(), table method 160 naming convention 34 event 149
GetFirst(), table method 160 Invoke() LineInsertAfterOriginal, scrolling
GetLast(), table method 160 function method 174 window event 151
GetNext(), table method 160 procedure method 170 LineInsertBeforeOriginal, scrolling
GetPrevious(), table method 160 IsAsynchEventPending() method 78 window event 151
Getstring() function, see DexGetstring() IsChanged, window property 143 LineLeaveAfterOriginal, scrolling
function IsEmpty window event 151
Getting Started, part 6-13 composite field property 181 LineLeaveBeforeOriginal, scrolling
global defaults file, returning path to 96 global property 167 window event 151
global fields, defined 205 table field property 164 LinkField property, for label controls 32
global functions window field property 155 list box controls, described 32
accessing through code 173 IsFilled local fields
described 173 composite field property 181 accessing 153
global procedures global property 168 defined 205
accessing through code 169 table field property 164 described 153
described 169 window field property 155 naming convention for 153
global table buffers IsOpen Lock()
accessing 157 form property 141 composite field method 180
described 48, 157 window property 143 window field method 154
shared access 48, 157 IWCCustomMessagingAddIn interface locking
globals 117 active locking 59
accessing through code 167
multiuser scenarios 59
chapter 167-168 K passive locking 59
defined 205 Key, table property 161 releasing locks 59
properties for 167 keys rows 59
resource reference 167 defined 205 lookups
for tables 50 available to use in Visual Studio
segments for 50 Tools 80

PROGRAMMERS GUIDE 209


IN DEX

lookups (continued) modal dialogs (continued) procedures


example 80 for web client 134 changing parameter values 171
operation of 79 Modified and Alternate Forms, chapter chapter 169-172
using existing lookup windows 79 71-73 events for 170
Lookups sample modified forms invokable procedures 172
integration 195 accessing with code 71 learning parameters 171
overview 195 creating application assembly for 71 methods for 169
running 195 defined 205 optional parameters 170
use of Visual Studio Tools 196 guidelines for accessing 73 parameter types 170
using try...catch with 73 parameters for 171
M using with Visual Studio Tools 71 resource reference 169
macro support multiuser processing process, attaching to Dynamics.exe for
asynchronous processes 78 described 59 debugging 69
for Visual Studio Tools forms 75 reading rows 61 ProcessMessage() method, for receiving
macro syntax 75 removing rows 62 messages 126
overview 75 updating rows 61 product ID, defined 205
playing macros 76 product support, for Visual Studio Tools
recording macros 75 N for Microsoft Dynamics GP 3
main dictionary names, overriding application assembly projects
generating application assembly for name 36 adding a Dynamics GP form to 25
35 namespace, for accessing dictionary creating for Visual Studio Tools 12,
overriding application assembly resources 38, 39 121
name 36 properties, supported by dynamic
margin notes 3 O rendering 112
menus, adding to Additional menu 139 online help content, displaying in web PullFocus(), window method 143
message proxy client 102
SendMessage() method 125 Open() R
SendMessages() method 125 form method 141 RangeClear(), table method 160
use for custom rendering 125 window method 143 RangeEnd(), table method 160
message rejection OpenAfterOriginal RangeRemove(), table method 160
example 129 form event 142 ranges
for custom rendering 129 window event 144 example 55, 56, 57
Revert() method 129 OpenBeforeOriginal for table access 55
storing prior values 129 form event 142 multi-segment key 56
message resources, retrieving from window event 144 removing rows in a range 57
application dictionary 93 optimistic concurrency control, described simple key 55
MessageBox class, support on web client 59 RangeStart(), table method 160
109 optimizing, application assembly recording macro statements 75
messages generation 36 RecordMacroItem() method, described 75
examples for custom rendering 126 Recover() method, use for session
for custom rendering 124 P recovery 127
how used for custom rendering 124 parameters recovery, session recovery for web client
parameters for 124 for functions 175 127
receiving messages for custom for procedures 171 references, to application assemblies 37,
rendering 126 optional parameters 170, 174 71, 72
rejected by server 129 passive locks registering events 41
sending messages for custom defined 205 registering Visual Studio templates 8
rendering 124 described 59 regular expressions, for parsing macro
structure of 124 releasing 59 statements 77
messaging, initializing 119 paths, path for the runtime engine 96 Release, solution configuration 67, 132
Microsoft Dynamics GP per-user defaults file, returning path to 96 Release(), table method 161
events in 41 PlayMacroItem() method, overriding 76 releasing locks on table rows 59
tables 47 prerequisites Remove(), table method 161
Microsoft Dynamics GP SDK for doing Silverlight development removing rows
installing 3 120 from tables 53
table information in 48 for using Visual Studio Tools for multiuser considerations 62
modal dialogs Microsoft Dynamics GP 3 rendering
DexAsk() function 85 PrintAfterOriginal, window event 144 custom 117
DexError() function 89 PrintBeforeOriginal, window event 144 custom rendering 108
DexGetstring() function 95 printing files through code 91 dynamic 111
DexWarning() function 101 Procedures, form property 141 dynamic rendering 108

210 P R O G R A M M E R S G U I D E
I N D E X

Resource Descriptions tool, described 47 session recovery tables (continued)


Resource Reference, part 138-176 considerations 127 closing 49
resources, see dictionary resources example 128 errors from table operations 54
responding to events 43 for custom rendering 127 in Microsoft Dynamics GP 47
retrieving rows SET files, see launch files keys for 50
from tables 50 sharing global table buffers 48 learning about 47
multiuser considerations 61 Show() methods for 158
Revert() method, for message rejection 129 command method 166 multiuser processing 59
row locking composite field method 180 opening 49
active locking 59 window field method 155 properties for 161
described 59 signing, application assemblies 35 ranges 55
passive locking 59 Silverlight removing rows 53
releasing locks 59 building a project 132 resource reference 157
rows building and deploying application retrieving rows 50
locking 59 131 saving rows 51
removing from tables 53 requirements for doing development updating rows 52
retrieving from tables 50 120 working with 47
saving in tables 51 web client extension information 131 technical support, for Visual Studio Tools
updating in tables 52 Silverlight 5 Developer Runtime 120 for Microsoft Dynamics GP 3
Run(), command method 166 Silverlight 5 SDK 120 templates
runtime components, for Visual Studio Silverlight 5 Toolkit 120 for Visual Studio 2010 7
Tools 11 Silverlight 5 Tools for Visual Studio 120 for Visual Studio 2012 7
runtime engine Silverlight project manually registering 8
retrieving type of 97 adding a window to 123 temporary directory, retrieving location
returning the path for 96 for web client add-in 121 90
RunValidate() referencing web client assemblies 122 text box controls 31
composite field method 180 SN.exe, described 35 third-party applications, application
window field method 155 solution configuration, for a Visual Studio assemblies for 33
project 67, 132 toolbar, button type 29
S standard buttons 29 toolbar with separator, button type 30
Salesperson Analysis sample status area trust level, for web client 99
integration 199 buttons 30 try...catch, using with modified and
overview 199 defined 205 alternate forms 73
running 199 described 26
use of Visual Studio Tools 202 StatusArea, WinForms property 26 U
sample integrations strong name key file, described 35 Uncheck(), command method 166
Environmental Details 191 strong names, for application assemblies Unlock()
Estimate Freight 187 35 composite field method 180
Field Defaulter 185 support, for Visual Studio Tools for window field method 155
installing 7 Microsoft Dynamics GP 3 unregistering events 44
Lookups 195 SupportedDexPlatforms, attribute 66, 107 updating rows
Salesperson Analysis 199 symbols in documentation 3 in tables 52
Save(), table method 161 multiuser considerations 61
saving, rows in tables 51 T Upgrading an Integration, chapter 15-21
scrolling windows table buffers upgrading integrations
accessing current row 150 defined 205 C# integrations 15
accessing through code 149 described 48, 157 described 15
chapter 149-151 form-level 48 from Release 10 or later 20
described 149 global 48 from Release 9 15
events for 149 sharing access 48 Visual Basic integrations 17
preventing rows from displaying 150 table fields URLs, displaying in web browser 100
resource reference 149 accessing through code 163 user interface, for Visual Studio Tools
SDK, for Microsoft Dynamics GP 3, 80 chapter 163-164 projects 25
segments methods for 163 Using Lookups, chapter 79-82
defined 205 properties for 164
for keys 50 resource reference 163 V
SendMessage() method, for custom table ranges, example 55, 56, 57 ValidateAfterOriginal
rendering 125 Tables, form property 141 composite field event 182
SendMessages() method, for custom tables window field event 156
rendering 125 accessing through code 48, 157 ValidateBeforeOriginal
chapter 157-161 composite field event 182

PROGRAMMERS GUIDE 211


IN DEX

ValidateBeforeOriginal (continued) web client runtime log, writing to 130


window field event 156 window fields
Value accessing through code 153
composite field property 181 chapter 153-156
global property 168 events for 156
table field property 164 methods for 153
window field property 155 properties for 155
variables, for dictionary resources 39 resource reference 153
Visual Basic windows
registering events 42 accessing through code 143
setting assembly information 66 adding to Silverlight project 123
unregistering events 45 chapter 143-147
upgrading integrations 17 events for 144
Visual Studio local fields 153
upgrading to Visual Studio 2010 9 methods for 143
version required for Visual Studio properties for 143
Tools 3 resource reference 143
Visual Studio Tools WinForms
accessing modified forms 71 adding controls to 27
architecture 11 adding to a project 25
capabilities 11 chapter 25-27
components installed 9 properties for 26
creating user interface 25 Working with Tables, chapter 47-63
development components 12
prerequisites 3 X
projects, creating 12 .xap file
runtime components 11 building 132
SDK installation 7 defined 205
technical support 3 extracting assemblies from 122
installing 132
W optimizing size 132
warning symbol 3 XML files, for IntelliSense 12
Warning() function, see DexWarning()
function
WCCompliantWindow attribute 111
web browser, displaying content in 100
web client
closing forms on 134
custom rendering 108, 117
debugging Visual Studio Tools
integrations 135
determining if being used 133
developing add-ins for 133
displaying online help content 102
dynamic rendering 108, 111
extension information 131
form rendering 108
local file acces 134
modal dialogs 134
overview 107-109
part 106-135
retrieving trust level of 99
specifying support for 66, 107
writing code for 108
web client add-in project
adding a window to 123
creating 121
referencing web client assemblies 122
web client assemblies, referencing 122
web client extension information, for
Silverlight application 131

212 P R O G R A M M E R S G U I D E

Potrebbero piacerti anche