Wednesday, December 15, 2010

Using Silverlight with Access – Part II

The first release was more of a concept. The focus of this release was to improve the Silverlight control and Database form coding experience to reduce the time required to create the Silverlight / Access integration. The release simplifies wiring together Silverlight and an Access Database form. We hope the changes result in less code to write. The next blog will show more Silverlight coding.

What we have been doing

The goal of this release was to enable the ability to auto-generate Silverlight Control and Database Form reference classes with minimal lines of code. To accomplish this goal, assembly and database form reflection concepts were incorporated to auto-generate common class patterns.
Release Highlights
·         Added WidgetRelector.Transform() that transforms Silverlight reflection XML into a client-side C# class.
·         Added ActiveForm.Proxy.Transform() that transforms a database form into a C# class. Useful for any Access addin project.
·         Added Generate Reference Files dialog form. The form uses Silverlight.Emit(), WidgetRelector.Transform() and ActiveForm.Proxy.Transform() to auto-generate C# reference proxy files.
·         Enhanced TreeviewPage.AddItem(header). The method now adds a child TreeViewItem to any selected node.
·         Added TreeviewPage.RemoveItem() that removes a TreeViewItem.
·         Added an abstract HtmlBridge class that defines recommended .NET EventArgs classes. HTML DOM events raised by Silverlight resemble standard .NET events.

Silverlight Control Changes

An IReflection interface was added that defines an Emit() method.

IRelection Interface

void Emit() Method
The Emit() method uses LINQ and Assembly reflection to emit XML describing ScriptableMembers and events available to HtmlBridge. The Emit() method is used to auto-generate a client-side Silverlight control proxy reference file.
How Silverlight reflection maps to Access / Silverlight Addin Reference class

XML
Access / Silverlight Addin Reference class
<class name="TreeviewPage">…
class TreeviewPage
<attribute name="HtmlBridgeEvent.onclick" />
public new event EventHandler<ElementEventArgs> onclick;
<class name="ElementEventArgs"> …
base.onclick += new EventHandler<ElementEventArgs>(TreeviewPage_onclick);
<method name="AddItem"> …
<parameter name="itemValue">
          <parameterType name="String" …
public void AddItem(String itemValue)
  base.InvokeScriptableMethod("AddItem('" + itemValue + "')");


Create a Silverlight Control proxy reference file
The follow example creates all client-side (Addin) Silverlight reference code.
WidgetAddinRelector r = new WidgetAddinRelector((mshtml.HTMLDocument)ActiveForm
.WebBrowserControls(ActiveForm.WebBrowser.Names[0].ToString()).Object.Document);

r.Emit();

Event Attributes
HtmlBridge event attribute classes were added to define class and member level event attributes. The attributes are used to emit which HTML DOM events are raised by a Silverlight control. For example, the onclickAttribute reveals to WidgetReflector that the Silverlight control raises an HTML DOM onclick event. WidgetReflector reflects on event attributes to auto-generate HtmlBridge event code.
How HtmlBridge attributes map to Access / Silverlight Addin Reference

HtmlBridge Event Attributes
Access / Silverlight Addin Reference
[ScriptableType, onclick, onmousedown]public partial class TreeviewPage : UserControl, IReflection
public new event EventHandler<ElementEventArgs> onclick;

public new event EventHandler<ElementEventArgs> onmousedown;

base.onclick += new EventHandler<ElementEventArgs>(TreeviewPage_onclick);

base.onmousedown += new EventHandler<ElementEventArgs>(TreeviewPage_ onmousedown);
[ScriptableMember, ondataavailable]
public void AddItem(string itemValue)
public new event EventHandler<AsyncEventArgs> ondataavailable;

base.onclick += new EventHandler<AsyncEventArgs>(TreeviewPage_ ondataavailable);


HtmlBridge Attribute

The HtmlBridgeAttribute defines EventArg classes exposed by a Silverlight control.
Example
[HtmlBridge]
public class ElementEventArgs : EventArgs
{
public string Qualifier { get; private set; }
                public string Name { get; private set; }
                 public string Text { get; private set; }
                 public string Tag { get; private set; }
                 public string Value { get; private set; }
Silverlight onclick Example
onclick(new HtmlBridge.ElementEventArgs(item.Header.ToString(), tag));
Access Addin
MyDocumentTasks.TreeviewPage.onclick += new EventHandler<ElementEventArgs>(TreeviewPage_onclick);
void TreeviewPage_onclick(object sender, ElementEventArgs e)

HtmlBridge Utility Class

An HtmlBridge utility class was added to simplify calling HtmlBridge scripting methods from a Silverlight control.

Silverlight Control
HtmlBridge
htmlBridge.onclick(new HtmlBridge.ElementEventArgs(item.Header.ToString(), tag));
[HtmlBridgeEvent]
public void onclick(ElementEventArgs eventArgs)
{
      FireEvent("onclick", eventArgs);
}

public void FireEvent(string eventName)
{         HtmlPage.Window.Eval(_elementName + ".fireEvent('" + eventName + "')");
}


Access Database Changes

WidgetReflector

A WidgetReflector class was added. The class is a primarily a LINQ class that transforms a Silverlight reflection Xml stream into a Silverlight control proxy reference class. The class auto-generates a Silverlight control proxy reference class hiding the Silverlight control plumbing details from the developer.
Usage
WidgetReflector.Transform(sourceXml, sourceCodePath)

ActiveForm

ActiveForm is a static class for an Access form object wrapper. The class is defined as static since Access creates object instances.

internal static class Proxy
Internal static class that transforms or auto-generates the ActiveForm into a .NET wrapper class. Note that the class has not been tested with all Access controls.

Usage
MyDataAddin.ActiveForm.Proxy.Transform();

The Transform() method auto-generates all database form proxy reference code. For example, calling Transform() on the MyDocumentTasks form auto-generates all code enabling simple implementation methods hiding the addin plumbing details from the developer.

Examples

Implementation Code
Auto-generated Database Form code
MyDocumentTasks.ItemText.Value
private static Microsoft.Office.Interop.Access.TextBox _itemText = null;
    public static Microsoft.Office.Interop.Access.TextBox ItemText
{
      get
      {
        return _itemText;
      }
}
MyDocumentTasks.TreeviewPage.AddItem(itemValue)
public static TreeviewPage TreeviewPage;
TreeviewPage = new TreeviewPage((mshtml.HTMLDocument)
_webBrowser.Object.Document);


HtmlBridge

Abstract class inherited by Silverlight control providing base HtmlBridge members.

MyDocumentTasks.Reference

Class is now auto-generated from ActiveForm.Proxy.Transform().

TreeviewPage.Reference

Class is auto-generated from WidgetReflector.Transform().

Configuration Form

Added Addin Widger Proxy Files ribbon button to Database Tools.
Addin Widget Proxy Files opens Generate Refenence Files dialog form. Create button creates Silverlight and Database form proxy reference file. The configuration form was added to Access as a Power Tool.



Running the Generate Reference Files tool hides the Silverlight / Access addin wiring. Thus, implementation code becomes less complicated.
After running the tool and pasting the code into a .NET class file, a developer can write code similar to the following examples.
Ribbon Button to Open Form
public void myDocumentTasksButton_Click(IRibbonControl control)
{
//Open Form with reference to Addin
MyDocumentTasks.Open(this);
             
       //AddItemCommand
MyDocumentTasks.AddItemCommand.Click += new access.DispCommandButtonEvents_ClickEventHandler(AddItemCommand_Click);
MyDocumentTasks.AddItemCommand.OnClick = bindEvent;
             
//RemoveItemCommand
MyDocumentTasks.RemoveItemCommand.Click += new access.DispCommandButtonEvents_ClickEventHandler(RemoveItemCommand_Click);
MyDocumentTasks.RemoveItemCommand.OnClick = bindEvent;

             
       //TreeviewPage.onclick
MyDocumentTasks.TreeviewPage.onclick += new EventHandler<ElementEventArgs>(TreeviewPage_onclick);
             
//TreeviewPage.ondataavailable
MyDocumentTasks.TreeviewPage.ondataavailable += new EventHandler<AsyncEventArgs>(TreeviewPage_ondataavailable);
}


Add Item Click Delegate
void AddItemCommand_Click()
{
MyDocumentTasks.TreeviewPage.AddItem(MyDocumentTasks.ItemText.Value);

}


Remove Item Click Delegate

void RemoveItemCommand_Click()
{
 MyDocumentTasks.TreeviewPage.RemoveItem();
}

Silverlight TreeviewPage onclick Delegate

void TreeviewPage_onclick(object sender, ElementEventArgs e)
{
MyDocumentTasks.TabControl.Value = e.Tag;
}

Enhanced Treeview Methods
We enhanced the AddItem() method. The method adds a child TreeViewItem to any selected item. We also added an AddRootItem() and RemoveItem method.

No comments:

Post a Comment