Friday, January 21, 2011

AutoLoading more content when you scroll to the bottom of a ListBox in WP7 (Windows Phone 7)

I've just implemented this for Overflow7.

The approach I took was similar to http://blog.slimcode.com/2010/09/11/detect-when-a-listbox-scrolls-to-its-end-wp7/

However, instead of using a Style I did the hook up in code.

Basically derived my parent UserControl from:

     public class BaseExtendedListUserControl : UserControl
{
   
DependencyProperty ListVerticalOffsetProperty = DependencyProperty.Register(
     
"ListVerticalOffset",
     
typeof(double),
     
typeof(BaseExtendedListUserControl),
     
new PropertyMetadata(new PropertyChangedCallback(OnListVerticalOffsetChanged)));

   
private ScrollViewer _listScrollViewer;

   
protected void EnsureBoundToScrollViewer()
   
{
       
if (_listScrollViewer != null)
           
return;

       
var elements = VisualTreeHelper.FindElementsInHostCoordinates(new Rect(0,0,this.Width, this.Height), this);

        _listScrollViewer
= elements.Where(x => x is ScrollViewer).FirstOrDefault() as ScrollViewer;

       
if (_listScrollViewer == null)
           
return;

       
Binding binding = new Binding();
        binding
.Source = _listScrollViewer;
        binding
.Path = new PropertyPath("VerticalOffset");
        binding
.Mode = BindingMode.OneWay;
       
this.SetBinding(ListVerticalOffsetProperty, binding);
   
}

   
public double ListVerticalOffset
   
{
        get
{ return (double)this.GetValue(ListVerticalOffsetProperty); }
        set
{ this.SetValue(ListVerticalOffsetProperty, value); }
   
}

   
private static void OnListVerticalOffsetChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
   
{
       
BaseExtendedListUserControl control = obj as BaseExtendedListUserControl;
        control
.OnListVerticalOffsetChanged();
   
}

   
private void OnListVerticalOffsetChanged()
   
{
       
OnListVerticalOffsetChanged(_listScrollViewer);

   
}

   
protected virtual void OnListVerticalOffsetChanged(ScrollViewer s)
   
{
       
// do nothing
   
}
}

this then meant that in the user control itself I could just use:

         protected override void OnListVerticalOffsetChanged(ScrollViewer viewer)
   
{
       
// Trigger when at the end of the viewport
       
if (viewer.VerticalOffset >= viewer.ScrollableHeight)
       
{
                // actually do the load here!
        }
   
}

   
private void ListBox1_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
   
{
       
EnsureBoundToScrollViewer();
   
}

The "hacky" thing here was that I had to use ListBox1_ManipulationCompleted and VisualTreeHelper to find my ScrollViewer - I'm sure there are better ways...

Wednesday, January 19, 2011

TextWrapping for HyperlinkButton on Windows Phone 7 WP7

Thanks to MisterGoodcat!

From:

This is the magic style:
 <Style x:Key="HyperlinkButtonWrappingStyle"         TargetType="HyperlinkButton">     <Setter Property="Foreground"             Value="{StaticResource PhoneForegroundBrush}" />     <Setter Property="Background"             Value="Transparent" />     <Setter Property="FontSize"             Value="{StaticResource PhoneFontSizeMedium}" />     <Setter Property="Padding"             Value="0" />     <Setter Property="Template">         <Setter.Value>             <ControlTemplate TargetType="HyperlinkButton">                 <Border Background="Transparent">                     <VisualStateManager.VisualStateGroups>                         <VisualStateGroup x:Name="CommonStates">                             <VisualState x:Name="Normal" />                             <VisualState x:Name="MouseOver" />                             <VisualState x:Name="Pressed">                                 <Storyboard>                                     <DoubleAnimation Duration="0"                                                         To="0.5"                                                         Storyboard.TargetProperty="Opacity"                                                         Storyboard.TargetName="TextElement" />                                 </Storyboard>                             </VisualState>                             <VisualState x:Name="Disabled">                                 <Storyboard>                                     <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground"                                                                     Storyboard.TargetName="TextElement">                                         <DiscreteObjectKeyFrame KeyTime="0"                                                                 Value="{StaticResource PhoneDisabledBrush}" />                                     </ObjectAnimationUsingKeyFrames>                                 </Storyboard>                             </VisualState>                         </VisualStateGroup>                     </VisualStateManager.VisualStateGroups>                     <Border Background="{TemplateBinding Background}"                             Margin="{StaticResource PhoneHorizontalMargin}"                             Padding="{TemplateBinding Padding}">                         <TextBlock x:Name="TextElement"                                     HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"                                     Text="{TemplateBinding Content}"                                     TextDecorations="Underline"                                     VerticalAlignment="{TemplateBinding VerticalContentAlignment}"                                     TextWrapping="Wrap" />                     </Border>                 </Border>             </ControlTemplate>         </Setter.Value>     </Setter> </Style>

Thursday, January 13, 2011

Important Update - for submitting to WP7 Marketplace

Further to this marketplace advice: http://slodge.blogspot.com/2010/11/marketplace-advice-for-wp7-windows.html

This year I've discovered that the Marketplace is getting very strict on making sure apps include:
- App Name
- Version Number
- Support contact info

You have been warned!

iron7

iron7 is an IronRuby scripting environment for WP7

Not sure I can explain it very easily in words - maybe better to just show you these videos and to point you to http://www.iron7.com and http://script.iron7.com






Recent App Experiments

Not blogged here much recently... sorry!

Main reason is because I've been posting info over on http://iron7.com

This includes an MVC3 Razor app linking to jquerymobile - see http://script.iron7.com

However, to make up for this, here's a video of my latest WP7 app - a translation app called Translate-A-Bull - it includes: audio and animation - yes, that's right I finally used Expression Blend!

Here's a video:

One of my new favourite coding toys

I'm still very new to this Silverlight game... and there really doesn't seem to be much "XAML" out there for people to use in animations.

However.... this converter turns SVG into XAML - and there are heaps of free SVG images out there:
http://www.graphspe.com/svg-to-xaml-converter#/Converter

There are a few issues with the converter (doesn't quite work perfectly for WP7) but overall it's great!

Aside: There's also a codeplex project called XamlTune - but I couldn't get that to work on my XAML - it kept crashing :/ 


Wednesday, January 12, 2011

Some stats on WP7 App Sales


RunSat Free:


RunSat Full:

Note that the full app includes both "trial" and "paid" apps - about 20% are paid (so I've sold about 100 copies so far!)

One more set of stats - so far:
  • 35 reviews of RunSat Free - ~0.5%
  • 8 reviews of RunSat Full - ~2%

I've not thought deeply about these stats - I'll let others make their own conclusions for now!

Saturday, December 11, 2010

Error 80020006 on WP7 InvokeScript on the WebBrowser

^&$%...

If you hit this error...

Check you've set <phone:WebBrowser IsScriptEnabled="True" >

Doh! Another hour of my life gone!

Thursday, December 09, 2010

Switching to Azure SDK 1.3

I've had "quite a few" issues switching to the new SDK for Azure.

Most of these have been in big solutions where projects seem intent on continuing to reference the old 1.0.0.0 StorageClient - hopefully that's now all done (just that little flag to change which stops them referencing "Specific Version")

One configuration change concerned diagnostics - Neil McKenzie's post helps with this http://convective.wordpress.com/2010/12/01/configuration-changes-to-windows-azure-diagnostics-in-azure-sdk-v1-3 - but really the easiest way to update your diagnostics is to use the "properties wizard" for each role within the Azure cloud project in your solution.

Overall I quite like most of the 1.3 changes - the problems I've hit as a result haven't been fun, but I understand why the changes are needed... Forwards!

Tuesday, December 07, 2010

If you're fiddler POST posts aren't correctly getting the form variables...

... make sure you've set the header:
Content-type: application/x-www-form-urlencoded
Couldn't see why my POST wasn't working - it was just a missing header - doh!

Wednesday, December 01, 2010

My "presentation" to the Windows Phone User Group

I did this "presentation" using Notepad - it was all a bit last minute....

The theme of it was about how I've just built my first WP7 app - RunSat - and the lessons learned

I think (hope?) the presentation was better when it had a demo attached!




Timeline
- last November Samsung gave me a Omnia II.
- then I bought an iPhone
- then Samsung gave me a Bada phone
- 12 days ago I wrote my first Silverlight/WPF app
- then last Thursday Paul Foster lent me a WP7 phone







1. Wp7 development is a pleasure compared to:
WP7 dev was a pleasure
- PC dev, 
- WinCE (MFC, then CF2) on Wm6.5, 
- Monotouch, 
- Obj-C xCode, 
- Bada C++
- a teeny bit Eclipse/Android






2. Installation of the tools was super quick 
Zune for PC installation was a bit slow...










3. Device-based dev is super fast, reliable and painless  
- debugging support is great 
- really miss wifi debugging from MonoTouch








4. Emulator-based dev is a bit slower! 
And lack of GPS in emulator is a pain
Some workarounds available - e.g. reactive










5. Silverlight/XAML 
as a non-user 10 days ago, I've found this very easy to pick up 
- but I'm a world away from mastering XAML.
- efficiency doesn't seem to matter ?

- Blend makes blood come out of my ears





6. Tombstoning is actually pretty easy

- unless your data doesn't really fit 

- mine didn't









7. When you Google (Bing?) around for sample code, it's definitely a bit confusing working out what WPF/SL3/SL4 code/xaml will work on WP7

- but there is lots of good blogging available :)








8. Bing maps integration was super quick and super nice :)

- didn't support MVVM perfectly









9. Fighting the Appstore guidelines - I hate the app stores

- app store approval gotchas...
--- pivot control abuse?
--- GPS - request access yourself and supply privacy
--- run idle - request access yourself
--- help and support
--- dark/light theming



10. Cross platform 
- this app came from WM6.5
- it went to Monotouch
- it went from Monotouch to WP7
- next up is MonoDroid (preview 7 already)







Details of cross platform

- GPS integration - just effected one module
- File IO - main IO just worked
- BUT open/close/exists/delete code needed changing for IsolatedStorage
- DateTime (clock) source information
- XML serialisation - XMLDocument not available on WP7 - had to port code across to XDocument - not a biggie - also used JSON.Net
- Web services calls - legacy ASMX didn't work... had to hand craft my XML :( - Would probably have been quicker to change the server api's to newer WCF services.









Cross platform

- big story is how much I haven't rewritten...

- UI - lots of new code to write

---- tables/lists
---- WP7 Pivot/Panorama controls against tables and paged scrollviews
---- notifications

- MVVM pattern made this very manageable (UIDialog on MonoTouch also made my life much simpler) 
- will be much easier again in 2 days time?

- app lifecycle management - still working this out - tombstoning is quite straight forward but requires thought...

- tests... nunit runs on all platforms

Tuesday, November 30, 2010

Marketplace advice for WP7 Windows Phone 7

This post is priceless - http://blogs.msdn.com/b/wsteele/archive/2010/10/15/important-info-for-wp7-application-developers.aspx

1) READ the docs!!!

2) Know your iconography.

3) Support Information – Test Case 5.6.

4) Toast Notification – Test Case 6.2

5) Applications Running Under a Locked Screen – Test Case 6.3

6) Back Button – Test Case 5.2.4
7) Themes – Test Case 5.1.1
8) Languages.
9) Failures upon Upload to the Marketplace
10) Windows Phone Developer Tools.

    Sunday, November 28, 2010

    Razor MVC3, a file upload form

    @using (Html.BeginForm("CreateStepUpload", "Pivot", FormMethod.Post, new { enctype = "multipart/form-data" }))
    {
        @Html.ValidationSummary(true)
        <fieldset>
            <legend>Fields</legend>

            <div class="editor-label">
                File:
            </div>
            <div class="editor-field">
                <input type="file" name="theFile" id="theFile" />
            </div>
            <p>
                <input type="submit" value="Save" />
            </p>
        </fieldset>
    }

    Razor, MVC3 - a readonly textbox

    Code is:

    @Html.TextBoxFor(model => model.Fields[i].TheField, new { @readonly = true })

    Saturday, November 27, 2010

    Ssssshhhh - don't tell anyone but I'm enjoying web dev with ASP.Net MVC3 and Razor

    Just very impressed at the moment that my ViewModels are flying in/out of my Controllers with quite a lot of ease...

    Also impressed with how clean Razor feels compared to old ASP.Net

    Also impressed with how easy it is to extend the Expression<> based HtmlHelper code.

    ...

    A couple of things I've done that show how I'm techie enjoying myself:
    1. Enabling email verification was easy -  mainly thanks to Kevin at http://thekevincode.com/2010/09/adding-email-confirmation-to-asp-net-mvc/ 

    2. Creating enum based drop down select boxes was easy - just used http://blogs.msdn.com/b/stuartleeks/archive/2010/05/21/asp-net-mvc-creating-a-dropdownlist-helper-for-enums.aspx - then in Razor:

    @using MyExtensionsNamespace

    Some HTML

    @for (var i = 0; i < Model.MyProperty.Count; i++)
    <div>
    @Html.EnumDropDownListFor(model => model.MyProperty[i].MyEnumField)
    </div>
    }

    3. Using list collections was easy - see the snippet above - it just works when you then collect the ViewModel back in to the Controller Action method too :)

    4. Adding my own Model error was easy with ModelState.AddModelError 

    Thursday, November 25, 2010

    Getting Windows Phone 7 development working

    So I managed to borrow a Windows Phone 7 for some dev work :)
     
    I already had the basic tools installed and had been using the emulator.

    But to get the phone dev working...
    - you need to install the October 2010 update to the tools
    - you need to download and install the zune PC software (60MB download and requires reboot!)
    - you need to log on inside the zune PC software
    - you need to use the "Windows Phone Developer Registration tool" to unlock your phone

    Some more help here:

    The good news is... this all worked :) Took about 2 hours to get going, most of that spent downloading Zune stuff!

    Wednesday, November 24, 2010

    Razor outputting raw unescaped HTML.. ASP.Net MVC3

    In general I love the look and feel of the new Razor View Engine - works really well.

    However if you ever want to output raw HTML then it's a bit ugly - e.g. to output some JSON I did:

    var currentConnectionStrings = @(new HtmlString(Json.Encode(Model.ConnectionStrings)));

    It would be nice if this instead did something like @=Json.Encode(Model.ConnectionStrings) - or some other "special" character combination

    JQuery - responding to selected tab using tabselect

    If you have a standard jquery UI tabs setup:

                <div id="tabs-project">
               <ul>
               <li><a href="#tabs-project-core">Details</a></li>
               <li><a href="#tabs-project-connections">Connections</a></li>
               <li><a href="#tabs-project-alerts">Alerts</a></li>
               </ul>
               <div id="tabs-project-core">
                       etc...             
                </div>
               </div>

    And you want to determine which tab has been pressed by name (not index - because index might changed when code gets moved or if tabs get inserted..) then you can use:
     
            function getIndexOfTabAnchor(name) {
                return $("a[href*=#" + name + "]").parent().index();
            } 
            $("#tabs-project").tabs({
                select: function (event, ui) {
                    if (ui.index == getIndexOfTabAnchor('tabs-project-jobs')) {
                        // do jobs stuff...
                    }
                    else if (ui.index == getIndexOfTabAnchor('tabs-project-schedules')) {
                        // do schedules stuff...
                    }
                }
            });

    Note that getIndexOfTabAnchor() uses http://api.jquery.com/attribute-contains-selector/

    Awesome comparison of the costs and benefits of Azure versus AWS

    I've just stumbled upon this awesome analysis of some Azure versus AWS services.

    I think there are several strategic and architectural things to consider when choosing between the two services - choosing to deploy roles on Azure is an application lifestyle choice compared to choosing OS deployment and system admin on EC2 - and both lifestyles have their problems!

    There's lots of good material in here:
    http://compositecode.com/2010/11/01/cloudthrowdown-part1/

    Monday, November 22, 2010

    PivotViewer, shared images and memory problems

    I've spent a large chunk of the last weekend playing with the Silverlight PivotViewer from Microsoft.


    It's lovely!

    Despite the official upper limit on number of items being "3000", I've taken it up as high as 73000 items now - the animations don't work at that level, but the pivotviewer is very very useful there!

    You can see some screenshots (attached hopefully!) and there's also one "live" demo on http://zoom.runsaturday.com

    The only downside - there have been a few issues I've had - one of the key ones of which is:
    • if you create a .cxml collection in which items don't each have unique images (e.g. they share a default image) then the Silverlight control does something odd - it somehow seems to try to duplicate the shared images and uses up lots of CPU and memory as a result.
    This bug is reported in a bit more detail on this thread - http://forums.silverlight.net/forums/t/210211.aspx:

    To recap:

    • the bug is for collections where <Item>s share img references.
    • if I load up one of these collections in the standalone viewer these work fine
      - the load is smooth and the memory use is expected.
    • if I load up the same collection in the silverlight pivotviewer then the items with shared images
      take a long time to display (they pop into the display one by one) and the memory use is higher
      - it increases with each image loaded.

    You can just about see this effect if you watch the swimmer icons when you first load up:

    The effect is really really noticable when you get to larger data sets

    Sunday, November 21, 2010

    Numpty Silverlight DataBinding continues....

    So if you are doing Silverlight or WPF and you're trying to do MVVM... and you sit there wondering why your ObservableCollection<T> just isn't working...

    ... then consider it might just be....

    ... because you are an idiot and you declared your code:

    public ObservableCollection MyCollection;

    when it should of course have been...

    public ObservableCollection MyCollection {get;set;}

    Arggggggggggggggh! Serves me right for coding on Sunday night! 

    Some hacky fixes to PAuthor PivotViewer library

    Overall the PAuthor project for creating PivotViewer for Silveright datasets works great - I've used in in .Net4 for 4 separate command line apps :)

    However, when working on some large data sets (around 75000 Items) I found the following problems - mostly to do with corrupt items in my input.

    Hope this post helps other people...

    Problems seen in collectionCreator.Create(m_dziPaths, m_dzcPath); in ParallelDeepZoomCreator.cs

    • System.ArgumentException in ParallelDeepZoomCreator.cs due to problems in my item names (some of my names included the "*" wildcard character - doh!
    • And System.IO.FileNotFoundException in ParallelDeepZoomCreator.cs due to unknown problem (no real clue why these particular folders didn't exist - it was 8 out of 75000...)

    To fix these I just wrapped the call with: 

                 List<String> toRemove = new List<string>();             foreach (var c in m_dziPaths)             {                 try                 {                     System.Security.Permissions.FileIOPermission f = new System.Security.Permissions.FileIOPermission(                             System.Security.Permissions.FileIOPermissionAccess.AllAccess, c);                 }                 catch (ArgumentException exc)                 {                     toRemove.Add(c);                     System.Diagnostics.Trace.WriteLine("INVALID PATH " + c);                 }             }             foreach (var c in toRemove)             {                 m_dziPaths.Remove(c);             }              while (true)             {                 try                 {                     DZ.CollectionCreator collectionCreator = new DZ.CollectionCreator();                     collectionCreator.Create(m_dziPaths, m_dzcPath);                     break;                 }                 catch (System.IO.FileNotFoundException exc)                 {                     System.Diagnostics.Trace.WriteLine("STUART - SORRY - REMOVING " + exc.FileName);                     m_dziPaths.Remove(exc.FileName);                 }             } 


    Some multithreaded problem seen in image download

    The finalizer for PivotImage.cs occasionally sees IO exceptions in the File.Delete operation - the exception claims that the fie is currently open in another process.

    Not sure what is causing this - my guess is it's a multithreading issue of some description.

    To fix (mask) this I simple added a try catch to the finalizer:


            ~PivotImage()         {             if (m_shouldDelete == false) return;             if (File.Exists(m_sourcePath) == false) return;              try             {                 File.Delete(m_sourcePath);             }             catch (IOException)             {                 System.Diagnostics.Trace.WriteLine("Some clean up needed " + m_sourcePath);             }         } 

    That's it - hope it helps someone.

    Saturday, November 20, 2010

    Using the Silverlight PivotViewer Control and seeing NotFound when deployed on IIS

    If you build and test your lovely new PivotViewer SL app and then when
    you deploy to a full IIS server you see "NotFound" reported for your
    collection, then...

    Make sure you've set the mimetype for .cxml, .dzi, .dzc all as
    text/xml within IIS for your current website.

    Worked for me :)

    Helpful suggestion found on :
    http://forums.silverlight.net/forums/p/194861/452655.aspx