It has been a while since I blogged, it’s been busy. I have been neglecting my certifications, so I have got two and I am going for the third.

Never the less, no more excuses, let us get on with the show!

HTMLTextBlock update

I have updated the HTMLTextBlock, some bug fixes small bugfixes that you guys have asked for.

The control right now is basically a stack of RichTextBoxes with HTML translated to RichText XAML. For a future version I might drop this approach to support more rich layout features, such as tables. I am looking to build a visual tree from HTML and use the RichTextBox for displaying formatted text. I will keep you updated on my progress.

PullToRefreshPanel

For managing the playlist in the Channel9 Client for Windows Phone 7 I have used the excellent rearrangelistbox (also included in this release) from Jason Ginchereau. As a little treat inside the download of his control there is the PullDownToRefresh panel, which I have used extensively throughout the application. As he describes here, Mango changed the way the scrollviewer notifies the environment when it is stretched down. As an alternative he recommends changing the ManipulationMode of the ScrollViewer. But I have an alternative Glimlach.

Since Mango the scrollviewer works with VisualStates. The only problem is, the default template for the scrollviewer (the one in XAML) does not have these visual states. The scrollviewer can not find these states and does not transition to another visual state. The solution is to override the default style, with one of our own. This will require a little effort from your end. Copy and paste the following XAML fragment into your resource file (i.e. App.XAML);

<Style TargetType="ScrollViewer">
<Setter Property="VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="HorizontalScrollBarVisibility" Value="Auto"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ScrollViewer">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="ScrollStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="00:00:00.5"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="Scrolling">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="VerticalScrollBar" Storyboard.TargetProperty="Opacity" To="1" Duration="0"/>
<DoubleAnimation Storyboard.TargetName="HorizontalScrollBar" Storyboard.TargetProperty="Opacity" To="1" Duration="0"/>
</Storyboard>
</VisualState>
<VisualState x:Name="NotScrolling">
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="VerticalCompression">
<VisualState x:Name="NoVerticalCompression"/>
<VisualState x:Name="CompressionTop"/>
<VisualState x:Name="CompressionBottom"/>
</VisualStateGroup>
<VisualStateGroup x:Name="HorizontalCompression">
<VisualState x:Name="NoHorizontalCompression"/>
<VisualState x:Name="CompressionLeft"/>
<VisualState x:Name="CompressionRight"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid Margin="{TemplateBinding Padding}">
<ScrollContentPresenter x:Name="ScrollContentPresenter" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}"/>
<ScrollBar x:Name="VerticalScrollBar" IsHitTestVisible="False" Height="Auto" Width="5" HorizontalAlignment="Right" VerticalAlignment="Stretch" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" IsTabStop="False" Maximum="{TemplateBinding ScrollableHeight}" Minimum="0" Value="{TemplateBinding VerticalOffset}" Orientation="Vertical" ViewportSize="{TemplateBinding ViewportHeight}" />
<ScrollBar x:Name="HorizontalScrollBar" IsHitTestVisible="False" Width="Auto" Height="5" HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" IsTabStop="False" Maximum="{TemplateBinding ScrollableWidth}" Minimum="0" Value="{TemplateBinding HorizontalOffset}" Orientation="Horizontal" ViewportSize="{TemplateBinding ViewportWidth}" />
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

(Press Control K + D in Visual Studio after pasting.
Now we can listen for changes in the VisualState of the ScrollViewer to detect stretches (compression) to the various sides. How to use the control? Like all of my controls the usage is relatively straightforward Knipogende emoticon

<krempel:PullToRefreshPanel IsRefreshing="{Binding Loading}" StretchToDetect="Top" RefreshRequested="Refresh" PullingDownTemplate="{StaticResource PullUpAndHoldTemplate}" ReadyToReleaseTemplate="{StaticResource ReleaseToRefresh}" />
<toolkit:LongListSelector />  
<krempel:PullToRefreshPanel IsRefreshing="{Binding Loading}" StretchToDetect="Bottom" RefreshRequested="LoadMore" PullingDownTemplate="{StaticResource PullDownAndHoldTemplate}" ReadyToReleaseTemplate="{StaticResource ReleaseToLoadMore}" />

The PullToRefresh panel will search its parent container for the first ScrollViewer it can find. In this case the ScrollViewer of the LongListSelector. It then attaches an event handler to the VisualStateChanged event of the ScrollViewer and performs its magic The PullToRefreshPanel has several visual states which are toggled by a combination of the visualstate changes of the ScrollViewer and properties set on the panel. With the StretchToDetect property you can decide which of the stretches you want to react to. Then the user needs to hold the stretch for an amount in time set in milliseconds on the StretchDelay property. If all conditions are a go, the RefreshRequested eventhandler is executed. You can prevent multiple refreshes by setting the IsRefreshing property. There are three templates which can be used to display the different states of the panel;

  1. PullingDownTemplate, this will appear when the ScrollViewer is in the specified stretch mode
  2. ReadyToReleaseTemplate, this will appear after the specified timeout
  3. RefreshingTemplate, this will appear when the control is refreshing

So there you have it!

Download including an awesome example are available on CodePlex and the package is going to be updated in NuGet, soonish!

Let me know what you think in the comments!

Next time I will feature my piece de resistance turnstile navigation animation based on the Silverlight Toolkit for Windows Phone 7 Navigation animations!

Read from Source