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

Advertisements

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.

The Empire strikes back

I shamelessly stole a tweet for the title of this entry (hope you don’t mind, chetansharma) as I found it very fitting for what transpired today in New York at the Windows Phone 7 keynote.

First off, I’ll get my pet peeves off my chest regarding Windows Phone 7:

  • No cut and paste (slated for early 2011, so at least it’s coming – yes Microsoft, we do use this functionality still)
        • No multitasking
        • Certain functionality missing from the API which I won’t get into here

Now, I do understand that certain things had to be cut for the first release in order to provide a good and stable experience and so I hope that the rest will come in (near) future updates. The approach to do quality over quantity is a good one if this new platform is to stick, we don’t need for WP7 to fail right out of the gate.

So, all that settled, let’s get to the real news: WP7 has launched and the devices has done their stroll down the catwalk! I find myself in a pickle; I don’t know which device I want as they all seem so tastySmile

I do hope that WP7 marks Microsoft’s comeback into the smartphone marked and not a complete failure like, for example, Gartner predicts. Microsoft has done a solid piece of work; they started completely fresh (pretty gutsy and costly) and even came up with their own interface or as the keynote promoted: A different kind of phone. I won’t get into all the features as plenty of articles out there do indepth reviews of them shortly, I assume, but the idea of aggregating information from different sources and placing the data at your fingertips via the tiles is an interesting approach and I think it will work delightfully.

The Metro design is a matter of taste, I’m a big fan of graphically esthetic interfaces and I love the transition effects they do. I know some think they’ve overdone it and some even say its just stupid and a poor attempt at doing something to win over the masses. I’ll just say that my personal opinion is that I love my phone to be all pretty and fancy and leave it at that.

Also, Microsoft finally did what they should have done way earlier: Set some hardware requirements for their OS to ensure smooth running and good user experience across vendors. That’s one of the main advantages a certain fruit has had as they had firm control over the hardware their OS would run on.

I have one little nuisance nagging me and that’s the availability of certain services in my country. As far as I know, there will be no Xbox Live, no Zune and no Marketplace in Norway the day the devices are out in stores. I’m rather tired of fun functionality being available only in the US such as movie rentals etc but that’s an annoying licensing matter.

But, WP7 delivers what I’ve been waiting for: A development platform where I can use Silverlight and XNA and most importantly, Visual Studio. It’s easy for beginners to get into and for more advanced developers to have fun with. That’s where the nameless fruit fails horribly. I just hope that it will get firm footing in the marked and developing WP7 applications won’t become something rare and for especially interested.

And that’s my little comment on today’s keynote.
Wonderfully and delightfully yours.

Bring It

So, I decided to do a Windows Phone 7 application as a trial run and get the feel of it all instead of just small tests and demos.

It’s called Bring It, named after Bring which is a transportation service here in Norway and the application lets you track your packages, display a barcode for easy pickup at the post office, etc. I originally intended to add this to the Marketplace when it opened up, but I see that Posten has already developed and published their own application for free on the iPhone AppStore and Android Market so I figure they’ll do the same for Windows Phone 7 at one point.

Anyway, with that in mind I figured I’d post this app up for anyone who wants to use it as a sample and perhaps finish it (styling needs work for example).

I’ve added support for themes and globalization (even though the messages that come from the tracking service is in norwegian, so really only the headers and such are globalized), pivot control, it uses a MVVM pattern (still a bit new on that arena, so it might not be a perfect implementation – anyone with tips, please shareSmile ). Oh and it all works by pulling XML down from a public service provided by Posten.

It’s not entirely complete, missing a few features (such as deleting packages and such), but it works. As you can see from the screenshots, I used it to track my new Xbox 360 shipment Winking smile

Here are some mandatory screenshots:

image  imageimage

The fun bit is the ease of which WP7 application development is done. This app (granted, it’s simple, but still) only took a couple of hours to do.
I’d love to add push notification for tracking changes etc, maybe later.

Source:

Download

User profiles and search in SharePhone

So, version 1.0.3 is out and contains a couple of new features.

User profiles

ClientContext now offers two methods for dealing with user profiles, GetUserProfile and UpdateUserProfile.

Here’s a quick example of their usage:

 

ctx.GetUserProfile(@"sharepointdev\testuser", (UserProfile profile) => {
    profile.Title = "Test user";
    ctx.UpdateUserProfile(profile, null);
});

The UserProfile class only contains a couple of quick access properties so far, to access all of them you need to access the Properties property and read your values there. Here’s an example how:

from property in profile.Properties where property.Name == "PreferredName" select property

You can also use a simple utility method when you want to update a property:

profile.UpdateSingleValueProperty("PreferredName", "Santa");

Keep in mind that updating a user profile is subject to access restrictions set by the site administrator (some properties can only be updated by administrator, others by the owner of the profile).

Search

Again, the ClientContext class has been expanded to include some search functionality. This is the built-in SharePoint search (not sure how this will work with FAST in SharePoint 2010).

ctx.SearchProvider.KeywordSearch("Test", (SearchResult result) => {
    int numberOfHits = result.TotalAvailable;
    //access the hits via result.Results
});

You can also do advanced search via the Search(..) method and the QueryPacket class.

QueryPacket query = new QueryPacket();
query.EnableStemming = true;
query.QueryType = QueryType.MSSQLFT;
query.Query = "select * from Scope() where FREETEXT('test')";
ctx.SearchProvider.Search(query, (SearchResult result) => { });

SharePhone

Today I released a basic version of SharePhone, my WP7 library for working with SharePoint sites. Binaries and source code can be found here: Codeplex

I’m currently porting this code from a more functional Silverlight project so I apologize if the source is a bit messy.

Anyway, the current release lets you open up any SharePoint 2007/2010 web and its sub webs and work with their lists and list items.

Here’s a short example how:

First we instantiate our context and supply the URL for the root web.

ClientContext ctx = new ClientContext("http://sharepointdev");
//supply credentials if needed
ctx.Settings.Credentials = new CredentialSettings { Domain = "<domain>", UserName = "<user>", Password = "<password>" };

Then we get our root web object (remember, Silverlight requires any web service call to be made asynchronously which is why this is the only method available in this library).

ctx.GetRootWeb((object s, SPWebLoadCompletedEventArgs result) => {
    SPWeb rootWeb = result.Webs[0];               
});

Next, let’s load all the lists available at the root web:

web.Lists.LoadCompleted += (object sender, SPListLoadCompletedEventArgs e) => {
    Deployment.Current.Dispatcher.BeginInvoke(() => {
        list1.ItemsSource = e.Lists;
    });
};
web.Lists.LoadAll();

list1 is a ListBox and it’s defined like this in XAML:

            <ListBox Name="list1">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Title}" Style="{StaticResource PhoneTextNormalStyle}"/>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>

And we have our lists neatly listed out on our phone, ready to continue working with them. sample

Most of the operations on collections, such as sub webs on a web or lists or even list items in a list requires you first to load the collection like in the previous example (web.Lists.LoadAll()). The reason why I don’t load this data on first call is because I want to keep the data traffic at a minimum. Basically you load what you need and nothing more.

Next post I’ll show an example how to read list items, update the data and post them back to SharePoint using strong typed custom classes.