AutoScroller for UWP ScrollViewer

I recently published a couple of open source projects on NuGet and GitHub. One is UWP.AutoScroller. It auto-scrolls a UWP ScrollViewer when an element within it is dragged against its edge. It’s ported from a similar tool I wrote for Silverlight some time ago. 

I simplified its functionality. The Silverlight version also allowed you to programmatically scroll the ScrollViewer. This is not included in the new version – you just enable or disable the basic function.

I also simplified the code. In this version, handlers are added to events of the ScrollViewer itself instead of on elements within it. This is a simpler and more efficient approach.

Further information is in the project readme and the nuget documentation.

https://github.com/peterdongan/AutoScroller

https://www.nuget.org/packages/UWP.AutoScroller/

 

 

AutoScroller for Silverlight ScrollViewer

This is a small project I released as open source some time ago. It facilitates programmatic scrolling of a ScrollViewer in Silverlight.

ScrollViewer is a sealed class. Applying the functionality to it via a separate class seems like a neat approach.

Below is an example of its application. The functionality is applied by default in the example. Clicking the off button shows the default behaviour of the ScrollViewer. For convenience, this example is included in the source code download.

[silverlight: autoscrollviewer.xap]

The first three buttons on the right set the mode property of the AutoScroller. The ‘New Rectangle’ button adds a shape that may be dragged around the canvas, to demonstrate the autoscrolling functionality.
Automatic scrolling can be set directly also via the ScrollLeft, ScrollUp, SrollRight, ScrollDown properties. Lastly, there are properties to set the scrolling speed and the size of the canvas area that triggers the scrolling in Mode.Drag and Mode.Auto.

Download:

AutoScroller DLL
AutoScroller Source Code

A way to specify UI elements as properties declaratively in XAML

Here is an screenshot of an icon button type UserControl I developed in Silverlight:

This shows nine instances of the same UserControl, which is composed of a TextBlock and a panel containing an icon. The content of both of these are specified via properties. The challenge was to enable the panel to be specified declaratively in XAML. The problem was that you can’t use UI elements as static resources in Silverlight. For example, the following approach results in a runtime error:

<local:IconButton IconPanel="{StaticReource RectangleIcon}" Command="AddRectangle" Caption="Rectangle"/>

However, using a TypeConverter, I devised a way to allow the control to be specified like this:

<local:IconButton IconPanel="RectangleIcon" Command="AddRectangle" Caption="Rectangle"/>

A good general introduction to using Typeconverters with XAML is in Umair Saeed’s blog. The implementation of the TypeConverter class here is adapted from the generic example on that page.

//The TypeConverter class is in the System.ComponentModel namespace. The CultureInfo class is in System.Globalization.

public class IconConverter : TypeConverter
{
   public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
   {
      if (sourceType == typeof(string))
      {
         return true;
      }
      return base.CanConvertFrom(context, sourceType);
   }

   public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, Object value)
   {
      string strValue;
      if (value is string)
      {
         strValue = (string)value;
         if (strValue == "RectangleIcon")
            return Icons.Rectangle; 
         else
            return new Grid();
      }
      return base.ConvertFrom(context, culture, value);
   }

The Icons class just gives a convenient way of referring to the Icons. The code below can return a UserControl, or the root element from it. Note that in the latter case that you need to remove the root element from the created UserControl Instance, or an error will be generated: A UI element cannot be contained in multiple UI elements.

The RectangleIcon class it refers to is a UserControl just containing the Grid with the rectangle.

Lastly, here is how the implementation of the IconPanel property in the IconButton class:

private Panel _iconPanel;

[TypeConverter(typeof(IconConverter))]
public Panel IconPanel
{
   get
   {
      return _iconPanel;
   }
   set
   {
       _iconPanel = value;
       IconHolder.Content = _iconPanel;
    }
}

IconHolder is an empty UserControl which will hold the icon. Adding it directly as a child to the root element is also possible – however you need to make sure the names of the panels are different. Otherwise you may try to add a grid named LayoutRoot to another grid named LayoutRoot – which results in the error “Value does not fall within expected range” being thrown at runtime.

 

[Edited 21 July 2019 – restored image and code excerpts]

‘Hand’ Cursor and Website Icons

When you hover over a UI element and the cursor changes, this is an implementation of the Cursor Invitation design pattern. It indicates to the user that the UI element may be interacted with. The convention is to use it only when the interaction may be non-obvious, so it’s not used with standard buttons.

I was wondering if the convention was to use it with buttons in the form of icons. I couldn’t find anything about it online, so I looked at some Websites using icon-buttons to see what the consensus was. In all examples I found, hand cursors were used for icon buttons. This is logical, since not every icon on every Webpage is interactive. This isn’t consistent with Windows, where the cursor doesn’t change over icons. (This is also logical – every icon in Windows is interactive by default, so the extra prompt is unnecessary.)

Icon button at bing.com
Icon button at bing.com

It’s very easy to implement this in Silverlight – in both XAML and code-behind. You can just set the cursor property to the hand cursor.Eg:

XAML:
<Grid x:Name="LayoutRoot" Cursor="Hand">

C#:
target.Cursor = Cursors.Hand;

Even better, setting IsEnabled to false stops the cursor change from occurring  – so there’s no need to change the cursor property manually when the button is disabled.