Browse Source

initial checkin of new ButtonSpinner control. Allows you to add button spinners to any element and then respond to the Spin event to manipulate that element. To add use the following syntax

<toolkit:ButtonSpinner Spin="ButtonSpinner_Spin" >
            <TextBox x:Name="_txtValue" />
</toolkit:ButtonSpinner>

     private void ButtonSpinner_Spin(object sender, Microsoft.Windows.Controls.Primitives.SpinEventArgs e)
{
            int value = String.IsNullOrEmpty(_txtValue.Text) ? 0 : Convert.ToInt32(_txtValue.Text);
            if (e.Direction == Microsoft.Windows.Controls.Primitives.SpinDirection.Increase)
                value++;
            else
                value--;
            _txtValue.Text = value.ToString();
}
pull/1645/head
brianlagunas_cp 15 years ago
parent
commit
308ad9dc85
  1. 192
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ButtonSpinner/ButtonSpinner.cs
  2. 21
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/SpinDirection.cs
  3. 28
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/SpinEventArgs.cs
  4. 77
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/Spinner.cs
  5. 26
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/ValidSpinDirections.cs
  6. 153
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Themes/Generic.xaml
  7. 5
      ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj

192
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/ButtonSpinner/ButtonSpinner.cs

@ -0,0 +1,192 @@
using System;
using System.Windows;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Controls.Primitives;
using Microsoft.Windows.Controls.Primitives;
namespace Microsoft.Windows.Controls
{
/// <summary>
/// Represents a spinner control that includes two Buttons.
/// </summary>
[ContentProperty("Content")]
public class ButtonSpinner : Spinner
{
#region Properties
#region Content
/// <summary>
/// Identifies the Content dependency property.
/// </summary>
public static readonly DependencyProperty ContentProperty = DependencyProperty.Register("Content", typeof(object), typeof(ButtonSpinner), new PropertyMetadata(null, OnContentPropertyChanged));
public object Content
{
get { return GetValue(ContentProperty) as object; }
set { SetValue(ContentProperty, value); }
}
/// <summary>
/// ContentProperty property changed handler.
/// </summary>
/// <param name="d">ButtonSpinner that changed its Content.</param>
/// <param name="e">Event arguments.</param>
private static void OnContentPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
ButtonSpinner source = d as ButtonSpinner;
source.OnContentChanged(e.OldValue, e.NewValue);
}
#endregion //Content
private ButtonBase _increaseButton;
/// <summary>
/// Gets or sets the IncreaseButton template part.
/// </summary>
private ButtonBase IncreaseButton
{
get { return _increaseButton; }
set
{
if (_increaseButton != null)
{
_increaseButton.Click -= OnButtonClick;
}
_increaseButton = value;
if (_increaseButton != null)
{
_increaseButton.Click += OnButtonClick;
}
}
}
private ButtonBase _decreaseButton;
/// <summary>
/// Gets or sets the DecreaseButton template part.
/// </summary>
private ButtonBase DecreaseButton
{
get { return _decreaseButton; }
set
{
if (_decreaseButton != null)
{
_decreaseButton.Click -= OnButtonClick;
}
_decreaseButton = value;
if (_decreaseButton != null)
{
_decreaseButton.Click += OnButtonClick;
}
}
}
#endregion //Properties
#region Constructors
static ButtonSpinner()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(ButtonSpinner), new FrameworkPropertyMetadata(typeof(ButtonSpinner)));
}
#endregion //Constructors
#region Base Class Overrides
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
IncreaseButton = GetTemplateChild("IncreaseButton") as ButtonBase;
DecreaseButton = GetTemplateChild("DecreaseButton") as ButtonBase;
SetButtonUsage();
}
#endregion //Base Class Overrides
/// <summary>
/// Occurs when the Content property value changed.
/// </summary>
/// <param name="oldValue">The old value of the Content property.</param>
/// <param name="newValue">The new value of the Content property.</param>
protected virtual void OnContentChanged(object oldValue, object newValue) { }
/// <summary>
/// Handle click event of IncreaseButton and DecreaseButton template parts,
/// translating Click to appropriate Spin event.
/// </summary>
/// <param name="sender">Event sender, should be either IncreaseButton or DecreaseButton template part.</param>
/// <param name="e">Event args.</param>
private void OnButtonClick(object sender, RoutedEventArgs e)
{
SpinDirection direction = sender == IncreaseButton ? SpinDirection.Increase : SpinDirection.Decrease;
OnSpin(new SpinEventArgs(direction));
}
/// <summary>
/// Cancel LeftMouseButtonUp events originating from a button that has
/// been changed to disabled.
/// </summary>
/// <param name="e">The data for the event.</param>
protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonUp(e);
Point mousePosition;
if (IncreaseButton != null && IncreaseButton.IsEnabled == false)
{
mousePosition = e.GetPosition(IncreaseButton);
if (mousePosition.X > 0 && mousePosition.X < IncreaseButton.ActualWidth &&
mousePosition.Y > 0 && mousePosition.Y < IncreaseButton.ActualHeight)
{
e.Handled = true;
}
}
if (DecreaseButton != null && DecreaseButton.IsEnabled == false)
{
mousePosition = e.GetPosition(DecreaseButton);
if (mousePosition.X > 0 && mousePosition.X < DecreaseButton.ActualWidth &&
mousePosition.Y > 0 && mousePosition.Y < DecreaseButton.ActualHeight)
{
e.Handled = true;
}
}
}
/// <summary>
/// Called when valid spin direction changed.
/// </summary>
/// <param name="oldValue">The old value.</param>
/// <param name="newValue">The new value.</param>
protected override void OnValidSpinDirectionChanged(ValidSpinDirections oldValue, ValidSpinDirections newValue)
{
SetButtonUsage();
}
/// <summary>
/// Disables or enables the buttons based on the valid spin direction.
/// </summary>
private void SetButtonUsage()
{
// buttonspinner adds buttons that spin, so disable accordingly.
if (IncreaseButton != null)
{
IncreaseButton.IsEnabled = ((ValidSpinDirection & ValidSpinDirections.Increase) == ValidSpinDirections.Increase);
}
if (DecreaseButton != null)
{
DecreaseButton.IsEnabled = ((ValidSpinDirection & ValidSpinDirections.Decrease) == ValidSpinDirections.Decrease);
}
}
}
}

21
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/SpinDirection.cs

@ -0,0 +1,21 @@
using System;
namespace Microsoft.Windows.Controls.Primitives
{
/// <summary>
/// Represents spin directions that could be initiated by the end-user.
/// </summary>
/// <QualityBand>Preview</QualityBand>
public enum SpinDirection
{
/// <summary>
/// Represents a spin initiated by the end-user in order to Increase a value.
/// </summary>
Increase = 0,
/// <summary>
/// Represents a spin initiated by the end-user in order to Decrease a value.
/// </summary>
Decrease = 1
}
}

28
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/SpinEventArgs.cs

@ -0,0 +1,28 @@
using System;
using System.Windows;
namespace Microsoft.Windows.Controls.Primitives
{
/// <summary>
/// Provides data for the Spinner.Spin event.
/// </summary>
/// <QualityBand>Preview</QualityBand>
public class SpinEventArgs : RoutedEventArgs
{
/// <summary>
/// Gets the SpinDirection for the spin that has been initiated by the
/// end-user.
/// </summary>
public SpinDirection Direction { get; private set; }
/// <summary>
/// Initializes a new instance of the SpinEventArgs class.
/// </summary>
/// <param name="direction">Spin direction.</param>
public SpinEventArgs(SpinDirection direction)
: base()
{
Direction = direction;
}
}
}

77
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/Spinner.cs

@ -0,0 +1,77 @@
using System;
using System.Windows.Controls;
using System.Windows;
namespace Microsoft.Windows.Controls.Primitives
{
/// <summary>
/// Base class for controls that represents controls that can spin.
/// </summary>
public abstract class Spinner : Control
{
#region Properties
/// <summary>
/// Identifies the ValidSpinDirection dependency property.
/// </summary>
public static readonly DependencyProperty ValidSpinDirectionProperty = DependencyProperty.Register("ValidSpinDirection", typeof(ValidSpinDirections), typeof(Spinner), new PropertyMetadata(ValidSpinDirections.Increase | ValidSpinDirections.Decrease, OnValidSpinDirectionPropertyChanged));
public ValidSpinDirections ValidSpinDirection
{
get { return (ValidSpinDirections)GetValue(ValidSpinDirectionProperty); }
set { SetValue(ValidSpinDirectionProperty, value); }
}
/// <summary>
/// ValidSpinDirectionProperty property changed handler.
/// </summary>
/// <param name="d">ButtonSpinner that changed its ValidSpinDirection.</param>
/// <param name="e">Event arguments.</param>
private static void OnValidSpinDirectionPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Spinner source = (Spinner)d;
ValidSpinDirections oldvalue = (ValidSpinDirections)e.OldValue;
ValidSpinDirections newvalue = (ValidSpinDirections)e.NewValue;
source.OnValidSpinDirectionChanged(oldvalue, newvalue);
}
#endregion //Properties
/// <summary>
/// Occurs when spinning is initiated by the end-user.
/// </summary>
public event EventHandler<SpinEventArgs> Spin;
/// <summary>
/// Initializes a new instance of the Spinner class.
/// </summary>
protected Spinner() { }
/// <summary>
/// Raises the OnSpin event when spinning is initiated by the end-user.
/// </summary>
/// <param name="e">Spin event args.</param>
protected virtual void OnSpin(SpinEventArgs e)
{
ValidSpinDirections valid = e.Direction == SpinDirection.Increase ? ValidSpinDirections.Increase : ValidSpinDirections.Decrease;
if ((ValidSpinDirection & valid) != valid)
{
// spin is not allowed.
throw new InvalidOperationException("Spin action is not valid at this moment.");
}
EventHandler<SpinEventArgs> handler = Spin;
if (handler != null)
{
handler(this, e);
}
}
/// <summary>
/// Called when valid spin direction changed.
/// </summary>
/// <param name="oldValue">The old value.</param>
/// <param name="newValue">The new value.</param>
protected virtual void OnValidSpinDirectionChanged(ValidSpinDirections oldValue, ValidSpinDirections newValue) { }
}
}

26
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Core/Primitives/ValidSpinDirections.cs

@ -0,0 +1,26 @@
using System;
namespace Microsoft.Windows.Controls.Primitives
{
/// <summary>
/// Represents spin directions that are valid.
/// </summary>
[Flags]
public enum ValidSpinDirections
{
/// <summary>
/// Can not increase nor decrease.
/// </summary>
None = 0,
/// <summary>
/// Can increase.
/// </summary>
Increase = 1,
/// <summary>
/// Can decrease.
/// </summary>
Decrease = 2
}
}

153
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/Themes/Generic.xaml

@ -926,4 +926,157 @@
</Setter>
</Style>
<!-- =============================================================================== -->
<!-- ButtonSpinner -->
<!-- =============================================================================== -->
<DataTemplate x:Key="IncreaseGlyph">
<Path Width="7" Height="4" Data="M 0,3 C0,3 0,4 0,4 0,4 3,4 3,4 3,4 3,3 3,3 3,3 4,3 4,3 4,3 4,4 4,4 4,4 7,4 7,4 7,4 7,3 7,3 7,3 6,3 6,3 6,3 6,2 6,2 6,2 5,2 5,2 5,2 5,1 5,1 5,1 4,1 4,1 4,1 4,0 4,0 4,0 3,0 3,0 3,0 3,1 3,1 3,1 2,1 2,1 2,1 2,2 2,2 2,2 1,2 1,2 1,2 1,3 1,3 1,3 0,3 0,3 z" Fill="#FF000000"/>
</DataTemplate>
<DataTemplate x:Key="DecreaseGlyph">
<Path Width="7" Height="4" Data="M 0,1 C0,1 0,0 0,0 0,0 3,0 3,0 3,0 3,1 3,1 3,1 4,1 4,1 4,1 4,0 4,0 4,0 7,0 7,0 7,0 7,1 7,1 7,1 6,1 6,1 6,1 6,2 6,2 6,2 5,2 5,2 5,2 5,3 5,3 5,3 4,3 4,3 4,3 4,4 4,4 4,4 3,4 3,4 3,4 3,3 3,3 3,3 2,3 2,3 2,3 2,2 2,2 2,2 1,2 1,2 1,2 1,1 1,1 1,1 0,1 0,1 z" Fill="#FF000000"/>
</DataTemplate>
<SolidColorBrush x:Key="SpinButtonNormalOuterBorderFillKey" Color="#FFABADB3"/>
<LinearGradientBrush x:Key="SpinButtonNormalInnerBorderFillKey" StartPoint="0.5,0" EndPoint="0.5,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Offset="0" Color="#FFfcfcfc"/>
<GradientStop Offset="0.69" Color="#FFf9f9f9"/>
<GradientStop Offset="0.69" Color="#FFf3f3f3"/>
<GradientStop Offset="1" Color="#FFf3f3f3"/>
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
<LinearGradientBrush x:Key="SpinButtonNormalCenterFillKey" StartPoint="0.5,0" EndPoint="0.5,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Offset="0" Color="#FFf2f2f2"/>
<GradientStop Offset="0.69" Color="#FFe8e8e8"/>
<GradientStop Offset="0.69" Color="#FFd1d1d1"/>
<GradientStop Offset="1" Color="#FFd1d1d1"/>
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
<SolidColorBrush x:Key="SpinButtonHottrackOuterBorderFillKey" Color="#FF3C7FB1"/>
<LinearGradientBrush x:Key="SpinButtonHottrackInnerBorderFillKey" StartPoint="0.5,0" EndPoint="0.5,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="#FFfafdfe" Offset="0" />
<GradientStop Color="#FFf5fbfe" Offset="0.5" />
<GradientStop Color="#FFeff9fe" Offset="0.5009999871253967" />
<GradientStop Color="#FFe8f5fc" Offset="1" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
<LinearGradientBrush x:Key="SpinButtonHottrackCenterFillKey" StartPoint="0.5,0" EndPoint="0.5,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="#FFeaf6fd" Offset="0" />
<GradientStop Color="#FFd9f0fc" Offset="0.5" />
<GradientStop Color="#FFbee6fd" Offset="0.5009999871253967" />
<GradientStop Color="#FFa7d9f5" Offset="1" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
<SolidColorBrush x:Key="SpinButtonPressedOuterBorderFillKey" Color="#FF2C628B"/>
<LinearGradientBrush x:Key="SpinButtonPressedInnerBorderFillKey" StartPoint="0.5,0" EndPoint="0.5,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="#FF9eb0ba" Offset="0" />
<GradientStop Color="#FF9abacb" Offset="0.5" />
<GradientStop Color="#FF78aac5" Offset="0.5008999705314636" />
<GradientStop Color="#FF5a96b8" Offset="0.8999999761581421" />
<GradientStop Color="#FF68b2da" Offset="1" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
<LinearGradientBrush x:Key="SpinButtonPressedCenterFillKey" StartPoint="0.5,0" EndPoint="0.5,1">
<LinearGradientBrush.GradientStops>
<GradientStopCollection>
<GradientStop Color="#FFe5f4fc" Offset="0" />
<GradientStop Color="#FFc4e5f6" Offset="0.5" />
<GradientStop Color="#FF98d1ef" Offset="0.5009999871253967" />
<GradientStop Color="#FF68b3db" Offset="1" />
</GradientStopCollection>
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
<Style x:Key="SpinButtonStyle" TargetType="{x:Type RepeatButton}">
<Setter Property="Background" Value="{StaticResource SpinButtonNormalCenterFillKey}"/>
<Setter Property="BorderBrush" Value="{StaticResource SpinButtonNormalOuterBorderFillKey}"/>
<Setter Property="Foreground" Value="{StaticResource SpinButtonGlyphNormalForegroundFillKey}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Padding" Value="3,1"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RepeatButton}">
<Border x:Name="Bd" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" CornerRadius="0">
<Grid>
<Border x:Name="innerBd" BorderBrush="{StaticResource SpinButtonNormalInnerBorderFillKey}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="0"/>
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Margin="{TemplateBinding Padding}"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="BorderBrush" TargetName="innerBd" Value="{StaticResource SpinButtonHottrackInnerBorderFillKey}"/>
<Setter Property="Background" TargetName="Bd" Value="{StaticResource SpinButtonHottrackCenterFillKey}"/>
<Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource SpinButtonHottrackOuterBorderFillKey}"/>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource SpinButtonPressedOuterBorderFillKey}"/>
<Setter Property="Background" TargetName="Bd" Value="{StaticResource SpinButtonPressedCenterFillKey}"/>
<Setter Property="BorderBrush" TargetName="innerBd" Value="{StaticResource SpinButtonPressedInnerBorderFillKey}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False"/>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type local:ButtonSpinner}">
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="BorderBrush">
<Setter.Value>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FFA3AEB9" Offset="0" />
<GradientStop Color="#FF8399A9" Offset="0.375" />
<GradientStop Color="#FF718597" Offset="0.375" />
<GradientStop Color="#FF617584" Offset="1" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:ButtonSpinner}">
<Grid>
<Border x:Name="ElementContainer" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}">
<DockPanel>
<Grid DockPanel.Dock="Right">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="1" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<RepeatButton x:Name="IncreaseButton" SnapsToDevicePixels="True" Grid.Row="0" Focusable="False" Style="{StaticResource SpinButtonStyle}" ContentTemplate="{StaticResource IncreaseGlyph}" ClickMode="Press" />
<RepeatButton x:Name="DecreaseButton" SnapsToDevicePixels="True" Grid.Row="2" Focusable="False" Style="{StaticResource SpinButtonStyle}" ContentTemplate="{StaticResource DecreaseGlyph}" ClickMode="Press" />
</Grid>
<ContentControl x:Name="presentationSite"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
Content="{TemplateBinding Content}" />
</DockPanel>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

5
ExtendedWPFToolkitSolution/Src/WPFToolkit.Extended/WPFToolkit.Extended.csproj

@ -64,6 +64,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="BusyIndicator\BusyIndicator.cs" />
<Compile Include="ButtonSpinner\ButtonSpinner.cs" />
<Compile Include="ChildWindow\ChildWindow.cs" />
<Compile Include="ChildWindow\VisualStates.ChildWindow.cs" />
<Compile Include="ChildWindow\WindowState.cs" />
@ -71,6 +72,10 @@
<Compile Include="ColorPicker\HsvColor.cs" />
<Compile Include="ColorPicker\ColorUtilities.cs" />
<Compile Include="ColorPicker\ColorSpectrumSlider.cs" />
<Compile Include="Core\Primitives\SpinDirection.cs" />
<Compile Include="Core\Primitives\SpinEventArgs.cs" />
<Compile Include="Core\Primitives\Spinner.cs" />
<Compile Include="Core\Primitives\ValidSpinDirections.cs" />
<Compile Include="MessageBox\MessageBox.cs" />
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>

Loading…
Cancel
Save