WPF/E, ASP.NET AJAX and Web Services – hooking it all together


Recently I've been working with WPF/E and extending some code that I have to make it more visually enhanced.  To display the proper data on the page I wanted to do the following: call a web service asynchronously, have it return to me an arrary of a complex type which I could then work with in javascript to get the proper data so that I could create XAML to be displayed by my webpage.  Here's what I did to get it to work.


Before you run this make sure you have the latest downloadeds: the latest WPF/E SDK bits (December CTP 2006) as well as the latest release of ASP.NET AJAX (1.0 RC). 


For demonstration purposes I'll just return some date information.  Now the first thing, create the web service and return a complex type.  For this I created a web service and referenced the System.Web.Script.Services namespace.  Here's a look at the code.



using System;


using System.Data;


using System.Configuration;


using System.Web;


using System.Web.Security;


using System.Web.UI;


using System.Collections;


using System.Web.Services;


using System.Web.Services.Protocols;


using System.Web.Script.Services;


 


namespace MyComplexType


{


    public class MyInformation


    {


        public string Day;


        public string Month;


        public string Year;


    }


    [WebService(Namespace = "http://tempuri.org/")]


    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]


    // Here's where you tell ASP.NET AJAX to create a proxy for your complex type with the GenerateScriptType attribute


    [GenerateScriptType(typeof(MyInformation))]


    [ScriptService]


    public class MyComplexTypeService


    {


        public MyComplexTypeService()


        {


        }


 



        [WebMethod]


        public ArrayList GetMyInformation()


        {


            ArrayList list = new ArrayList();


            for (int counter = 0; counter < 2; counter++)


            {


                MyInformation info = new MyInformation();


                info.Day = System.DateTime.Today.Day.ToString();


                info.Month = System.DateTime.Today.Month.ToString();


                info.Year = System.DateTime.Today.Year.ToString();


                list.Add(info);


            }


            return list;


        }


    }


}


I also want to produce some XAML for my page that displays my data.  So, I create a simple XAML file that has a couple of canvas elements: 


<?xml version="1.0" encoding="utf-8"?>


<Canvas xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="216" Height="292" Background="LightGray">


  <Canvas x:Name="DataCanvas" Height="70" Width="200" Canvas.Left="8" Canvas.Top="200"></Canvas>


</Canvas>


 


 



The next thing I thought about was how my page would use the javascript to interact with the page and the XAML.  So, in my page I have a simple input control that the onclick method is set to call a javascript method called "OnLookup()"  From here this kicks off my call to the web service.  Lets take a look at the javascript file:

 

var _results;


 


function OnLookup()


{


    ClearList();


    MyComplexType.MyInformation.MyComplexTypeService.GetMyInformation(OnSucceeded);


}


 


function OnSucceeded(result)


{


    _results = result;


    Array.forEach(result,AddXamlElement);


   


}


 


function ClearList()


{


    //This gets a reference to the aghost control on the HTML page that holds the XAML object.


    var canvas = $get("WpfeControl");


   


    //next I get the canvas I want to add the data to in the form of a XAML rectangle.


    var properCanvas = canvas.findName("DataCanvas");


   


    //clear all the elements


    properCanvas.children.clear();


}


 


function AddXamlElement(element,index)


{


    //index automatically increments for each call, so I use that to name my rectangles


   


    //This gets a reference to the aghost control on the page that holds the XAML object.


    var canvas = $get("WpfeControl");


   


    //next I get the canvas I want to add the data to in the form of a XAML rectangle.


    var properCanvas = canvas.findName("DataCanvas");


 


    //Create a new XAML rectangle and give it a namespace and a name


    var xamlRect = '<Rectangle xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Name="';


    xamlRect += "Rect_"+index;


    xamlRect += '" Height="30" Width="170" Canvas.Left="2" Canvas.Top="';


    if(index === 0){xamlRect += '2';}


    else{xamlRect += (32 * index);}


    xamlRect += '" Stroke="White" StrokeThickness="1" MouseLeftButtonDown="javascript:DoSomething">';


    xamlRect += '<Rectangle.Fill>';


    xamlRect += '<LinearGradientBrush  StartPoint="0,0" EndPoint="1,0">';


    xamlRect += '<GradientStop Color="Black" Offset="0.0" />';


    xamlRect += '<GradientStop Color="Blue" Offset="0.50" />';


    xamlRect += '<GradientStop Color="Black" Offset="1.0" />';


    xamlRect += '</LinearGradientBrush>';


    xamlRect += '</Rectangle.Fill>';


    xamlRect += '</Rectangle>';


    var xamlText = '<TextBlock xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Name="';


    xamlText += "TextBlock_"+index;


    xamlText += '" Text="';


    xamlText += element.Day; 


    xamlText += '/' + element.Month; 


    xamlText += '/' + element.Year; 


    xamlText += '" FontSize="10" Foreground="White" Canvas.Left="8" Canvas.Top="';


    xamlText += (32 * index)+4;


    xamlText += '" MouseLeftButtonDown="javascript:DoSomething"/>';


   


    //add my rectangle with an event


    var newControl = canvas.CreateFromXaml(xamlRect);


   


    //add my text with an event


    var newControl2 = canvas.CreateFromXaml(xamlText);


    properCanvas.children.Add(newControl);


    properCanvas.children.Add(newControl2);


}


 


function DoSomething(sender,args)


{


    //parse the element in the array stored globally and use that to find the element in the array


}


And there you have it.  Now your webservice can make a call, return a complex type, and use that type to put XAML on a webpage that has WPF/E.

Comments (2)

  1. Antoine Dubuc says:

    Hi Brett,

    I’d like to know how you think we cann deal with user input to make WPF/E more interactive. How would you go about doing a http://www.canvaspaint.org in WPF/E? (I’m asking of course because it so happens I need to do just that and I am clueless 😉

    Thanks,

    Antoine Dubuc

    Analyst, Business Marketing Solutions

    Transcontinental Direct Montreal

    4491 des Grandes-Prairies Blvd.

    St. Leonard, Quebec, H1R 1A5

    Telephone : (514) 328-7070 x311

    Fax :       (514) 328-2537

    http://www.transcontinental-printing.com

    Transcontinental Printing G.P.

    ps: http://orchus.spaces.live.com

  2. Antoine – you definitely have your work cut out for you!  Actually it wouldn’t be super difficult, it might just be time consuming.  My approach would be like this:

    Define a main canvas for the paint “application”.  This would consist of the following children canvases:

    1.  Menu Canvas with the file, edit, etc.

    2.  Control Canvas with the different drawing tools.

    3.  Color pallete canvas.

    4.  Main drawing canvas.

    From that I would control all the mouse events as they clicked on different images and colors(images) and then add the line to the drawing canvas using a path that is defined by points that the user clicks.

    Hope that helps – I don’t have time right now to put any code out for you.

Skip to main content