Dienstag, 14. Dezember 2010

Windows Phone recipes – Open source projects

Windows Phone recipes are open source (MSPL) projects aimed at helping Windows Phone developers with their Windows Phone applications. Recipes are usually common patterns for topics that require some attention. The idea is to provide a sample with some reusable code that can be reused later and modified to fit other similar scenarios. Developers are more than welcome to use them as is, or to change them as they see fit.

Windows Phone Recipes – Helping the Community

Samstag, 11. Dezember 2010

Windows Phone 7: Grid style listbox

If you want to implement a grid for your Windows Phone 7 app you have to use a Listbox control because of the missing DataGrid at the Windows Phone 7 platform. A first idea for contsructing a Grid then could be to use the WrapPanel control in your ItemTemplate of the Listbox control. But if you do this, the data virtualization of the ListBox will be disabled (Virtualizing Data in Windows Phone 7 Silverlight Applications - Peter Torr's Blog - Site Home - MSDN Blogs). This will increase the loading time of your ListBox and results in a very poor UX handling. The problem is, that you can not use any complex data structures in the ItemTemplate at a Listbox for Windows Phone 7. Every line in the Listbox should be one data line. So a solution for developing a grid styled Listbox is to implement a RowAdapter class for your bounded data.

Here a implementation of a RowAdapter, I used in one of my projects:

public class RowAdapter<TItemType> : IList<IEnumerable<TItemType>>, INotifyCollectionChanged
    {
        private readonly IList<TItemType> _sourceList;
        private readonly int _columns;
 
        private class RowObject : IEnumerable<TItemType>
        {
            internal readonly RowAdapter<TItemType> Parent;
            internal readonly int StartIndex;
 
            public RowObject(RowAdapter<TItemType> parent, int startIndex)
            {
                Parent = parent;
                StartIndex = startIndex;
            }
 
            #region IEnumerable<TItemType> Members
 
            public IEnumerator<TItemType> GetEnumerator()
            {
                int limit = Parent._sourceList.Count;
                int end = Math.Min(StartIndex + Parent._columns, limit);
 
                for (int pos = StartIndex; pos < end; ++pos)
                {
                    yield return Parent._sourceList[pos];
                }
            }
 
            #endregion
 
            #region IEnumerable Members
 
            System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
            {
                return GetEnumerator();
            }
 
            #endregion
        }
 
        public RowAdapter(IList<TItemType> sourceList, int columns)
        {
            if (null == sourceList)
                throw new ArgumentNullException("sourceList", Resource.RowAdapter_RowAdapter_sourceList_is_null);
            if (columns <= 0)
                throw new ArgumentOutOfRangeException("columns", Resource.RowAdapter_RowAdapter_ColumnsGreaterOne);
 
            // We require the source list to implement IList because we
            // need to know how many item there are
            _sourceList = sourceList;
            _columns = columns;
 
            var sourceNotify = sourceList as INotifyCollectionChanged;
            if (null != sourceNotify)
            {
                sourceNotify.CollectionChanged += OnSourceCollectionChanged;
            }
        }
 
        #region IList<IEnumerable<TItemType>> Members
 
        public int IndexOf(IEnumerable<TItemType> item)
        {
            var realItem = item as RowObject;
            if (null == realItem || !ReferenceEquals(realItem.Parent, this))
                return -1;          // It does not belong to this collection
 
            Debug.Assert(0 == realItem.StartIndex % _columns, "RowObject item has a wierd index");
            return realItem.StartIndex / _columns;
        }
 
        public void Insert(int index, IEnumerable<TItemType> item)
        {
            throw new NotSupportedException();
        }
 
        public IEnumerable<TItemType> this[int index]
        {
            get
            {
                if (index < 0 || index > Count)
                    return null;
 
                return InternalGetRow(index);
            }
            set
            {
                throw new NotSupportedException();
            }
        }
 
        public void RemoveAt(int index)
        {
            throw new NotSupportedException();
        }
 
        #endregion
 
        #region ICollection<IEnumerable<TItemType>> Members
 
        public void Add(IEnumerable<TItemType> item)
        {
            throw new NotSupportedException();
        }
 
        public bool Contains(IEnumerable<TItemType> item)
        {
            var realItem = item as RowObject;
            return null != realItem && object.ReferenceEquals(realItem.Parent, this);
        }
 
        public void CopyTo(IEnumerable<TItemType>[] array, int arrayIndex)
        {
            // I haven't implemented this. It is easy to implement if you need it
            throw new NotImplementedException();
        }
 
        public bool Remove(IEnumerable<TItemType> item)
        {
            throw new NotSupportedException();
        }
        public void Clear()
        {
            throw new NotSupportedException();
        }
 
        public int Count
        {
            get
            {
                return (_sourceList.Count + (_columns - 1)) / _columns;
            }
        }
 
        public bool IsReadOnly
        {
            get { return true; }
        }
 
        #endregion
 
        #region IEnumerable<IEnumerable<TItemType>> Members
 
        public IEnumerator<IEnumerable<TItemType>> GetEnumerator()
        {
            for (int i = 0; i < Count; ++i)
            {
                yield return InternalGetRow(i);
            }
        }
 
        #endregion
 
        #region IEnumerable Members
 
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
 
        #endregion
 
        #region INotifyCollectionChanged Members
 
        public event NotifyCollectionChangedEventHandler CollectionChanged;
 
        private void FireCollectionChanged()
        {
            
            var handler = CollectionChanged;
            if (null != handler)
            {
                handler(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
            }
        }
 
        private void OnSourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            FireCollectionChanged();
        }
 
        #endregion
 
        private RowObject InternalGetRow(int index)
        {
           return new RowObject(this, index * _columns);
        }
    }

Freitag, 3. Dezember 2010

Traps of Windows Azure Development

My personal traps of Windows Azure development for this week are:

  • Problems with long project names (longer 248) for the temporary name of my delivery package for running at the Windows Azure emulator
    • Use _CSRUN_STATE_DIRECTORY as environment variable to shorten the path
  • Remove PlatformTarget from an existing Web project file to avoid compile error
  • Strange CommunicationObjectFaultedException error if you use a Source Safe tool and your web.config is read only
  • If you use assemblies that are not content of a normal Windows Server 2008 SP2 installation (for example RIA Services), you have to set the properties “Copy Local” to true of the assemblies involved – otherwise you get a never ending “busy” state of your web role at Windows Azure Management Tools

Windows Azure: CommunicationObjectFaultedException

If your web.config is read only you get maybe the following strange error message in a Windows Azure project at runtime. It costs my half a day to find out, that this has nothing to do with my web service configuration or web service usage.

image

Mittwoch, 1. Dezember 2010

Hosting Silverlight Application with RIA Services as Cloud Service

We have an existing web project (Silverlight 4, WCF RIA Services) that we wanted to bring to the cloud using Windows Azure.  We added a new project, Windows Azure Cloud Service and added a new Web Role.  After this you can connect your existing web project to this web role. The isolated web project compiles fine, but our new solution brings the following compile error:

    “Error      1             The "CreateRiaClientFilesTask" task failed unexpectedly.System.Web.HttpException (0x80004005): Could not load file or assembly 'msshrtmi' or one of its dependencies. An attempt was made to load a program with an incorrect format. ---> System.Configuration.ConfigurationErrorsException: Could not load file or assembly 'msshrtmi' or one of its dependencies. An attempt was made to load a program with an incorrect format. ---> System.BadImageFormatException: Could not load file or assembly 'msshrtmi' or one of its dependencies. An attempt was made to load a program with an incorrect format.”

Strange, what happens and what can we do?

The solution is very easy, but hard to find out: You have to unload your .web project (which hosts the Silverlight application) and edit it the project file.  If you now remove the tags

    <PlatformTarget>AnyCPU</PlatformTarget>
from the project file, your solution can be compiled !

Sonntag, 28. November 2010

Windows Phone 7: Customize live tiles, push notification

Found a good article of Chris Koenig about customizing the tiles with Windows Phone 7 Push Notification Services:

Customizing WP7 Push Notification Tiles « Development « Chris Koenig

Montag, 22. November 2010

Windows Phone 7: Recording the microphone

Description and sample project for recording something with the Windows Phone 7 microphone.

Writing a Proper Wave File - CodeProject

Windows Phone 7: Video Player with MVVM pattern

If you plan to implement a video player for Windows Phone 7 you could found a good solution using the MVVM pattern here: Windows Phone 7 View Model Style Video Player - CodeProject

Freitag, 19. November 2010

Windows Phone 7: No forward navigation

Information forward navigation at Windows Phone 7:

Navigation Stack on Windows Phone 7 - Peter Foot - APPA Mundi

“While Windows Phone uses the same NavigationService and page-based model as “regular” Silverlight, one area the documentation doesn’t make clear is that although the APIs seem to support both Back and Forward navigation in reality there is no forward navigation on Windows Phone. This means when you navigate to a new page and then return Back to the previous page you can’t call NavigationService.GoForward() to return. CanGoForward will always return False. In the documentation for System.Windows.Controls.Frame (the base class of PhoneApplicationFrame) GoForward is described as:-

“Navigates to the most recent entry in the forward navigation history, or throws an exception if no entry exists in forward navigation. For Windows Phone this method will always throw an exception because there is no forward navigation stack.”

(my use of bold)”