Daily Gem: VB / Silverlight / WP7 – Disable Pinch or Scroll in IE9 WebBrowser control

Step 1:  Create a helper class for the WebBrowser

Code Snippet

  1. Imports System.Linq
  2. Imports System.Windows
  3. Imports System.Windows.Controls
  4. Imports System.Windows.Input
  5. Imports Microsoft.Phone.Controls
  6.  
  7.  
  8. Public ClassWebBrowserHelper
  9.     Private _browser As WebBrowser
  10.  
  11.     ”’ <summary>
  12.     ”’ Gets or sets whether to suppress the scrolling of
  13.     ”’ the WebBrowser control;
  14.     ”’ </summary>
  15.     PublicProperty ScrollDisabled() As Boolean
  16.         Get
  17.             Return m_ScrollDisabled
  18.         EndGet
  19.         Set(value As Boolean)
  20.             m_ScrollDisabled = value
  21.         EndSet
  22.     EndProperty
  23.     Private m_ScrollDisabled As Boolean
  24.  
  25.     PublicProperty PinchDisabled() As Boolean
  26.         Get
  27.             Return m_PinchDisabled
  28.         EndGet
  29.         Set(value As Boolean)
  30.             m_PinchDisabled = value
  31.         EndSet
  32.     EndProperty
  33.     Private m_PinchDisabled As Boolean
  34.  
  35.  
  36.     PublicSub New(browser AsWebBrowser)
  37.         _browser = browser
  38.         AddHandler browser.Loaded, NewRoutedEventHandler(AddressOf browser_Loaded)
  39.     EndSub
  40.  
  41.     PrivateSub browser_Loaded(sender As Object, e As RoutedEventArgs)
  42.         Dim border = TryCast(_browser.Descendants(OfBorder)().Last(), Border)
  43.  
  44.         AddHandler border.ManipulationDelta, AddressOf Border_ManipulationDelta
  45.         AddHandler border.ManipulationCompleted, AddressOf Border_ManipulationCompleted
  46.     EndSub
  47.  
  48.     PrivateSub Border_ManipulationCompleted(sender AsObject, e AsManipulationCompletedEventArgs)
  49.         ‘ optionally suppress pinch
  50.         IfPinchDisabled Then
  51.             If e.FinalVelocities.ExpansionVelocity.X <> 0.0 OrElse e.FinalVelocities.ExpansionVelocity.Y <> 0.0 Then
  52.                 e.Handled = True
  53.             EndIf
  54.         EndIf
  55.     EndSub
  56.  
  57.     PrivateSub Border_ManipulationDelta(sender AsObject, e AsManipulationDeltaEventArgs)
  58.         ‘ optionally suppress pinch
  59.         IfPinchDisabled Then
  60.             If e.DeltaManipulation.Scale.X <> 0.0 OrElse e.DeltaManipulation.Scale.Y <> 0.0 Then
  61.                 e.Handled = True
  62.             EndIf
  63.         EndIf
  64.  
  65.         ‘ optionally suppress scrolling
  66.         IfScrollDisabled Then
  67.             If e.DeltaManipulation.Translation.X <> 0.0 OrElse e.DeltaManipulation.Translation.Y <> 0.0 Then
  68.                 e.Handled = True
  69.             EndIf
  70.         EndIf
  71.     EndSub
  72. End Class

Step 2: Add the LinqToVisualTree module, used by the above class to help in locating the browser’s border control

Code Snippet
  1. Imports System.Linq
  2. Imports System.Collections.Generic
  3. Imports System.Windows
  4. Imports System.Windows.Media
  5. Imports System.Runtime.CompilerServices
  6.  
  7. <System.Runtime.CompilerServices.Extension()> _
  8. Module LinqToVisualTree
  9.     ”’ <summary>
  10.     ”’ Adapts a DependencyObject to provide methods required for generate
  11.     ”’ a Linq To Tree API
  12.     ”’ </summary>
  13.     PublicClass VisualTreeAdapter
  14.         ImplementsILinqTree(OfDependencyObject)
  15.         Private _item As DependencyObject
  16.  
  17.         PublicSub New(item AsDependencyObject)
  18.             _item = item
  19.         EndSub
  20.         PublicFunction Children() AsIEnumerable(Of DependencyObject) Implements ILinqTree(OfDependencyObject).Children
  21.             Dim list As New List(OfDependencyObject)
  22.             DimchildrenCount As Integer = VisualTreeHelper.GetChildrenCount(_item)
  23.             For i As Integer = 0 To childrenCount – 1
  24.                 list.Add(VisualTreeHelper.GetChild(_item, i))
  25.             Next
  26.             Return list
  27.         EndFunction
  28.  
  29.         PublicReadOnly Property Parent() AsDependencyObject ImplementsILinqTree(OfDependencyObject).Parent
  30.             Get
  31.                 ReturnVisualTreeHelper.GetParent(_item)
  32.             EndGet
  33.         EndProperty
  34.     EndClass
  35.     ”’ <summary>
  36.     ”’ Defines an interface that must be implemented to generate the LinqToTree methods
  37.     ”’ </summary>
  38.     ”’ <typeparam name="T"></typeparam>
  39.     PublicInterface ILinqTree(Of T)
  40.         Function Children() As IEnumerable(OfT)
  41.  
  42.         ReadOnlyProperty Parent() As T
  43.     EndInterface
  44.  
  45.     ”’ <summary>
  46.     ”’ Returns a collection of descendant elements.
  47.     ”’ </summary>
  48.     <Extension()>
  49.     PublicFunction Descendants(item AsDependencyObject) AsIEnumerable(OfDependencyObject)
  50.         Dim adapter As ILinqTree(OfDependencyObject) = NewVisualTreeAdapter(item)
  51.         Dim list As New List(OfDependencyObject)
  52.         ForEach child In adapter.Children()
  53.             list.Add(child)
  54.             Dim ad2 As ILinqTree(OfDependencyObject) = NewVisualTreeAdapter(child)
  55.             ForEach grandChild In child.Descendants()
  56.  
  57.  
  58.                 list.Add(grandChild)
  59.             Next
  60.         Next
  61.         Return list
  62.     EndFunction
  63.  
  64.     ”’ <summary>
  65.     ”’ Returns a collection containing this element and all descendant elements.
  66.     ”’ </summary>
  67.     <Extension()>
  68.     PublicFunction DescendantsAndSelf(item AsDependencyObject) AsIEnumerable(OfDependencyObject)
  69.         Dim list As New List(OfDependencyObject)
  70.         list.Add(item)
  71.         ForEach child In item.Descendants()
  72.             list.Add(child)
  73.         Next
  74.         Return list
  75.     EndFunction
  76.  
  77.     ”’ <summary>
  78.     ”’ Returns a collection of ancestor elements.
  79.     ”’ </summary>
  80.     <Extension()>
  81.     PublicFunction Ancestors(item AsDependencyObject) AsIEnumerable(OfDependencyObject)
  82.         Dim adapter As ILinqTree(OfDependencyObject) = NewVisualTreeAdapter(item)
  83.         Dim list As New List(OfDependencyObject)
  84.  
  85.         Dim parent = adapter.Parent
  86.         While parent IsNot Nothing
  87.             list.Add(parent)
  88.             adapter = New VisualTreeAdapter(parent)
  89.             parent = adapter.Parent
  90.         EndWhile
  91.         Return list
  92.     EndFunction
  93.  
  94.     ”’ <summary>
  95.     ”’ Returns a collection containing this element and all ancestor elements.
  96.     ”’ </summary>
  97.     <Extension()>
  98.     PublicFunction AncestorsAndSelf(item AsDependencyObject) AsIEnumerable(OfDependencyObject)
  99.         Dim list As New List(OfDependencyObject)
  100.         list.Add(item)
  101.  
  102.         ForEach ancestor In item.Ancestors()
  103.             list.Add(ancestor)
  104.         Next
  105.         Return list
  106.     EndFunction
  107.  
  108.     ”’ <summary>
  109.     ”’ Returns a collection of child elements.
  110.     ”’ </summary>
  111.     <Extension()>
  112.     PublicFunction Elements(item AsDependencyObject) AsIEnumerable(OfDependencyObject)
  113.         Dim list As New List(OfDependencyObject)
  114.         Dim adapter As ILinqTree(OfDependencyObject) = NewVisualTreeAdapter(item)
  115.         ForEach child In adapter.Children()
  116.             list.Add(child)
  117.         Next
  118.         Return list
  119.     EndFunction
  120.  
  121.     ”’ <summary>
  122.     ”’ Returns a collection of the sibling elements before this node, in document order.    ”’ </summary>
  123.     <Extension()>
  124.     PublicFunction ElementsBeforeSelf(item AsDependencyObject) AsIEnumerable(OfDependencyObject)
  125.         Dim list As New List(OfDependencyObject)
  126.         If item.Ancestors().FirstOrDefault() Is NothingThen
  127.             ‘yield Exit Function
  128.             ‘Exit Function
  129.             Return list
  130.         EndIf
  131.         ForEach child In item.Ancestors().First().Elements()
  132.             If child.Equals(item) Then
  133.                 Exit For
  134.             EndIf
  135.             list.Add(child)
  136.         Next
  137.         Return list
  138.     EndFunction
  139.  
  140.     ”’ <summary>
  141.     ”’ Returns a collection of the after elements after this node, in document order.
  142.     ”’ </summary>
  143.     <Extension()>
  144.     PublicFunction ElementsAfterSelf(item AsDependencyObject) AsIEnumerable(OfDependencyObject)
  145.         Dim list As New List(OfDependencyObject)
  146.         If item.Ancestors().FirstOrDefault() Is NothingThen
  147.             ‘yield Exit Function
  148.             Return list
  149.             ‘Exit Function
  150.         EndIf
  151.         DimafterSelf As Boolean = False
  152.         ForEach child In item.Ancestors().First().Elements()
  153.             IfafterSelf Then
  154.                 ‘yield Return child
  155.                 list.Add(child)
  156.             EndIf
  157.  
  158.             If child.Equals(item) Then
  159.                 afterSelf = True
  160.             EndIf
  161.         Next
  162.         Return list
  163.     EndFunction
  164.  
  165.     ”’ <summary>
  166.     ”’ Returns a collection containing this element and all child elements.
  167.     ”’ </summary>
  168.     <Extension()>
  169.     PublicFunction ElementsAndSelf(item AsDependencyObject) AsIEnumerable(OfDependencyObject)
  170.         Dim list As New List(OfDependencyObject)
  171.         ‘yield Return item
  172.         list.Add(item)
  173.  
  174.         ForEach child In item.Elements()
  175.             ‘yield Return child
  176.             list.Add(child)
  177.         Next
  178.         Return list
  179.     EndFunction
  180.  
  181.     ”’ <summary>
  182.     ”’ Returns a collection of descendant elements which match the given type.
  183.     ”’ </summary>
  184.     <Extension()>
  185.     PublicFunction Descendants(Of T)(item AsDependencyObject) AsIEnumerable(OfDependencyObject)
  186.         Return item.Descendants().Where(Function(i) TypeOf i Is T).Cast(OfDependencyObject)()
  187.     EndFunction
  188.  
  189.  
  190.  
  191.     ”’ <summary>
  192.     ”’ Returns a collection of the sibling elements before this node, in document order
  193.     ”’ which match the given type.
  194.     ”’ </summary>
  195.     <Extension()>
  196.     PublicFunction ElementsBeforeSelf(Of T)(item AsDependencyObject) AsIEnumerable(OfDependencyObject)
  197.         Return item.ElementsBeforeSelf().Where(Function(i) TypeOf i Is T).Cast(OfDependencyObject)()
  198.     EndFunction
  199.  
  200.     ”’ <summary>
  201.     ”’ Returns a collection of the after elements after this node, in document order
  202.     ”’ which match the given type.
  203.     ”’ </summary>
  204.     <Extension()>
  205.     PublicFunction ElementsAfterSelf(Of T)(item AsDependencyObject) AsIEnumerable(OfDependencyObject)
  206.         Return item.ElementsAfterSelf().Where(Function(i) TypeOf i Is T).Cast(OfDependencyObject)()
  207.     EndFunction
  208.  
  209.     ”’ <summary>
  210.     ”’ Returns a collection containing this element and all descendant elements
  211.     ”’ which match the given type.
  212.     ”’ </summary>
  213.     <Extension()>
  214.     PublicFunction DescendantsAndSelf(Of T)(item AsDependencyObject) AsIEnumerable(OfDependencyObject)
  215.         Return item.DescendantsAndSelf().Where(Function(i) TypeOf i Is T).Cast(OfDependencyObject)()
  216.     EndFunction
  217.  
  218.     ”’ <summary>
  219.     ”’ Returns a collection of ancestor elements which match the given type.
  220.     ”’ </summary>
  221.     <Extension()>
  222.     PublicFunction Ancestors(Of T)(item AsDependencyObject) AsIEnumerable(OfDependencyObject)
  223.         Return item.Ancestors().Where(Function(i) TypeOf i Is T).Cast(OfDependencyObject)()
  224.     EndFunction
  225.  
  226.     ”’ <summary>
  227.     ”’ Returns a collection containing this element and all ancestor elements
  228.     ”’ which match the given type.
  229.     ”’ </summary>
  230.     <Extension()>
  231.     PublicFunction AncestorsAndSelf(Of T)(item AsDependencyObject) AsIEnumerable(OfDependencyObject)
  232.         Return item.AncestorsAndSelf().Where(Function(i) TypeOf i Is T).Cast(OfDependencyObject)()
  233.     EndFunction
  234.  
  235.     ”’ <summary>
  236.     ”’ Returns a collection of child elements which match the given type.
  237.     ”’ </summary>
  238.     ”’
  239.     <Extension()>
  240.     PublicFunction Elements(Of T)(item AsDependencyObject) AsIEnumerable(OfDependencyObject)
  241.         Return item.Elements().Where(Function(i) TypeOf i Is T).Cast(OfDependencyObject)()
  242.     EndFunction
  243.  
  244.     ”’ <summary>
  245.     ”’ Returns a collection containing this element and all child elements.
  246.     ”’ which match the given type.
  247.     ”’ </summary>
  248.     <Extension()>
  249.     PublicFunction ElementsAndSelf(Of T)(item AsDependencyObject) AsIEnumerable(OfDependencyObject)
  250.         Return item.ElementsAndSelf().Where(Function(i) TypeOf i Is T).Cast(OfDependencyObject)()
  251.     EndFunction
  252.  
  253.  
  254.     ”’ <summary>
  255.     ”’ Applies the given function to each of the items in the supplied
  256.     ”’ IEnumerable.
  257.     ”’ </summary>
  258.     <Extension()>
  259.     PrivateFunction DrillDown(items AsIEnumerable(Of DependencyObject), [function] As Func(OfDependencyObject, IEnumerable(OfDependencyObject))) AsIEnumerable(OfDependencyObject)
  260.         Dim list As New List(OfDependencyObject)
  261.         ForEach item In items
  262.             ForEach itemChild In [function](item)
  263.                 ‘yield Return itemChild
  264.                 list.Add(itemChild)
  265.             Next
  266.         Next
  267.         Return list
  268.     EndFunction
  269.  
  270.  
  271.     ”’ <summary>
  272.     ”’ Applies the given function to each of the items in the supplied
  273.     ”’ IEnumerable, which match the given type.
  274.     ”’ </summary>
  275.     <Extension()>
  276.     PublicFunction DrillDown(Of T AsDependencyObject)(items AsIEnumerable(Of DependencyObject), [function] As Func(OfDependencyObject, IEnumerable(OfDependencyObject))) AsIEnumerable(OfDependencyObject)
  277.         Dim list As New List(OfDependencyObject)
  278.         ForEach item In items
  279.             ForEach itemChild In [function](item)
  280.                 IfTypeOf itemChild Is T Then
  281.                     ‘yield Return DirectCast(itemChild, T)
  282.                     list.Add(DirectCast(itemChild, T))
  283.                 EndIf
  284.             Next
  285.         Next
  286.         Return list
  287.     EndFunction
  288.  
  289.  
  290.     ”’ <summary>
  291.     ”’ Returns a collection of descendant elements.
  292.     ”’ </summary>
  293.     <Extension()>
  294.     PublicFunction Descendants(items AsIEnumerable(Of DependencyObject)) As IEnumerable(OfDependencyObject)
  295.  
  296.         Return items.DrillDown(Function(i) i.Descendants())
  297.     EndFunction
  298.  
  299.     ”’ <summary>
  300.     ”’ Returns a collection containing this element and all descendant elements.
  301.     ”’ </summary>
  302.     <Extension()>
  303.     PublicFunction DescendantsAndSelf(items AsIEnumerable(Of DependencyObject)) As IEnumerable(OfDependencyObject)
  304.         Return items.DrillDown(Function(i) i.DescendantsAndSelf())
  305.     EndFunction
  306.  
  307.     ”’ <summary>
  308.     ”’ Returns a collection of ancestor elements.
  309.     ”’ </summary>
  310.     <Extension()>
  311.     PublicFunction Ancestors(items AsIEnumerable(Of DependencyObject)) As IEnumerable(OfDependencyObject)
  312.         Return items.DrillDown(Function(i) i.Ancestors())
  313.     EndFunction
  314.  
  315.     ”’ <summary>
  316.     ”’ Returns a collection containing this element and all ancestor elements.
  317.     ”’ </summary>
  318.     <Extension()>
  319.     PublicFunction AncestorsAndSelf(items AsIEnumerable(Of DependencyObject)) As IEnumerable(OfDependencyObject)
  320.         Return items.DrillDown(Function(i) i.AncestorsAndSelf())
  321.     EndFunction
  322.  
  323.     ”’ <summary>
  324.     ”’ Returns a collection of child elements.
  325.     ”’ </summary>
  326.     <Extension()>
  327.     PublicFunction Elements(items AsIEnumerable(Of DependencyObject)) As IEnumerable(OfDependencyObject)
  328.         Return items.DrillDown(Function(i) i.Elements())
  329.     EndFunction
  330.  
  331.     ”’ <summary>
  332.     ”’ Returns a collection containing this element and all child elements.
  333.     ”’ </summary>
  334.     <Extension()>
  335.     PublicFunction ElementsAndSelf(items AsIEnumerable(Of DependencyObject)) As IEnumerable(OfDependencyObject)
  336.         Return items.DrillDown(Function(i) i.ElementsAndSelf())
  337.     EndFunction
  338.  
  339.  
  340.     ”’ <summary>
  341.     ”’ Returns a collection of descendant elements which match the given type.
  342.     ”’ </summary>
  343.     <Extension()>
  344.     PublicFunction Descendants(Of T AsDependencyObject)(items AsIEnumerable(Of DependencyObject)) As IEnumerable(OfDependencyObject)
  345.         Return items.DrillDown(Of T)(Function(i) i.Descendants())
  346.     EndFunction
  347.  
  348.     ”’ <summary>
  349.     ”’ Returns a collection containing this element and all descendant elements.
  350.     ”’ which match the given type.
  351.     ”’ </summary>
  352.     <Extension()>
  353.     PublicFunction DescendantsAndSelf(Of T AsDependencyObject)(items AsIEnumerable(Of DependencyObject)) As IEnumerable(OfDependencyObject)
  354.         Return items.DrillDown(Of T)(Function(i) i.DescendantsAndSelf())
  355.     EndFunction
  356.  
  357.     ”’ <summary>
  358.     ”’ Returns a collection of ancestor elements which match the given type.
  359.     ”’ </summary>
  360.     <Extension()>
  361.     PublicFunction Ancestors(Of T AsDependencyObject)(items AsIEnumerable(Of DependencyObject)) As IEnumerable(OfDependencyObject)
  362.         Return items.DrillDown(Of T)(Function(i) i.Ancestors())
  363.     EndFunction
  364.  
  365.     ”’ <summary>
  366.     ”’ Returns a collection containing this element and all ancestor elements.
  367.     ”’ which match the given type.
  368.     ”’ </summary>
  369.     <Extension()>
  370.     PublicFunction AncestorsAndSelf(Of T AsDependencyObject)(items AsIEnumerable(Of DependencyObject)) As IEnumerable(OfDependencyObject)
  371.         Return items.DrillDown(Of T)(Function(i) i.AncestorsAndSelf())
  372.     EndFunction
  373.  
  374.     ”’ <summary>
  375.     ”’ Returns a collection of child elements which match the given type.
  376.     ”’ </summary>
  377.     <Extension()>
  378.     PublicFunction Elements(Of T AsDependencyObject)(items AsIEnumerable(Of DependencyObject)) As IEnumerable(OfDependencyObject)
  379.         Return items.DrillDown(Of T)(Function(i) i.Elements())
  380.     EndFunction
  381.  
  382.     ”’ <summary>
  383.     ”’ Returns a collection containing this element and all child elements.
  384.     ”’ which match the given type.
  385.     ”’ </summary>
  386.     <Extension()>
  387.     PublicFunction ElementsAndSelf(Of T AsDependencyObject)(items AsIEnumerable(Of DependencyObject)) As IEnumerable(OfDependencyObject)
  388.         Return items.DrillDown(Of T)(Function(i) i.ElementsAndSelf())
  389.     EndFunction
  390.  
  391.  
  392.     ‘End Namespace
  393. End Module

Now, in your codebehind for XAML pages that use the WebBrowser control where you wish to suppress pinch or scroll, add the following declaration:

  1. Dim WithEvents MBH As WebBrowserHelper

 

Finally, in Public Sub New () of your codebehind of these XAML pages, associate this declared WebBrowserHelper with an actual WebBrowser (in this case named “MyWebBrowser”):

  1. MBH = New WebBrowserHelper(MyWebBrowser)

 

That’s it!

Adapted from C# to VB, and for completeness and accuracy, from:

  1. Suppressing Zoom and Scroll interactions in the Windows Phone 7 WebBrowser Control

    http://www.scottlogic.co.uk/blog/colin/2011/11/suppressing-zoom-and-scroll-interactions-in-the-windows-phone-7-browser-control/

Daily Gem: VB / Silverlight / WP7.5 – Infinite scrolling lists

How to raise an end-of-list reached event so you can add more items.

Step 1:  Subclass the standard Listbox with the following code

Code Snippet

  1. Imports System.Windows.Controls.Primitives
  2.  
  3. Public ClassExtendedListBox
  4.     InheritsListBox
  5.  
  6.     Protected _isBouncy As Boolean = False
  7.     PrivatealreadyHookedScrollEvents As Boolean = False
  8.  
  9.     PublicSub New()
  10.         AddHandlerMe.Loaded, NewRoutedEventHandler(AddressOfListBox_Loaded)
  11.     EndSub
  12.  
  13.     PrivateSub ListBox_Loaded(sender As Object, e As RoutedEventArgs)
  14.         Dimsb As ScrollBar = Nothing
  15.         Dimsv As ScrollViewer = Nothing
  16.         IfalreadyHookedScrollEvents Then
  17.             Return
  18.         EndIf
  19.  
  20.         alreadyHookedScrollEvents = True
  21.         Me.[AddHandler](ExtendedListBox.ManipulationCompletedEvent, DirectCast(AddressOf LB_ManipulationCompleted, EventHandler(OfManipulationCompletedEventArgs)), True)
  22.         sb = DirectCast(FindElementRecursive(Me, GetType(ScrollBar)), ScrollBar)
  23.         sv = DirectCast(FindElementRecursive(Me, GetType(ScrollViewer)), ScrollViewer)
  24.  
  25.         Ifsv IsNot Nothing Then
  26.             ‘ Visual States are always on the first child of the control template
  27.             Dim element As FrameworkElement = TryCast(VisualTreeHelper.GetChild(sv, 0), FrameworkElement)
  28.             If element IsNot Nothing Then
  29.                 Dimvgroup As VisualStateGroup = FindVisualState(element, "VerticalCompression")
  30.                 Dimhgroup As VisualStateGroup = FindVisualState(element, "HorizontalCompression")
  31.                 Ifvgroup IsNot Nothing Then
  32.                     AddHandlervgroup.CurrentStateChanging, NewEventHandler(OfVisualStateChangedEventArgs)(AddressOfvgroup_CurrentStateChanging)
  33.                 EndIf
  34.                 Ifhgroup IsNot Nothing Then
  35.                     AddHandlerhgroup.CurrentStateChanging, NewEventHandler(OfVisualStateChangedEventArgs)(AddressOfhgroup_CurrentStateChanging)
  36.                 EndIf
  37.             EndIf
  38.         EndIf
  39.  
  40.     EndSub
  41.  
  42.     PublicDelegate Sub OnCompression(sender As Object, e AsCompressionEventArgs)
  43.     PublicEvent Compression As OnCompression
  44.  
  45.     PrivateSub hgroup_CurrentStateChanging(sender AsObject, e AsVisualStateChangedEventArgs)
  46.         If e.NewState.Name = "CompressionLeft" Then
  47.             _isBouncy = True
  48.             RaiseEvent Compression(Me, NewCompressionEventArgs(CompressionType.Left))
  49.         EndIf
  50.  
  51.         If e.NewState.Name = "CompressionRight" Then
  52.             _isBouncy = True
  53.             RaiseEvent Compression(Me, NewCompressionEventArgs(CompressionType.Right))
  54.         EndIf
  55.         If e.NewState.Name = "NoHorizontalCompression" Then
  56.             _isBouncy = False
  57.         EndIf
  58.     EndSub
  59.  
  60.     PrivateSub vgroup_CurrentStateChanging(sender AsObject, e AsVisualStateChangedEventArgs)
  61.         If e.NewState.Name = "CompressionTop" Then
  62.             _isBouncy = True
  63.             RaiseEvent Compression(Me, NewCompressionEventArgs(CompressionType.Top))
  64.         EndIf
  65.         If e.NewState.Name = "CompressionBottom" Then
  66.             _isBouncy = True
  67.             RaiseEvent Compression(Me, NewCompressionEventArgs(CompressionType.Bottom))
  68.         EndIf
  69.         If e.NewState.Name = "NoVerticalCompression" Then
  70.             _isBouncy = False
  71.         EndIf
  72.     EndSub
  73.  
  74.     PrivateSub LB_ManipulationCompleted(sender AsObject, e AsManipulationCompletedEventArgs)
  75.         If _isBouncy Then
  76.             _isBouncy = False
  77.         EndIf
  78.     EndSub
  79.  
  80.     PrivateFunction FindElementRecursive(parent AsFrameworkElement, targetType As Type) As UIElement
  81.         DimchildCount As Integer = VisualTreeHelper.GetChildrenCount(parent)
  82.         DimreturnElement As UIElement = Nothing
  83.         IfchildCount > 0 Then
  84.             For i As Integer = 0 To childCount – 1
  85.                 Dim element As [Object] = VisualTreeHelper.GetChild(parent, i)
  86.                 ‘If element.[GetType]() = targetType Then
  87.                 ‘If element.GetType.FullName = targetType.FullName Then
  88.                 If element.GetType.Equals(targetType) Then
  89.  
  90.                     ReturnTryCast(element, UIElement)
  91.                 Else
  92.                     returnElement = FindElementRecursive(TryCast(VisualTreeHelper.GetChild(parent, i), FrameworkElement), targetType)
  93.                 EndIf
  94.             Next
  95.         EndIf
  96.         ReturnreturnElement
  97.     EndFunction
  98.  
  99.     PrivateFunction FindVisualState(element AsFrameworkElement, name As String) As VisualStateGroup
  100.         If element Is Nothing Then
  101.             ReturnNothing
  102.         EndIf
  103.  
  104.         Dim groups As IList(OfVisualStateGroup) = VisualStateManager.GetVisualStateGroups(element)
  105.         ForEach group As VisualStateGroupIn groups
  106.             If group.Name = name Then
  107.                 Return group
  108.             EndIf
  109.         Next
  110.  
  111.         ReturnNothing
  112.     EndFunction
  113. End Class
  114.  
  115. Public ClassCompressionEventArgs
  116.     InheritsEventArgs
  117.     PublicProperty Type() As CompressionType
  118.         Get
  119.             Return m_Type
  120.         EndGet
  121.         ProtectedSet(value AsCompressionType)
  122.             m_Type = value
  123.         EndSet
  124.     EndProperty
  125.     Private m_Type As CompressionType
  126.  
  127.     PublicSub New(type__1 AsCompressionType)
  128.         Type = type__1
  129.     EndSub
  130. End Class
  131.  
  132. Public EnumCompressionType
  133.     Top
  134.     Bottom
  135.     Left
  136.     Right
  137. End Enum

 

Step 2:  Add the following XAML to the Application.Resources section of App.xaml

XAML Snippet

  1. <StyleTargetType="ScrollViewer">
  2.     <Setter Property="VerticalScrollBarVisibility" Value="Auto"/>
  3.     <Setter Property="HorizontalScrollBarVisibility" Value="Auto"/>
  4.     <Setter Property="Background" Value="Transparent"/>
  5.     <Setter Property="Padding" Value="0"/>
  6.     <Setter Property="BorderThickness" Value="0"/>
  7.     <Setter Property="BorderBrush" Value="Transparent"/>
  8.     <Setter Property="Template">
  9.         <Setter.Value>
  10.             <ControlTemplateTargetType="ScrollViewer">
  11.                 <BorderBorderBrush="{TemplateBindingBorderBrush}"BorderThickness="{TemplateBindingBorderThickness}" Background="{TemplateBinding Background}">
  12.                     <VisualStateManager.VisualStateGroups>
  13.                         <VisualStateGroup x:Name="ScrollStates">
  14.                             <VisualStateGroup.Transitions>
  15.                                 <VisualTransitionGeneratedDuration="00:00:00.5"/>
  16.                             </VisualStateGroup.Transitions>
  17.                             <VisualState x:Name="Scrolling">
  18.                                 <Storyboard>
  19.                                     <DoubleAnimation Storyboard.TargetName="VerticalScrollBar" Storyboard.TargetProperty="Opacity" To="1" Duration="0"/>
  20.                                     <DoubleAnimation Storyboard.TargetName="HorizontalScrollBar" Storyboard.TargetProperty="Opacity" To="1" Duration="0"/>
  21.                                 </Storyboard>
  22.                             </VisualState>
  23.                             <VisualState x:Name="NotScrolling"/>
  24.                         </VisualStateGroup>
  25.                         <VisualStateGroup x:Name="VerticalCompression">
  26.                             <VisualState x:Name="NoVerticalCompression"/>
  27.                             <VisualState x:Name="CompressionTop"/>
  28.                             <VisualState x:Name="CompressionBottom"/>
  29.                         </VisualStateGroup>
  30.                         <VisualStateGroup x:Name="HorizontalCompression">
  31.                             <VisualState x:Name="NoHorizontalCompression"/>
  32.                             <VisualState x:Name="CompressionLeft"/>
  33.                             <VisualState x:Name="CompressionRight"/>
  34.                         </VisualStateGroup>
  35.                     </VisualStateManager.VisualStateGroups>
  36.  
  37.  
  38.                     <Grid Margin="{TemplateBinding Padding}">
  39.                         <ScrollContentPresenter x:Name="ScrollContentPresenter" Content="{TemplateBinding Content}"ContentTemplate="{TemplateBindingContentTemplate}"/>
  40.                         <ScrollBar x:Name="VerticalScrollBar"IsHitTestVisible="False" Height="Auto" Width="5"HorizontalAlignment="Right"VerticalAlignment="Stretch" Visibility="{TemplateBindingComputedVerticalScrollBarVisibility}"IsTabStop="False" Maximum="{TemplateBindingScrollableHeight}" Minimum="0" Value="{TemplateBindingVerticalOffset}" Orientation="Vertical"ViewportSize="{TemplateBindingViewportHeight}" />
  41.                         <ScrollBar x:Name="HorizontalScrollBar"IsHitTestVisible="False" Width="Auto" Height="5"HorizontalAlignment="Stretch"VerticalAlignment="Bottom" Visibility="{TemplateBindingComputedHorizontalScrollBarVisibility}"IsTabStop="False" Maximum="{TemplateBindingScrollableWidth}" Minimum="0" Value="{TemplateBindingHorizontalOffset}" Orientation="Horizontal"ViewportSize="{TemplateBindingViewportWidth}" />
  42.                     </Grid>
  43.                 </Border>
  44.             </ControlTemplate>
  45.         </Setter.Value>
  46.     </Setter>
  47. </Style>

You can now simply replace your ListBox references with ExtendedListBox references in your code wherever a listbox is used.

  1. <local:ExtendedListBox x:Name="lbMyList"VerticalAlignment="Top"ItemsSource="{Binding}">

 

You might handle list-end / top scroll events in your code-behind as follows:

Code Snippet

  1. Private SublbMyList_Compression(sender As Object, e As CompressionEventArgs) HandleslbMyList.Compression
  2.     DimCompressionArgs = CType(e, CompressionEventArgs)
  3.     SelectCase CompressionArgs.Type
  4.         CaseCompressionType.Bottom ‘Bottom reached… add more list items
  5.             …
  6.         CaseCompressionType.Top ‘At top  fetch and add earlier list items
  7.             …
  8.     EndSelect
  9. End Sub

Cheers.  Smile


Adapted from C# to VB, and for completeness and accuracy, from: 

  1. Windows Phone Mango change, Listbox: How to detect compression(end of scroll) states ?http://blogs.msdn.com/b/slmperf/archive/2011/06/30/windows-phone-mango-change-listbox-how-to-detect-compression-end-of-scroll-states.aspx
  2. ExtendedListBox: custom WP7 Listbox control which detects end of scroll, allows infinite scrolling
    http://nuncaalaprimera.com/2012/01/extendedlistbox-custom-wp7-listbox-control-which-detects-end-of-scroll-allows-infinite-scrolling/

Daily Gem: Quickly and temporarily bypass Vista / Win 7 file redirection in your VB6 Apps

How to quickly get around redirection in your VB6 app:

a) You wish to check for or launch program in “c:\Windows\System” folder (Without redirection to “c:\Windows\SysWow64″)

Use the “\SysNative” path!

Public Const CSIDL_WINDOWS = &H24
GetSpecialFolder(CSIDL_WINDOWS) & "\SysNative\"
Note, the GetSpecialFolder function appears in many other plaes, like this.

For example:

z = shell(GetSpecialFolder(CSIDL_WINDOWS) & "\SysNative\<64-bit appname>.exe")

b) Check for program in “c:\Program Files” without redirection to “c:\Program Files (x86)”

Abuse the “\SysNative” path!

GetSpecialFolder(CSIDL_WINDOWS) & "\SysNative\..\..\Program Files\"

For example:

z = shell(GetSpecialFolder(CSIDL_WINDOWS) & "\SysNative\..\..\Program Files\<64-bit appname>.exe")

This leads to the question, how to get “Program Files” directory name?

Answer:

ProgramFilesFolder$ = Environ("ProgramW6432")
ProgramFilesFolder$ = Mid(ProgramFilesFolder$, InStr(ProgramFilesFolder$, "\") + 1)
z = shell(GetSpecialFolder(&H24) & "\SysNative\..\.." & ProgramFilesFolder$ & "\<64-bit appname>.exe")