PullToRefreshPanel

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!

Advertisements

~ by Matthijs Krempel on April 20, 2012.

14 Responses to “PullToRefreshPanel”

  1. Nice work Matthijs. Could you use a plugin that enables syntaxhighlighting for the code? Makes it easier to read.

  2. did you know there is a patent on pull to refresh? held by twitter?

  3. Hi Matthijs,

    I’m a community curator for DZone.com and I ran across your blog today while looking for content for our WIndows Phone Zone. I was wondering if you would be interested in having some of your recent posts republished on our site. If so, please send me an email so I can provide some more information.

    Thanks,

    Chris Smith

  4. Hi Matthijs,
    Thanks for awesome components:)

    I just updated “Krempel.WP7.Core” via NuGet to the current version, and it seems, that now HtmlTextBlock do not support (means, it do not see any changes) manually changed FontSize ,FontFamily, and Color Brushes for elements H1,H2,H3, and Hyperlinks. Just FontStyle and FontWeight works for that elements…

    Also, Hyperlinks, at previous version, respond when tapped on them by its color changes, but… now they static-look, just underlined…

    Please, check your NuGet version. Waiting for update:)
    Thanks and sry for my eng.

    • Hi Yurri,

      Is it possible for you to reload the HTML after you update the updated the styles?

      • I am not sure what you meant by “reload the HTML”, but I would tryin to describe a situation on a short example.
        Crete an empty project, install on it “Krempel’s WP7 Library”(1.1.0) via NuGet.
        Drop to the ContentPanel two components – HTMLTextBlock(With visual appeareance of H1,H2) and Button(With OnClick event).

        private void Button_Click(object sender, System.Windows.RoutedEventArgs e)
        {
        this.TestHTMLTextBox.Html=”Header just text Header2 Hyperlink“;
        }

        If you run this app, you will see, that HTMLTextBlock do not display height, font and color for H1,H2, that we set up.
        It use component’s properties – FontFamily,FontSize,Foreground brush for _all_ text in component. But in previous version of library all works awesome:)

      • Oh, I forget the main:

      • http://pastebin.com/kjAYP2he

      • i’ll look into it!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: