Runtime XAML generation

I know what you are thinking: Woah! A new blog post this soon? Its only years since the last one; where do you find the time?
Writer’s block? Lazy? Just useless? Anyway! I’ve been wanting to do this post for a while now; hopefully it’s of use to someone.

Background

While working on a client project, we came to a point where we needed to generate UI at runtime to support templating of forms.

The scenario is this:
We have a wizard component that guides a user through data input and analysis which is a set of sections and pages with input fields, workflow statuses, data visualizations, etc.
However, a customer of the software may need to customize this process to their company requirements or even create a new process.

Now, we don’t want to upload XAML markup to the backend which would allow too much editing freedom (this is something the customer should be able to do themselves without involving expensive template-designing consultant fees) nor do we want XAML in the backend because the client app could be replaced/supplemented with another app on a different platform.
So, the template is a JSON format which does not deal with the specific client-side implementation. Which gives us even more benefits such as validation of uploaded templates (kind of hard with a XAML dump) and the payload is small and fast to deal with.

That’s the quick and generic overview of this.

Solution

First off: The code for this is my client’s property so I cannot share it here without permission.

I got the idea after a friend was talking enthusiastically about Monoids.
My thought was this: XAML elements are DependencyObjects which can only be created on the UI-thread and it’s a bit of a hassle to deal with the structure as you initialize it all.
I didn’t want to create all the elements, add the elements to their parent StackPanels, Grids, etc and it all becomes very sequential and annoying to deal with.
Furthermore, if some part of the UI generation required some async work it all becomes an issue with these DependencyObjects.

So I played around with creating this XAML describing class which behaved as a monoid. The reason for that is that the XAML element (such as a textbox) can be dealt with on its own, in a parallel thread or however you want it.
When all of the elements are done parsing, they can be combined in any sequence they feel like because each element knows who it is and who their desired parent is.
This information comes from the template – basically, a group of fields is given id 1 (and in the app is considered to be a container such as a StackPanel) and the fields that belong to that group get their own ids with a parent id of 1.
Having this information means that each element can return from wherever they come from in any order and for final combination it will all fall into place.

In short, the code could look like this for declaring some XAML controls:


var field = XamlElementDescriptor<TextBlock>.Create(groupId: null, parentGroupId: 1);

field.AddProperty(“Text”, “asdf”);

 


var container = XamlElementDescriptor<StackPanel>.Create(groupId: 1);

container.AddProperty(“HorizontalAlignment”, “Stretch”);

 

To combine them it would be a matter of just adding them together:


var combinedElements = field + container;

 

And render it: var xaml = XamlWriter.Render(combinedElements.First());

 

combinedElements.First() will be the StackPanel with the TextBlock inside it.
And the output of the parsing results in a simple:


This also supports custom controls and attached properties, of course, and will add the necessary namespaces to the XAML markup to make use of them.

A slightly more complex example to demonstrate this could be something like this:

 

var field = XamlElementDescriptor<TextBlock>.Create(groupId: null, parentGroupId: 1);

field.AddProperty(“Text”, “asdf”);

 


var container = XamlElementDescriptor<StackPanel>.Create(groupId: 1);

container.AddProperty(“HorizontalAlignment”, “Stretch”);

 


var grid = XamlElementDescriptor<Grid>.Create(groupId: 2, parentGroupId: 1);

grid.AddExpandedProperty(“Grid.ColumnDefinitions”, new
XamlElementDescriptorCollection {


XamlElementDescriptor<ColumnDefinition>.Create(),


XamlElementDescriptor<ColumnDefinition>.Create()

});

 


var image = XamlElementDescriptor<Image>.Create(parentGroupId: 2);

image.AddProperty(“Source”, “/Assets/blabla/etc.jpg”);

image.AddProperty(“Stretch”, “UniformToFill”);

image.AddProperty(“Grid.Column”, “0”);


var combinedElements = container + field + grid + image;

 

 

 


var xaml = XamlWriter.Render(combinedElements.First());

Using XamlReader now to instantiate the controls is now just a walk in the park.

That is the quick run-down of my solution for this – and it may not be the best (any input would be appreciated), but it works really well and its really fast.

Oh, you may be thinking “Well, this is error prone as adding properties using strings can cause runtime exceptions if typos are introduced and the like”.
The sexy lady Roslyn helps us there! I wrote an extension that validates this and provides errors and simple code fixes.

Or even custom attached properties (with a code fix):

 

I might do a follow-up blog post how the Roslyn analyzer was written; maybe quite fast if there’s any interest in it.

Back to square one

I’m a “noob”. Thats basically the feeling these days as I’m playing around with XNA for WP7. But its fun and its easy. After years of doing enterprise development this is a nice change of gears; it lets me take a break from my every day routine of SharePoint and such.

I’ve always considered game development to be the place where I could fully let loose and enjoy some cutting edge code, but the industry is hard to get into – especially for beginners. WP7 changes that, of course, as it allows everyone with varied .NET backgrounds to join in on the fun.
Full XNA development puts alot on the plate what with shaders and such, but with WP7 you get an entry level introduction to game development (and yet you get to play with advanced concepts such as sensors and touch in an easy way). I’ve done some shader coding; just enough to understand that I’m actually happy XNA for WP7 doesnt support more than what is included (for now) because otherwise I’d charge that hill as well and for now I’m happy with enjoying the basics.

While XNA is a platform that provides a lot of help its still not the big babysitter like the other platforms I use every day. It gets you started with the fun stuff and hiding all the low level code which deals with the hardware etc. My first realization was that doing input management and control UI is something that you need to handle yourself. There is a certain measure of infrastructure code that you need to put in place before you get to play with the fun stuff; not like, for example, Silverlight where you can just draw a button and attach to a click event.
But its worth it because you gain a deeper understanding of what the babysitter platforms actually do for you and leaves you a better developer. I firmly believe its important for developers to know what a framework actually does for them.

XNA for WP7 (as that is what I work with at this moment) is just easy enough to do simple games and challenging enough so that I have something to pit my mind against when doing more advanced games.

Hopefully I’ll have some good ideas worth publishing on the Marketplace soon as my number one ambition, still and always, is to create something that people enjoy whether it be for entertainment or business.

In reality this isn’t back to square one because with my .NET backround WP7 development, be it Silverlight or XNA, is easy – just enjoy it, people.

Rewriting FullTextQuery within CoreResultsWebPart

Recently I found that SharePoint advanced search used query parts like Title like ‘%querystring%’ when dealing with contains operators. When dealing with documents that had long titles this didn’t yield the expected search results and with further testing I found that using CONTAINS(Title,’”querystring”’) gave me all the results I wanted.

Problem was that the advanced search was out-of-the-box and no way to configure this (as far as I know) so I needed a way to rewrite the FullTextQuery that was being generated by SharePoint without too much custom code and changing the behavior of the CoreResultsWebPart.

Enter: Reflection. I love this tool, but it should be used sparingly in large solutions as there is a performance hit.

Anyway, basically what I did was extend the CoreResultsWebPart and override the SetPropertiesOnHiddenObject method. This method initializes a private field within CoreResultsWebPart of the type SearchResultHiddenObject and this class contains the FullTextQuery propery which we want to modify at runtime.

So, here’s the quick and dirty code (should be cleaned up before production use):

private string queryPattern = @"(?<Title>Title[\w\s]+[^%]%(?<Query>[\w\s\d]+[^%]*)%')";

protected override void SetPropertiesOnHiddenObject() { base.SetPropertiesOnHiddenObject(); try { Type t = this.GetType(); FieldInfo hiddenObjectField = t.BaseType.GetField("srho", BindingFlags.NonPublic | BindingFlags.Instance); if (hiddenObjectField != null) { object hiddenObject = hiddenObjectField.GetValue(this); Type hiddenObjectType = hiddenObject.GetType(); PropertyInfo fullTextQuery = hiddenObjectType.GetProperty("FullTextQuery", BindingFlags.Public | BindingFlags.Instance); string query = fullTextQuery.GetValue(hiddenObject, null) as string; if (query != null) { Match m = Regex.Match(query, queryPattern); if (m.Success) { string queryString = m.Groups["Query"].Value; query = Regex.Replace(query, queryPattern, "CONTAINS(Title,'\"$2\"')", RegexOptions.IgnoreCase); fullTextQuery.SetValue(hiddenObject, query, null); } } } } catch (Exception ex) { HttpContext.Current.Response.Write("Error: " + ex); } }

‘As you can see I use a regular expression to match and replace the query, but you can replace this with however you wish to modify the query.


Replace the out-of-the-box CoreResultsWebPart with this webpart and you’ll retain all the normal functionality except you gain a little more power over the actual query that is used. This works perfectly on SharePoint 2007; I haven’t tested it on SharePoint 2010 and it might not be needed there.

Bring It update

I just submitted a new version of my shipment tracking application for Windows Phone 7 for testing and hopefully it will be available within a day or two. The big new feature is push notification where you’ll get status updates on your shipment (courtesy of my new Azure service that I mentioned in my previous post).

As I don’t have the means to do large scale testing it will be interesting to see how it holds up when users get the update and start using it.

permission

This feature brings with it the possibility to turn on and off push notification (as required by Microsoft) and for every shipment you wish to track you can specify the level of notification you wish to have. This is configured at the edit screen displayed below.

addpackagelevels

Tile update only specifies that only the number of updates available will be displayed on the tile itself (requires that the application is pinned to the start menu). The rest will send toast notifications.

Also, I added a little graphical update just to freshen up the UI a bit. This is also theme dependant like the rest of the application.

mainscreendetailsevents

 

Any feedback would be appreciated Smilefjes

Azure impressions

So, I decided to do something proper with my free Azure subscription (bundled with my MSDN account) and create a cloud service for my Windows Phone 7 application. It’s been a while since I worked with Azure and I was really impressed by the current version; the ease of deployment and online management.

The Silverlight management tools at http://windows.azure.com is very comfortable to work with and creating simple SQL Azure databases via a web browser is just, well, easy Smilefjes The Visual Studio 2010 Azure templates are equally great and gets you up and running within minutes.

In simple terms: Created a web service role for my WP7 application to talk to, used Entity Framework to connect to the Azure SQL database, created a worker role that (in this case) checks shipment statuses and sends push notifications back to the WP7 app and voila: Cloud-enabled appSmilefjes

The local debugging capabilities (Compute and Storage emulators) are all wired up for you and a quick F5 gets you going.

Basically, that’s my impressions for the current version of Azure and thus far I’m (obviously) pleased with itSmilefjes

SharePoint FBA & Reactive Extensions

Some of the dangers with new toys is to overuse them, I fear I might be doing that with reactive extensions but oh well.. It’s all about the learningSmile

Today I did a test to do Form Based Authentication with SharePoint using reactive extensions. This is the first attempt, it can probably be made more streamlined as I figure out more about Rx.

Oh, apologize for the syntax coloring in the code, I really need to find some better CSS for this…

I have two classes: One for doing the FBA (which also holds the cookie jar as we will get a cookie once the FBA is successful and need to pass this along to the next web service call) and one for doing web service calls.

public class FormsBasedAuthentication {
    public static CookieContainer CookieJar = new CookieContainer();
    private const string AuthEnvelope = @"<?xml version=""1.0"" encoding=""utf-8""?>
                <soap:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"">
                  <soap:Body>
                    <Login xmlns=""http://schemas.microsoft.com/sharepoint/soap/"">
                      <username>{0}</username>
                      <password>{1}</password>
                    </Login>
                  </soap:Body>
                </soap:Envelope>";

    public static IObservable<string> Authenticate(string server, string username, string password) {
        Uri authService = new Uri(string.Format("{0}/_vti_bin/authentication.asmx", server));
        HttpWebRequest authRequest = WebRequest.Create(authService) as HttpWebRequest;
        authRequest.CookieContainer = CookieJar;
        authRequest.Headers["SOAPAction"] = "http://schemas.microsoft.com/sharepoint/soap/Login";
        authRequest.ContentType = "text/xml; charset=utf-8";
        authRequest.Method = "POST";
        return (from request in Observable.FromAsyncPattern<Stream>(authRequest.BeginGetRequestStream, authRequest.EndGetRequestStream)().Do(stream => {
            UTF8Encoding encoding = new UTF8Encoding();
            string envelope = string.Format(AuthEnvelope, username, password);
            byte[] bytes = encoding.GetBytes(envelope);
            stream.Write(bytes, 0, bytes.Length);
            stream.Close();
        })
                from response in Observable.FromAsyncPattern<WebResponse>(authRequest.BeginGetResponse, authRequest.EndGetResponse)()
                select HandleResponse(response, authRequest));
    }

    private static string HandleResponse(WebResponse response, HttpWebRequest request) {
        var httpResponse = response as HttpWebResponse;
        if (httpResponse != null){
            var result = XDocument.Load(response.GetResponseStream());
            var code = result.Descendants(XName.Get("ErrorCode", "http://schemas.microsoft.com/sharepoint/soap/")).FirstOrDefault();
            if (code != null)
                return code.Value;
        }
        return "ErrorOccured";
    }

}

This will return an observable that will return the authentication result – if the login was successful, the published value will be NoError.

Next we have our web service class:

public class BaseWebService {
       private static string soapEnvelope =
           @"<soap:Envelope
                           xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
                           xmlns:xsd='http://www.w3.org/2001/XMLSchema'
                           xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'>
                   <soap:Body>{0}</soap:Body></soap:Envelope>";

       private XDocument soapEnvelopeXml;
       public string BaseUrl { get; set; }
       #region Helper methods
       private XDocument CreateSoapEnvelope(string content) {
           var envelope = string.Format(soapEnvelope, content);
           XDocument soapEnvelopeXml = XDocument.Parse(envelope);

           return soapEnvelopeXml;
       }

       private HttpWebRequest CreateWebRequest(string url, string action) {
           Uri serviceUrl = new Uri(url, UriKind.Absolute);
           var webRequest = WebRequest.Create(serviceUrl) as HttpWebRequest;
           webRequest.Headers["SOAPAction"] = action;
           webRequest.ContentType = "text/xml;charset=\"utf-8\"";
           webRequest.Accept = "text/xml";
           webRequest.Method = "POST";
           webRequest.CookieContainer = FormsBasedAuthentication.CookieJar;
           return webRequest;
       }
       #endregion

       public IObservable<XDocument> CallService<T>(string url, string action, string soapContent) {
           soapEnvelopeXml = CreateSoapEnvelope(soapContent);
           HttpWebRequest webRequest = CreateWebRequest(url, action);
           var call = (from request in Observable.FromAsyncPattern<Stream>(webRequest.BeginGetRequestStream, webRequest.EndGetRequestStream)().Do(stream => {
                                                                                                                                                       soapEnvelopeXml.Save(stream);
                                                                                                                                                       stream.Close();
                                                                                                                                                   })
                       from response in Observable.FromAsyncPattern<WebResponse>(webRequest.BeginGetResponse, webRequest.EndGetResponse)()
                       select Handle(response));
           return call;
       }
       private XDocument Handle(WebResponse response){
           var doc = XDocument.Load(response.GetResponseStream());
           return doc;
       }
   }

This produces an observable which will publish a XDocument with the result of the web service call. As you can see, we are using our cookie jar from the FBA class (see the CreateWebRequest method) so that our authentication token gets passed along.

To put this together and do an authenticated call to the Lists.asmx web service in SharePoint, we need two small methods.

private static void GetList(string authStatus){
            if (authStatus == "NoError"){
                BaseWebService webService = new BaseWebService();
                webService.CallService<XDocument>(“<url>/_vti_bin/Lists.asmx”, ActionGetList, string.Format(SoapGetList, "Pages")).Subscribe(Handle);
            }
        }

This method gets the published value from the FBA class and checks that we can proceed with our next call.

Oh, must not forget the SoapAction and content of the envelope:

private const string ActionGetList = "http://schemas.microsoft.com/sharepoint/soap/GetList";
private const string SoapGetList = @"<GetList xmlns='http://schemas.microsoft.com/sharepoint/soap/' xmlns:i='http://www.w3.org/2001/XMLSchema-instance'><listName>{0}</listName></GetList>";

 

private static void Handle(XDocument doc){
            Console.WriteLine(doc.ToString());
        }

And this one handles the result from the call to Lists.asmx (not doing much at this point).

So, to start it all off, we need to get our FBA observable set up:

var auth = FormsBasedAuthentication.Authenticate("<url to sharepoint site>", "<user>", "<password>");

Next we start it off:

auth.Do(GetList).Start();

What this does is that our FBA observable will call GetList for every published value that the FBA observable gives us (which should be just one) and to fire the entire process off we turn the ignition and .Start() Smile

This is all then done asynchronously.

Getting controls from inside a DataTemplate

Today I had to access a control which resided inside a DataTemplate used by a PivotItem (WP7) and there’s no straight forward way to do this as far as I know.

Thing is that pivotControl.Items[idx] returns the databound item and pivotControl.ItemContainerGenerator.ContainerFromItem(item) yields a PivotItem. But I figured that pivotItem.Content would contain the controls defined in the DataTemplate – wrong, it gives back the databound item.

So, my next try was to use the pivotItem.ContentTemplate.LoadContent() which actually did give me my controls – but LoadContent() actually creates a new object and doesn’t give you the reference to the actual live object on your screen.

Of course, the solution is rather simple if you can just think of it right off the batWinking smile

First, get the container:

DependencyObject container = pivotControl.ItemContainerGenerator.ContainerFromItem(item);

Then we use the VisualTreeHelper to take a walk around and find the control we want (by name).

var details = container.GetChild<Detail>("details");

This is all possible with this little extension method:

public static T GetChild<T>(this DependencyObject parent, string name) where T:DependencyObject{
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++) {
                DependencyObject child = VisualTreeHelper.GetChild(parent, i);

                if (child.GetType() == typeof(T) && ((FrameworkElement)child).Name == name)
                    return (T)child;

                if (child.GetChild<T>(name) != null)

                    return child.GetChild<T>(name);
            }
            return null;
        }

If there’s a simpler solution to this, please let me knowSmile

Bring It preview

Just a quick little preview of my package tracking app. Added a little fun gimmick where you can see where the last transport event took place using Bing maps. Still some styling left to do and get it all prettified, but it’s starting to come together.

http://player.vimeo.com/video/16043460

Bring It Preview from Frode Hus on Vimeo.

Using reactive extensions with WebRequest

I’ve recently started looking at the Rx library from Microsoft labs and it’s very interesting stuff, even though I have to admit I have a hard time wrapping my head around it. But it starts to sink in, bit by bit 🙂


When working with Windows Phone 7 development and my SharePoint library for WP7, I do a lot of asynchronous calls to web services. This code can often get a bit messy with all the callback methods so I tried to refactor it using reactive extensions and I am pretty pleased with the result:) I’m no expert on the field so I won’t guarantee that this is the best way to do it, but it works.

Here’s a sample of how to do a call to the Lists.asmx web service in SharePoint:
string Envelope = @"<?xml version=""1.0"" encoding=""utf-8""?>
                                    <soap:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"">
                                        <soap:Body>
                                            <GetList xmlns=""http://schemas.microsoft.com/sharepoint/soap/"">
                                                <listName>{0}</listName>
                                            </GetList>
                                        </soap:Body>
                                    </soap:Envelope>";

        public void GetList(string server, string name, Action<XDocument> handler)
        {
            HttpWebRequest req = WebRequest.Create(string.Format("{0}/_vti_bin/lists.asmx", server)) as HttpWebRequest;
            req.Headers["SOAPAction"] = "http://schemas.microsoft.com/sharepoint/soap/GetList";
            req.ContentType = "text/xml; charset=utf-8";
            req.Method = "POST";
            var listRequest = (from request in Observable.FromAsyncPattern<Stream>(req.BeginGetRequestStream, req.EndGetRequestStream)().Do(stream =>
            {
                UTF8Encoding encoding = new UTF8Encoding();
                string e = string.Format(Envelope, name);
                byte[] bytes = encoding.GetBytes(e);
                stream.Write(bytes, 0, bytes.Length);
                stream.Close();
            })
                     from response in Observable.FromAsyncPattern<WebResponse>(req.BeginGetResponse, req.EndGetResponse)()
                     select HandleResponse(response)).Subscribe(handler);
        }
        private void DoStuff(XDocument xml)
        {
                //parse the xml result here
        }
        private XDocument HandleResponse(WebResponse response)
        {
            HttpWebResponse res = response as HttpWebResponse;
            if (res != null && res.StatusCode == HttpStatusCode.OK)
            {
                XDocument doc = XDocument.Load(response.GetResponseStream());
                return doc;
            }
            return null;
        }

Then of course we call the method:

GetList("http://spserver.com", "Pages", DoStuff);

In Windows Phone 7 we could add .ObserveOnDispatcher() before our .Subscribe() in the LINQ query so that the current Dispatcher is used when notifying observers.

We could also generalize the method so that it returns a IObservable<T> instead which we can subscribe to.

SharePhone continues on

Just wanted to inform that I’ll be adding Forms Based Authentication as well as Basic Authentication modes as options in SharePhone so that the library can be used for those that has these kinds of authentication methods configured for their SharePoint sites.