First Look: Cooliris – ‘Enjoy the richest way to view photos from Flickr, Facebook, Picasa, and even your computer.’

I was upgrading Firefox on one of my computers last night and stumbled upon Cooliris as a featured add-on. From the Cooliris website:

What is Cooliris?

It's simply the fastest and most stunning way to browse photos and videos from the Web or your desktop. Effortlessly scroll an infinite "3D Wall" of your content without having to click page to page, whether you'e on Facebook, Google Images, YouTube, Flickr, Picasa, Kodak Gallery, or any supported site. Or channel surf the latest news, TV episodes, movies, and music videos all from within Cooliris.

I was very impressed with my first experience with Cooliris as, coincidentally, I was recently planning to write a Silverlight slideshow control that could present a Picasa web album. Cooliris already has this feature built-in, among many others (such as displaying images from other web sites and search engines). In addition to their desktop support, I was also glad to learn about their support for mobile platforms as well, especially their support for Android (the media gallery app is included as the official media app for the Nexus One (looking forward to getting my phone upgraded to Android 2.1 :))).

Check out the Cooliris Express tool on the Cooliris website to quickly build an embeddable 3D wall of pictures (such as my Picasa web albums displayed below) for your blog or site.

 

Technorati Tags:

Uninstalling PVConnect Add-In from Windows Home Server May Improve Console Performance

I have been putting up with a very slow Windows Home Server Console for a long time now (at least six months). The console response time to clicks and its window refresh rate have been very slow; as in, I would have to wait minutes for the response to a button click to complete. Today, I had to work with the console for a long time and I just got fed up with the problem. A quick search on the web fixed my problem, thanks to the MS Windows Home Server forum. I had to uninstall the PVConnect add-in (which I do not use anyway). The console is now as responsive as when I first got my WHS.

Link: WHS Console keeps freezing - PAINFULLY slow

Technorati Tags:

Configuring Silverlight Service References Using ‘initParams’ (C#)

Silverlight cannot easily be configured to use a different endpoint address via a configuration setting. Unlike other .Net application types that can be configured upon deployment using their ‘.config’ files (for Windows apps, it is the ‘app.config’ file, and for web apps it is the ‘web.config’ file), Silverlight applications need to be configured before deployment using the ‘ServiceReferences.ClientConfig’ file. This has been very inconvenient for me so I had to come up with a simple solution to this problem.

My solution to the problem involves the following:

  • Set the configuration settings in the initParams initialization parameter of the Silverlight plug-in object. A typical Silverlight object tag in my web page would then look like:
        <object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%"
            id="silverlightControl">
          <param name="source" value="ClientBin/MyApp.xap"/>
          <param name="onError" value="onSilverlightError" />
          <param name="background" value="white" />
          <param name="minRuntimeVersion" value="3.0.40624.0" />
          <param name="autoUpgrade" value="true" />
          <param name="initParams" value="EndpointHost=localhost,EndpointPort=51324"/>
          <a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=3.0.40624.0" style="text-decoration:none">
               <img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style:none"/>
          </a>
        </object>
  • In the App class’s  Startup event, generate the endpoint for the service by parsing initParams. The following code contains three methods that take care of this:
        private EndpointAddress m_endpointAddress;
        private void Application_Startup(object sender, StartupEventArgs e)
        {
            //get the endpoint for the web service
            //as specified in InitParams
            AppServicesSoapClient client = new AppServicesSoapClient();
            Uri serviceUri = GetServiceUriFromInitParams(e.InitParams, client.Endpoint.Address.Uri);
            m_endpointAddress = new EndpointAddress(serviceUri, client.Endpoint.Address.Headers.ToArray());
        }

        private Uri GetServiceUriFromInitParams(IDictionary<string, string> initParams, Uri referenceUri)
        {
            UriBuilder uriBuilder = new UriBuilder(referenceUri);
            foreach (KeyValuePair<string, string> initParam in initParams)
            {
                switch (initParam.Key.ToLower())
                {
                    case "endpointhost":
                        uriBuilder.Host = initParam.Value;
                        break;
                    case "endpointport":
                        uriBuilder.Port = Convert.ToInt32(initParam.Value);
                        break;
                    case "endpointpath":
                        uriBuilder.Path = initParam.Value;
                        break;
                }
            }
            return uriBuilder.Uri;
        }
        public AppServicesSoapClient GetAppServicesClient()
        {
            AppServicesSoapClient client = new AppServicesSoapClient();
            client.Endpoint.Address = m_endpointAddress;
            return client;
        }

Some notes about the code above:

  1. The m_endpointAddress member variable is used to contain the endpoint address resolved from initParams.
  2. The Application_Startup event handler generates the value for the endpoint address. It uses a default instance of a service client to get the default endpoint URI. It then calls GetServiceUriFromInitParams to get a URI configured with the parsed values of initParams.
  3. The GetServiceUriFromInitParams method generates a URI using a reference URI (the default service endpoint URI, in this case). It parses initParams to find keys of interest to replace parts of the URI with the specified values. The sample uses host, port, and path only (for most of my apps, host and port are sufficient) but the method can easily be extended to handle the other parts of a URI using the same technique. The UriBuilder class provides the crucial services for easily constructing the URI from a base value and replacing its parts with the new values.
  4. The GetAppServicesClient method serves as the application-wide method for instantiating clients configured with the desired endpoint.

For ASP .Net hosting applications, the solution can be extended to store the configuration setting in the web.config file. Sample ‘web.config’ appSettings and Silverlight object tags follow:

  <appSettings>
    <add key="ServiceEndpointParams" value="EndpointHost=localhost,EndpointPort=51324"/>
  </appSettings>
       <object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%"
            id="silverlightControl">
          <param name="source" value="ClientBin/SpellingVee.xap"/>
          <param name="onError" value="onSilverlightError" />
          <param name="background" value="white" />
          <param name="minRuntimeVersion" value="3.0.40624.0" />
          <param name="autoUpgrade" value="true" />
          <param name="initParams" value="<%=System.Configuration.ConfigurationManager.AppSettings["ServiceEndpointParams"] %>" />
          <a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=3.0.40624.0" style="text-decoration:none">
               <img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style:none"/>
          </a>
       </object>

A simpler solution using the same technique is to specify the full URL in initParams (which is the same approach implemented in ‘web.config’ and ‘app.config’ files), instead of just parts of it. However, I like this solution better as most of the time only the host and port will be different between my development and production endpoints (this avoids having to remember the full URL).

Sample Code: Integrating Picasa Web Albums into an ASP.NET Application

Picasa Web Integration I have come up with a sample Visual Studio 2008 (C#) web application project integrating Picasa Web Albums into an ASP.NET website. I blogged on this subject last year (see Integrating Picasa Web Albums into my Website) and am providing sample code as I have recently received a request for this. Much of the solution comes from code I actually use on my website, including the theme/style of the page (based on the Personal Web Site Starter Kit which I used as a starting point when I rebuilt my website a few years ago). You can download the solution at: http://www.aocampo.com/Downloads/PicasaWebIntegration.zip.

Main Project Components

  1. Pages
    • Default.aspx – displays albums (as in the screenshot above)
    • Slideshow.aspx – displays an album’s slideshow using an embedded Picasa Web Album.
  2. Class Files
    • Album.cs – a class file for the Album class, an abstraction of a Picasa Web Album.
    • PhotoManager.cs = a class file for the PhotoManager class that wraps the Google Data API services.

Deployment Notes

  1. Before running the project, replace the value for the PicasaWebUserId application setting in the web.config file to the Picasa Web Album ID that you want to use.
  2. To optimize performance, the PhotoManager gets the list of albums associated with a specified account the first time the album list is needed and uses the same list for all subsequent requests until the application is restarted. This means that when the albums are updated (say, a new album was added), the albums displayed will not be refreshed. This is usually sufficient for low traffic websites (like mine) as the web application shuts down periodically on idle (so the PhotoManager will likely refresh the album list at least once a day). To force a refresh of the albums list, pass a ‘reset=y’ query string to the page (e.g., navigate to ‘Default.aspx?reset=y’). 

Sample Code: Data Virtualization Using a Web Service with Xceed DataGrid for WPF

I got a few requests for sample code to my post about Data Virtualization with Xceed DataGrid for WPF. I have come up with a sample Visual Studio 2008 solution for this. You can download the solution at: http://www.aocampo.com/Downloads/DataVirtSample.zip.

The solution contains:

  1. A sample WPF application project (DataVirtClient) that uses the Xceed DataGrid for WPF. You will need to set the Xceed DataGrid for WPF Professional Edition license key in the App.xaml.cs file to run the application.
  2. A sample ASP .Net web service project (DataVirtSvc) that is called by the WPF application. The web service serves as the data source for the data being virtualized in the WPF application.

Notes

  • I tried to make the sample as simple as possible. Hopefully, the simplified implementation will make understanding the technique easier. Having said this, note that this ‘bare bones’ sample is for demonstration purposes only and it is up to you to take the essence of the technique and refine it to fit your problem.
  • The main methods that the web service must provide are:
    • A method to provide the item count in a dataset
    • A method to provide a ‘page’ of a dataset
  • Main ingredients of data virtualization with the Xceed DataGrid for WPF:
    • Use a DataGridVirtualizingCollectionView as the control’s ItemsSource
    • Handle the QueryItemCount and QueryItems events of the DataGridVirtualizingCollectionView
      • Call the appropriate web service methods in these event handlers
      • In the QueryItems event, call the web method asynchronously
  • I mentioned using ASP .Net session state for my solution in my previous post. This sample does not do that as the web service uses a static data set. My guess is that you will have to implement some sort of persistence (like ASP .Net session state) or notification mechanism in your app if you will be working with non-static data. In the case of my previous post, I used ASP .Net session state to persist the dataset (of RSS feed items) that is currently bound to the datagrid to keep the dataset virtually static on the server (i.e., the server will work on the persisted dataset in session state instead of live data in the database that is prone to change every few minutes --- I know that this solution generally does not scale well but it is acceptable in my case).
  • The solution was built with version 3.1 of the Xceed DataGrid for WPF (version 3.2 was released recently).

Data Virtualization with Xceed DataGrid for WPF

I wrote about my adventures in converting a Web application (BusterNews.com) to WPF in a previous post. In that article, I briefly mentioned that I wanted to set the new application apart from its web counterpart by presenting feed items in a contiguous list instead of the ‘paged’ approach of a web application. The main challenge in accomplishing this goal was that the application’s data source is a web service (no data is cached on the client), and so providing this feature was not as straightforward as using a built-in WPF feature. Fortunately, it was as straightforward as utilizing the Xceed DataGrid’s data virtualization capabilities (available on the Pro version).

Before I continue, let me point out that Xceed provides a far more detailed sample project (which was the basis of my solution) in their documentation. My focus in this post is the technique I used for integrating the web service as a data source of the data grid; the feature set I use is only a small subset of the data virtualization capabilities of the datagrid control.

Back to the problem: I wanted to present feed items such that a user can navigate anywhere in the list just as they would in a desktop application like Outlook. The problem was that certain feeds may have thousands of items and bringing this data back from a web service may be very costly in terms of bandwidth and perform poorly from the user experience perspective. The image below shows a sample of this case --- news feeds like MSNBC may contain thousands of items over a period of two weeks because it updates many times a day.

BusterNews Reader

My solution consisted of two main parts:

  1. Setting-up the datagrid for virtualization
  2. Setting up web services to serve the data that the datagrid needs

Setting up the DataGrid

Setting up the DataGrid requires configuring it with a DataGridVirtualizingCollectionView data source and setting event handlers for the specified data source.

The following XAML code block shows part of the declaration that includes binding to the datasource:

 

The ItemsSource property is bound to a ReaderFeedItems dependency property of the page which is a DataGridVirtualizingCollectionView type. The property is set up as follows:

 

The code above shows the following:

  1. ReaderFeedItems is set to a DataGridVirtualizingCollectionView with a page size (m_feedItemsPageSize) and a maximum realized item count (m_feedItemsMaxRealizedItemCount). This sets up the datagrid with a special collection view that knows how to perform data virtualization. The collection view is configured with settings for managing the paging of data items and memory.
  2. Handlers are set for the different data virtualization events:
    • The QueryItemCount event occurs when the datagrid needs to know how many items are in the data source.
    • The QueryItems event occurs when the datagrid needs a page of data.
    • The AbortQueryItems event occurs when the request for a page of data is cancelled.

The event handlers look something like this:

The code above shows the following:

  • ReaderFeedItems_QueryItemCount calls a web service to get the feed items count for the currently selected feed source.
  • ReaderFeedItems_QueryItems makes an asynchronous call to a web service for the set of data requested by the data grid. When the asynchronous call is successfully completed, the data returned is passed back to the datagrid. This is shown in the following event handler code:

The solution is generally as simple as that.

One significant implementation note I would like to make is that I had to cache the datasets (using ASP .Net session state) on the server side to keep return values for queries consistent throughout a user session. Without this, data virtualization will fail once the data changes as the application currently has no mechanism for getting notified when new feed items for the current dataset have come in.

WPF Value Converter via MarkupExtension

Dr. WPF had a great post about deriving a value converter from MarkupExtension to avoid having to declare the converter as a static resource before being able to access it. This is a very convenient way of providing a value converter with less steps. I extended his technique and created a generic abstract class that can be used to derive value converters from to avoid the repetitive code that I would need to remember per his approach.

Here’s the result:

    // Base class
    public abstract class ConverterMarkupExtension<T> : MarkupExtension, IValueConverter
    where T : class, new()
    {
        private static T m_converter = null;
        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            if (m_converter == null)
            {
                m_converter = new T();
            }
            return m_converter;
        }
        #region IValueConverter Members
        public abstract object Convert(object value, Type targetType, 
            object parameter, System.Globalization.CultureInfo culture);
        
        public abstract object ConvertBack(object value, Type targetType, 
            object parameter, System.Globalization.CultureInfo culture);
        #endregion
    }
    //Sample derived class
    public class BytesToKBValueConverter : ConverterMarkupExtension
    {
        public override object Convert(object value, Type targetType, 
            object parameter, System.Globalization.CultureInfo culture)
        {
            if (value != null && value is double)
            {
                double bytes = System.Convert.ToDouble(value);
                return bytes / 1024.0d;
            }
            else
                return value;
        }
        public override object ConvertBack(object value, 
            Type targetType, object parameter, 
            System.Globalization.CultureInfo culture)
        {
            throw new NotSupportedException();
        }
    }

…and a sample markup to use the value converter:

image 

This approach also made it easier to convert my existing value converters.

 

Converting a Web Application (BusterNews.com) to a WPF Desktop Application

I wrote BusterNews.com in 2004 as a personal exercise in ASP .Net. The application has served me very well through the years as my online RSS reader. I recently found myself writing a counterpart of the reader in WPF.

I have been contemplating to convert BusterNews.com into a rich Internet application (RIA) since the first beta of Silverlight came out a long time ago. I have never been able to do it due to the limits of time and technology. However, for most week nights the past week and a half, the stars aligned for me to come up with a decent WPF version of the reader part of the application. Although it is not an RIA, I should be able to easily convert this version into a XAML Browser Application (XBAP), then, eventually, into a Silverlight application.

I think being able to come up with this application in a relatively short period of time was due mostly to the following:

  1. The application to be converted was already stable – a good data model is already in place and ready for consumption.
  2. I am now more familiar with the tools and technologies to be used to meet my objective.

Technical Implementation

On the back-end, the SQL Server database is unchanged. However, I wrote ASP.Net web services to provide the inter-op services between the WPF application and the database. The Entity Framework and LINQ provided means to rapidly implement these. My current version is noticeably slower (but acceptable) in performance than the original because it does not (yet) use stored procedures.

On the front-end, WPF provides the technology to come up with a rich, interactive application. Although I haven’t taken advantage of many of WPF’s UI features such as animation, effects, etc., the GUI that I came up with is significantly more useful than the web version (e.g., using the FlowDocumentReader control, I provide instant features for searching content and changing a document’s view). WPF’s powerful data binding features also provide the services I need to easily present the same data in many places, in different ways. In addition to this, a crucial component of the application is the Xceed DataGrid for WPF which provides data virtualization (a topic for a separate blog entry) --- while BusterNews.com provides a view of the data in pages, the WPF version, despite having a web service as a data source, is able to provide virtually a full view of the data without much negative impact on performance.

The application is deployed as published ClickOnce application so I get the benefits of being able to install the application from the web, as well as the online update features of ClickOnce applications to easily upgrade to new versions (this was very useful in testing, to update my test installations as I found bugs). Deploying the application is as easy as using the ‘Publish’ option from Visual Studio 2008 and specifying the publishing information.

Challenges

I encountered some challenges in coming up with this application, probably mostly due to lack of planning; I have had this project at the back of my mind for a long time and then it ‘just happened.’ Some of the real technical challenges I encountered were:

  1. Designing the web services – I initially planned to keep the web services stateless. However, I ended up using session state as it plays a major role in my implementation of data virtualization. I struggled with making this decision for a relatively long time but I think I made the right one.
  2. Converting HTML to XAML – RSS feeds for blogs are usually formatted in HTML. In a web application, it does not take much effort to display HTML. In a WPF application, however, presenting HTML is not as easy. Although there is a web browser control that could host the HTML, the control is just a wrapper to the IE browser control and does not play well with WPF in terms of presentation, just like Windows Forms controls. The solution was to find a way to convert HTML to XAML. This took a lot of effort. I found two top contenders for my implementation – XAML/HTML Converter and SgmlReader. I ended up using XAML/HTML Converter, modifying the code slightly to fit my requirements, including support for images; this is still a work in progress but I can live with the current version that I have.
  3. Presenting data – As I mentioned above, BusterNews.com presents a view of data in pages, as is common in web applications. I wanted to overcome this limitation in my WPF application. The challenge was that the data source for the application is a web service and I wanted the application to perform as if the application had a direct connection to the data and show the data in a contiguous list rather than in pages. The Xceed DataGrid for WPF (Professional Edition) solves this problem for me by providing data virtualization (I will talk about this in a separate blog entry). The result is a responsive application that requests just the right amount of data from the web service (if it is not already in memory) as is needed by the current view of the user.

The result

Following are screen shots of BusterNews.com and its WPF counterpart, BusterNews Reader, respectively.

BusterNews.com

BusterNews Reader 

This has been an exciting exercise for me, to make the old new again. My next step is to convert the WPF application into an XBAP to make it more web-friendly; hopefully within the next few weeks.

Links:

Technorati Tags:

Xceed DataGrid for WPF Version 3.1 Released

Xceed Live Explorer Xceed recently released version 3.1 of their excellent DataGrid control for WPF. I have been using their free Express Edition (v2.0) for the past year and my applications have benefited a lot from the powerful built-in features that it provides. This control has saved me a lot of time in coding, as well as designing the presentation of data.

The Express edition includes other free and useful controls like a DatePicker and NumericTextBox. Xceed provides great free support resources too --- browsing their community forums has answered a lot of my questions ranging from the simple, ‘Getting Started’, type, to the more involved and task/design-specific ones.

Links:

Technorati Tags: ,

Office Automation: Fix for Application Crashing After ‘CodeModule.AddFromString’

I had a problem with Microsoft Office Word 2003 crashing after calling CodeModule.AddFromString to add custom code to the document. The code was creating command buttons on-the-fly, then adding the corresponding event handler code for each button’s Click event.

I was able to successfully get AddFromString to run in a simple version of the project. However, after adding the real, more complex logic, Word started to crash. Browsing user forums was of little help in finding a reliable solution --- a lot of experts discouraged the technique as it alters the state of the code at runtime. That makes sense, but in my case I really needed to create the command buttons at runtime as the workflow of the document requires it.

In my testing, I found that the crash does not happen when I display MsgBox’s. It seems to me that the crash was happening as a matter of a timing issue. After hours of trial-and-error and analysis, the solution that I found was related to this theory: call AddFromString last (or as late as possible) and only once. My workflow was such that I needed to create multiple command buttons and event handlers for each one that was created. The logic in my code executed such that for each iteration of the button creation, an event handler was created via AddFromString. My code was calling AddFromString multiple times. I also had another part of the application where AddFromString is called only once but other automation functions were performed on the document afterwards; this also crashed the application.

Forming all of the necessary code into a string and writing it via AddFromString (only once) at the end of a routine fixes the problem.

Note: I mentioned above that the solution is to call AddFromString last or as late as possible. I have one case that works where AddFromString is second to the last piece of code that executes --- the last piece deletes parts of the document that the code for AddFromString is dependent on.

Link: How to add a button to a Word document and assign its Click event at run-time

«March»
SunMonTueWedThuFriSat
28123456
78910111213
14151617181920
21222324252627
28293031123
45678910