WPFSpark v1.2
At last, it's here! After a really long gap of nearly 4 years, I am happy to announce that the next version of WPFSpark is finally released. :)
What's new in WPFSpark v1.2
In this section I will be providing a summary of new features and modifications made to the WPFSpark controls so that you can adapt your code quickly and integrate new features with ease. For WPFSpark v1.1, I had written several articles, explaining in detail, how each of the controls was designed and implemented. You can see those articles here (WPFSpark: M of N series). I intend to update these articles as soon as possible. For the time being, this article should bring you up to speed. All the code has been ported to .NET framework 4.6.1 using C# 6.0.
SprocketControl
None of the existing dependencies have been changed. However, in order to give the user more freedom, two new dependency properties have been added - InnerRadius
and OuterRadius
. They govern the length of the spoke. They are represented as a ratio of the radius of the inner circle and outer circle (between which the spokes lie) with the width of the SprocketControl, respectively.
Dependency Property | Type | Description | Default Value |
InnerRadius | Double | Gets or sets the ratio of the Inner Radius to the Width of the SprocketControl. | 0.175 |
OuterRadius | Double | Gets or sets the ratio of the Outer Width to the width of the SprocketControl. | 0.3125 |
ToggleSwitch
When WPFSpark v1.1 was released, users reported of a memory leak (it can be found here) in the FluidMoveBehavior
. ToggleSwitch
uses FluidMoveBehavior
in order to animate its content when its IsChecked state changes. I looked into various possible solutions to solve this issue but none of them proved satisfactory. Then I decided to remove ToggleSwitch's
dependency on FluidMoveBehavior
completely. The content of ToggleSwitch
is hosted inside a Grid
and FluidMoveBehavior
is used to animate the movement of the content from one column of the Grid
to another. So instead of hosting the content inside a Grid
, they are now hosted in a Canvas
and instead of using the FluidMoveBehavior
, DoubleAnimation
is used to animate the Margin
of the content.
While implementing this change, it made me look deeper into the ToggleSwitch
code and also the issues and suggestions reported by users in the CodePlex site. It thus triggered several other changes (and ultimately a huge rewrite) in order to make ToggleSwitch
easier to use while eliminating potential issues (both visual and in code). Here are the changes:
By default, the IsThreeState
property is set to False
as ToggleSwitch supports only two states for the IsChecked
property - True
and False
. Setting the IsChecked
property will not have any visual effect on ToggleSwitch
.
The following Dependency Properties have been removed
TargetColumnInternal
ThumbGlowColor
- replaced by ThumbGlowBrush
ThumbShineCornerRadius
ThumbWidth
- replaced by ThumbWidthRatio
. ThumbWidth
is now a read-only property which represents the actual width of the Thumb.
The following read-only Dependency Properties have been added
Dependency Property | Type | Description |
CheckedMargin | Thickness | Gets the calculated Margin of the PART_ContentGrid when the ToggleSwitch is in Checked state. |
UncheckedMargin | Thickness | Gets the calculated Margin of the PART_ContentGrid when the ToggleSwitch is in Unchecked state. |
ThumbWidth | double | Gets the calculated width of the Thumb. |
ThumbHeight | double | Gets the calculated height of the Thumb. |
ThumbCornerRadius | CornerRadius | Gets the calculated CornerRadius of the Thumb. |
The following new Dependency Properties have been added
Dependency Property | Type | Description | Default Value |
CheckedTextEffect | Effect | Gets or sets the effect to be applied on the Checked Text. | null |
UncheckedTextEffect | Effect | Gets or sets the effect to be applied on the Unchecked Text. | null |
ThumbGlowBrush | Brush | Gets or sets the Brush for the Glow in the Thumb which is shown when the mouse hovers over the ToggleSwitch. | Transparent |
ThumbShineBrush | Brush | Gets or sets the Brush for the shine on the Thumb. | Transparent |
ThumbWidthRatio | Double | Gets or sets the ratio of the Width of the Thumb to the Width of the ToggleSwitch. Value Range: 0.1 - 0.9, inclusive. | 0.4 |
OptimizeRendering | Boolean | Gets or sets the property which indicates whether the ClipBorder surrounding the ToggleSwitch should enable OptimizeClipRendering to prevent gaps between the border and the clipped content. Set this value to False, if the ToggleSwitch Background is Transparent or has partial transparency. Otherwise, if the Background is opaque, set this value to True for better rendering.. | False |
OptimizeThumbRendering | Boolean | Gets or sets the property which indicates whether the ClipBorder surrounding the ToggleSwitch Thumb should enable OptimizeClipRendering to prevent gaps between the border and the clipped content. Set this value to False, if the ToggleSwitch ThumbBackground is Transparent or has partial transparency. Otherwise, if the ThumbBackground is opaque, set this value to True for better rendering.. | False |
AutoThumbWidthRatio | Boolean | Gets or sets the property which indicates whether the ThumbWidthRatio should be automatically calculated based on the Width, Height and BorderThickness of the ToggleSwitch. This property has higher precedence over the ThumbWidthRatio property. If this property is set to true, any value for ThumbWidthRatio, set by the user, will be ignored and ThumbWidth will be equal to ThumbHeight. | True |
Golden Rules for ToggleSwitch
Although, ToggleSwitch
gives you the freedom to set the values of its Dependency Properties from a vast range of values, in order to have the ToggleSwitch
render effectively, just follow these golden rules:
- Provide uniform values for
BorderThickness
and ThumbBorderThickness
BorderThickness
and ThumbBorderThickness
should be proportionate i.e. if BorderThickness
is {a,b,a,b}
and ThumbBorderThickness
is {c,d,c,d}
then (a/b) should be equal to (c/d). - Provide uniform values for
CornerRadius
. If you are providing non-uniform values, try to ensure that the radii are horizontally (e.g. {a,a,b,b} ) or vertically (e.g. {a,b,b,a}) symmetrical. - Ensure that the
CornerRadius
is less than or equal to half of the ToggleSwitch's
height. - If you have
Background
and ThumbBackground
as non-transparent colors, then set the OptimizeRendering
and OptimizeThumbRendering
properties to true
. - Set the
AutoThumbWidthRatio
to true
and let the ToggleSwitch calculate the best ThumbWidth.
In the source code, in the file ToggleSwitch.Generic.xaml
, along with the ControlTemplate for ToggleSwitch
I have also added several styles which use the template. These style mimic the user experience of Toggle buttons found in Windows 10 and iOS. You must add the ToggleSwitch.Generic.xaml
in your App.xaml
to gain access to these styles. The list of styles are:
ToggleSwitch.UWP.Light.Style
- Represents the Windows 10 ToggleButton for light backgrounds.
ToggleSwitch.UWP.Dark.Style
- Represents the Windows 10 ToggleButton for dark backgrounds.
ToggleSwitch.iOS.Light.XXXX.Style
- Represents the iOS ToggleButton for light backgrounds where XXXX refers to the accent color.
You can derive from these styles to create your own styles with the accent color of your choice. You can refer to these styles in your XAML in the following way:
<wpfspark:ToggleSwitch Grid.Row="1"
Grid.Column="1"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Style="{StaticResource {ComponentResourceKey TypeInTargetAssembly=wpfspark:ToggleSwitch, ResourceId=ToggleSwitch.UWP.Dark.Style}}" />
ClipBorder
ClipBorder
class deserves an honorable mention here. ToggleSwitch
would not exist if it were not for the ClipBorder
class. In WPFSpark v1.1, ClipBorder
class derived from Border
class and set the Clip
property to clip its child within its bounds. However, that did not prove too effective. In certain scenarios, the ClipBorder
did not render correctly. For example, when the ClipBorder
had a thick border and both the BorderBrush
and Background
were the same color, you could see a small gap between the border and the background, especially at the round corners. Initially I thought it was due to the Clip Geometry that was being calculated for the ClipBorder's
child based on its borders. I tried different solutions (like adding a small tolerance value while calculating the Clip Geometry) but it did not eliminate the issue effectively.
Then I found out that the problem was not with ClipBorder
. The Border
class also displayed the same behavior.
This made me dig deep into the Microsoft Reference Source for the Border
class and come up with an optimized solution of my own. ClipBorder
no longer derives from Border
class. It now derives from the Decorator
class and clips its child more effectively than previously.
FluidWrapPanel
In WPFSpark v1.1, FluidWrapPanel
imposed a restriction that all its Children must have the same size (defined by ItemWidth
and ItemHeight
). One of the top feature requests made by users was to remove this restriction and allow adding Children having different dimensions. Initially, I thought it was difficult to achieve and it would require some crazy code modifications. Then I came up on the idea of using BitMatrix to track the positions of the Children and calculate the placement of a child while it was being dragged. This led to the implementation of the FluidBitMatrix
class which replaced the FluidLayoutManager
class.
However, there is one restriction - the Children must have dimensions which are multiples of ItemWidth
and ItemHeight
. I have also added a read-only Dependency Property FluidItems
which is an ObservableCollection
of the Children. By accessing this property you can obtain the current order of the Children in the FluidWrapPanel
and also be notified of changes when a child is dragged to a new location. Another Dependency Property which I have added is the OptimizeChildPlacement
which governs the algorithm to calculate the best available position for placing a child in the FluidWrapPanel
.
Dependency Property | Type | Description | Default Value |
OptimizeChildPlacement | Boolean | Gets or sets the property that indicates whether the placement of the children is optimized. If set to true, the child is placed at the first available position from the beginning of the FluidWrapPanel. If set to false, each child occupies the same (or greater) row and/or column than the previous child. | true |
SparkWindow
SparkWindow
now has the same look and feel as a Desktop Window in Windows 10. The About button has been removed. I was able to add the blur behind option (blurred glass effect) to the Window based on the excellent tip from the blog article by Rafael Rivera - Adding the "Aero Glass" blur to your Windows 10 apps.
NVM#, an app which I recently released, uses SparkWindow
. So does the WPFSparkClient
which shows the examples of the controls in WPFSpark. Both of these apps show how a SplitViewMenu
can be used in a WPF application. (SplitView Control
does not exist in WPF!)
Important Note: Whenever you instantiate a SparkWindow programatically, ensure that you set the properties AllowTransparency=true
and WindowStyle=None
before calling the ShowDialog()
method. Otherwise it would throw an exception.
Three new Dependency Properties have also been added - TitleImage
, TitleImageMargin
, TitleMargin
.
Dependency Property | Type | Description | Default Value |
TitleImage | UIElement | Gets or sets the UIElement (usually an Image) to be displayed in the TitleBar of the Window. | null |
TitleImageMargin | Thickness | Gets or sets the Margin of the TitleImage. | 0 |
TitleMargin | Thickness | Gets or sets the Margin of the Title text in the Title Bar. | 0 |
Update
SparkWindow
now supports resizing. Make sure you set the ResizeMode
property to CanResize
. This is set in the default SparkWindow
template. This allows the SparkWindow
to be resized by dragging the edges or the corners.
FluidPivotPanel
PivotHeaderControl
In order to prevent a Pivot Header from being selected by the user, you can set the IsEnabled
property to False
. Also a new Dependency Property DisabledForeground
has been added to define the foreground of the PivotHeader when it is in disabled state.
Dependency Property | Type | Description | Default Value |
DisabledForeground | Brush | Gets or sets the Foreground of the PivotHeaderControl when it is in disabled state | Black |
PivotPanel
A new API SelectHeaderByName
has been added which allows you to select a PivotHeaderControl
via code. It takes the name of the PivotHeaderControl
as argument.
FluidProgressBar
No changes have been made. The control should work in the same way as it did in WPFSpark v1.1.
FluidStatusBar
I have added a Dependency Property SyncLatest
. When it is set to True
, only the latest message will be displayed. The older messages which have not been displayed yet will be discarded. When the property is set to False
, the messages will be enqueued and shown one after the other.
Dependency Property | Type | Description | Default Value |
SyncLatest | Boolean | Gets or sets the property which indicates whether the display of status message is synced with the latest message. If set to true, when messages arrive, they are not enqueued to be displayed. Instead the latest one is displayed and the older ones are discarded. | False |
Using WPFSpark v1.2 in your code
WPFSpark v1.2.0.1 is available in NuGet. You can obtain it here. Alternatively, you can add it to your project from Visual Studio using the Manage NuGet Packages
option (Just right click on your project in the Solution Explorer and click on Manage NuGet Packages).
If you are interested in getting your hands dirty with code, you can access the WPFSpark source code in GitHub. I have moved the code from CodePlex to GitHub as I feel it is easier to manage your code in GitHub. Also the code is available under MIT License.
History
- 26-February-2016: Added Resize feature to SparkWindow
- 08-December-2015:
WPFSpark
v1.2.0.2 released - 01-December-2015:
WPFSpark
v1.2.0.1 released