update to v1.3.0

This commit is contained in:
NaBian committed 2018-10-03 21:27:15 +08:00
1 parent a68b0213a6
commit 9daa1a6ee1
60 files changed
+2391 -76

No files matched your search

+10
View File
@@ -1,3 +1,13 @@
2018.10.03 Version 1.3.0
* new controls
- add Clock
- add TimePicker
- add CirclePanel
* new style
- add Calendar
- add DataPicker
2018.09.18 Version 1.2.2
* new controls
- add StepBar
@@ -0,0 +1,30 @@
using System.Windows;
using HandyControl.Data.Enum;
// ReSharper disable once CheckNamespace
namespace HandyControl.Controls
{
public class InfoElement : DependencyObject
{
public static readonly DependencyProperty TitleProperty = DependencyProperty.RegisterAttached(
"Title", typeof(string), typeof(InfoElement), new PropertyMetadata(default(string)));
public static void SetTitle(DependencyObject element, string value) => element.SetValue(TitleProperty, value);
public static string GetTitle(DependencyObject element) => (string) element.GetValue(TitleProperty);
public static readonly DependencyProperty RequiredProperty = DependencyProperty.RegisterAttached(
"Required", typeof(bool), typeof(InfoElement), new PropertyMetadata(default(bool)));
public static void SetRequired(DependencyObject element, bool value) => element.SetValue(RequiredProperty, value);
public static bool GetRequired(DependencyObject element) => (bool)element.GetValue(RequiredProperty);
public static readonly DependencyProperty TitleAlignmentProperty = DependencyProperty.RegisterAttached(
"TitleAlignment", typeof(TitleAlignment), typeof(InfoElement), new PropertyMetadata(default(TitleAlignment)));
public static void SetTitleAlignment(DependencyObject element, TitleAlignment value) => element.SetValue(TitleAlignmentProperty, value);
public static TitleAlignment GetTitleAlignment(DependencyObject element) => (TitleAlignment) element.GetValue(TitleAlignmentProperty);
}
}
+69
View File
@@ -0,0 +1,69 @@
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace HandyControl.Controls
{
public class CirclePanel : Panel
{
public static readonly DependencyProperty DiameterProperty = DependencyProperty.Register(
"Diameter", typeof(double), typeof(CirclePanel), new PropertyMetadata(170.0));
public double Diameter
{
get => (double) GetValue(DiameterProperty);
set => SetValue(DiameterProperty, value);
}
public static readonly DependencyProperty KeepVerticalProperty = DependencyProperty.Register(
"KeepVertical", typeof(bool), typeof(CirclePanel), new PropertyMetadata(default(bool)));
public bool KeepVertical
{
get => (bool) GetValue(KeepVerticalProperty);
set => SetValue(KeepVerticalProperty, value);
}
public static readonly DependencyProperty OffsetAngleProperty = DependencyProperty.Register(
"OffsetAngle", typeof(double), typeof(CirclePanel), new PropertyMetadata(default(double)));
public double OffsetAngle
{
get => (double) GetValue(OffsetAngleProperty);
set => SetValue(OffsetAngleProperty, value);
}
// ReSharper disable once RedundantAssignment
protected override Size MeasureOverride(Size availableSize)
{
if (Children.Count == 0) return new Size(Diameter, Diameter);
availableSize = new Size(Diameter, Diameter);
var i = 0;
var perDeg = 360.0 / Children.Count;
var radius = Diameter / 2;
foreach (UIElement element in Children)
{
element.Measure(availableSize);
var centerX = element.DesiredSize.Width / 2.0;
var centerY = element.DesiredSize.Height / 2.0;
var angle = perDeg * i++ + OffsetAngle;
var transform = new RotateTransform
{
CenterX = centerX,
CenterY = centerY,
Angle = KeepVertical ? 0 : angle
};
element.RenderTransform = transform;
var r = Math.PI * angle / 180.0;
var x = radius * Math.Cos(r);
var y = radius * Math.Sin(r);
var rectX = x + availableSize.Width / 2 - centerX;
var rectY = y + availableSize.Height / 2 - centerY;
element.Arrange(new Rect(rectX, rectY, element.DesiredSize.Width, element.DesiredSize.Height));
}
return availableSize;
}
}
}
+418
View File
@@ -0,0 +1,418 @@
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
using HandyControl.Data;
using HandyControl.Tools;
namespace HandyControl.Controls
{
[TemplatePart(Name = ElementButtonAm, Type = typeof(RadioButton))]
[TemplatePart(Name = ElementButtonPm, Type = typeof(RadioButton))]
[TemplatePart(Name = ElementButtonConfirm, Type = typeof(Button))]
[TemplatePart(Name = ElementCanvas, Type = typeof(Canvas))]
[TemplatePart(Name = ElementBorderTitle, Type = typeof(Border))]
[TemplatePart(Name = ElementBorderClock, Type = typeof(Border))]
[TemplatePart(Name = ElementPanelNum, Type = typeof(CirclePanel))]
[TemplatePart(Name = ElementTimeStr, Type = typeof(TextBlock))]
public class Clock : Control
{
#region Constants
private const string ElementButtonAm = "PART_ButtonAm";
private const string ElementButtonPm = "PART_ButtonPm";
private const string ElementButtonConfirm = "PART_ButtonConfirm";
private const string ElementCanvas = "PART_Canvas";
private const string ElementBorderTitle = "PART_BorderTitle";
private const string ElementBorderClock = "PART_BorderClock";
private const string ElementPanelNum = "PART_PanelNum";
private const string ElementTimeStr = "PART_TimeStr";
#endregion Constants
#region Data
private RadioButton _buttonAm;
private RadioButton _buttonPm;
private Button _buttonConfirm;
private Canvas _canvas;
private Border _borderTitle;
private Border _borderClock;
private ClockRadioButton _currentButton;
private RotateTransform _rotateTransformClock;
private CirclePanel _circlePanel;
private List<ClockRadioButton> _radioButtonList;
private TextBlock _blockTime;
private int _secValue;
private bool _isLoaded;
private bool _appliedTemplate;
#endregion Data
#region Public Events
public static readonly RoutedEvent SelectedTimeChangedEvent =
EventManager.RegisterRoutedEvent("SelectedTimeChanged", RoutingStrategy.Direct,
typeof(EventHandler<FunctionEventArgs<DateTime?>>), typeof(Clock));
public event EventHandler<FunctionEventArgs<DateTime?>> SelectedTimeChanged
{
add => AddHandler(SelectedTimeChangedEvent, value);
remove => RemoveHandler(SelectedTimeChangedEvent, value);
}
public event EventHandler<FunctionEventArgs<DateTime?>> DisplayTimeChanged;
public event Action Confirmed;
#endregion Public Events
public Clock()
{
Loaded += (s, e) =>
{
if (_isLoaded) return;
_isLoaded = true;
DisplayTime = DateTime.Now;
};
}
#region Public Properties
public static readonly DependencyProperty SelectedTimeProperty = DependencyProperty.Register(
"SelectedTime", typeof(DateTime?), typeof(Clock), new PropertyMetadata(default(DateTime), OnSelectedTimeChanged));
private static void OnSelectedTimeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var ctl = (Clock)d;
var v = (DateTime?)e.NewValue;
ctl.OnSelectedTimeChanged(new FunctionEventArgs<DateTime?>(SelectedTimeChangedEvent, ctl)
{
Info = v
});
}
public DateTime? SelectedTime
{
get => (DateTime?) GetValue(SelectedTimeProperty);
set => SetValue(SelectedTimeProperty, value);
}
public static readonly DependencyProperty TimeFormatProperty = DependencyProperty.Register(
"TimeFormat", typeof(string), typeof(Clock), new PropertyMetadata("HH:mm:ss"));
public string TimeFormat
{
get => (string) GetValue(TimeFormatProperty);
set => SetValue(TimeFormatProperty, value);
}
public static readonly DependencyProperty ClockRadioButtonStyleProperty = DependencyProperty.Register(
"ClockRadioButtonStyle", typeof(Style), typeof(Clock), new PropertyMetadata(default(Style)));
public Style ClockRadioButtonStyle
{
get => (Style) GetValue(ClockRadioButtonStyleProperty);
set => SetValue(ClockRadioButtonStyleProperty, value);
}
public static readonly DependencyProperty DisplayTimeProperty = DependencyProperty.Register(
"DisplayTime", typeof(DateTime), typeof(Clock), new FrameworkPropertyMetadata(DateTime.MinValue, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnDisplayTimeChanged));
private static void OnDisplayTimeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var ctl = (Clock) d;
var v = (DateTime) e.NewValue;
ctl.Update(v);
ctl.OnDisplayTimeChanged(new FunctionEventArgs<DateTime?>(v));
}
public DateTime DisplayTime
{
get => (DateTime) GetValue(DisplayTimeProperty);
set => SetValue(DisplayTimeProperty, value);
}
internal static readonly DependencyProperty ShowConfirmButtonProperty = DependencyProperty.Register(
"ShowConfirmButton", typeof(bool), typeof(Clock), new PropertyMetadata(default(bool)));
internal bool ShowConfirmButton
{
get => (bool)GetValue(ShowConfirmButtonProperty);
set => SetValue(ShowConfirmButtonProperty, value);
}
private int SecValue
{
get => _secValue;
set
{
if (value < 0)
{
_secValue = 59;
}
else if (value > 59)
{
_secValue = 0;
}
else
{
_secValue = value;
}
}
}
#endregion Public Properties
#region Public Methods
public override void OnApplyTemplate()
{
_appliedTemplate = false;
_buttonAm?.RemoveHandler(ButtonBase.ClickEvent, new RoutedEventHandler(ButtonAm_OnClick));
_buttonPm?.RemoveHandler(ButtonBase.ClickEvent, new RoutedEventHandler(ButtonPm_OnClick));
_buttonConfirm?.RemoveHandler(ButtonBase.ClickEvent, new RoutedEventHandler(ButtonConfirm_OnClick));
_borderTitle?.RemoveHandler(MouseWheelEvent, new MouseWheelEventHandler(BorderTitle_OnMouseWheel));
if (_canvas != null)
{
_canvas.RemoveHandler(MouseWheelEvent, new MouseWheelEventHandler(MyCanvas_OnMouseWheel));
_canvas.RemoveHandler(ButtonBase.ClickEvent, new RoutedEventHandler(MyCanvas_OnClick));
_canvas.RemoveHandler(MouseMoveEvent, new MouseEventHandler(MyCanvas_OnMouseMove));
}
base.OnApplyTemplate();
_buttonAm = GetTemplateChild(ElementButtonAm) as RadioButton;
_buttonPm = GetTemplateChild(ElementButtonPm) as RadioButton;
_buttonConfirm = GetTemplateChild(ElementButtonConfirm) as Button;
_borderTitle = GetTemplateChild(ElementBorderTitle) as Border;
_canvas = GetTemplateChild(ElementCanvas) as Canvas;
_borderClock = GetTemplateChild(ElementBorderClock) as Border;
_circlePanel = GetTemplateChild(ElementPanelNum) as CirclePanel;
_blockTime = GetTemplateChild(ElementTimeStr) as TextBlock;
CheckNull();
_buttonAm.AddHandler(ButtonBase.ClickEvent, new RoutedEventHandler(ButtonAm_OnClick));
_buttonPm.AddHandler(ButtonBase.ClickEvent, new RoutedEventHandler(ButtonPm_OnClick));
_buttonConfirm.AddHandler(ButtonBase.ClickEvent, new RoutedEventHandler(ButtonConfirm_OnClick));
_borderTitle.AddHandler(MouseWheelEvent, new MouseWheelEventHandler(BorderTitle_OnMouseWheel));
_canvas.AddHandler(MouseWheelEvent, new MouseWheelEventHandler(MyCanvas_OnMouseWheel));
_canvas.AddHandler(ButtonBase.ClickEvent, new RoutedEventHandler(MyCanvas_OnClick));
_canvas.AddHandler(MouseMoveEvent, new MouseEventHandler(MyCanvas_OnMouseMove));
_rotateTransformClock = new RotateTransform();
_borderClock.RenderTransform = _rotateTransformClock;
_radioButtonList = new List<ClockRadioButton>();
for (var i = 0; i < 12; i++)
{
var num = i + 1;
var button = new ClockRadioButton
{
Num = num,
Content = num
};
button.SetBinding(StyleProperty, new Binding(ClockRadioButtonStyleProperty.Name) { Source = this });
_radioButtonList.Add(button);
_circlePanel.Children.Add(button);
}
_appliedTemplate = true;
}
#endregion Public Methods
#region Protected Methods
protected virtual void OnSelectedTimeChanged(FunctionEventArgs<DateTime?> e) => RaiseEvent(e);
protected virtual void OnDisplayTimeChanged(FunctionEventArgs<DateTime?> e)
{
var handler = DisplayTimeChanged;
handler?.Invoke(this, e);
}
#endregion Protected Methods
#region Private Methods
private void CheckNull()
{
if (_buttonPm == null || _buttonAm == null || _buttonConfirm == null || _canvas == null ||
_borderTitle == null || _borderClock == null || _circlePanel == null ||
_blockTime == null) throw new Exception();
}
private void BorderTitle_OnMouseWheel(object sender, MouseWheelEventArgs e)
{
if (e.Delta < 0)
{
SecValue--;
Update();
}
else
{
SecValue++;
Update();
}
e.Handled = true;
}
private void MyCanvas_OnMouseWheel(object sender, MouseWheelEventArgs e)
{
var value = (int)_rotateTransformClock.Angle;
if (e.Delta < 0)
{
value += 6;
}
else
{
value -= 6;
}
if (value < 0)
{
value = value + 360;
}
_rotateTransformClock.Angle = value;
Update();
e.Handled = true;
}
private void MyCanvas_OnClick(object sender, RoutedEventArgs e)
{
_currentButton = e.OriginalSource as ClockRadioButton;
if (_currentButton != null)
{
Update();
}
}
private void MyCanvas_OnMouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
var value = ArithmeticHelper.CalAngle(new Point(85, 85), e.GetPosition(_canvas)) + 90;
if (value < 0)
{
value = value + 360;
}
value = value - value % 6;
_rotateTransformClock.Angle = value;
Update();
}
}
private void Update()
{
if (!_appliedTemplate) return;
var hValue = _currentButton.Num;
if (_buttonPm.IsChecked == true)
{
hValue += 12;
if (hValue == 24) hValue = 12;
}
else if (hValue == 12)
{
hValue = 0;
}
if (hValue == 12 && _buttonAm.IsChecked == true)
{
_buttonPm.IsChecked = true;
_buttonAm.IsChecked = false;
}
if (_blockTime != null)
{
DisplayTime = GetDisplayTime();
_blockTime.Text = DisplayTime.ToString(TimeFormat);
}
}
/// <summary>
/// 更新
/// </summary>
/// <param name="time"></param>
private void Update(DateTime time)
{
if (!_appliedTemplate) return;
var h = time.Hour;
var m = time.Minute;
if (h >= 12)
{
_buttonPm.IsChecked = true;
_buttonAm.IsChecked = false;
}
else
{
_buttonPm.IsChecked = false;
_buttonAm.IsChecked = true;
}
_rotateTransformClock.Angle = m * 6;
var hRest = h % 12;
if (hRest == 0) hRest = 12;
var ctl = _radioButtonList[hRest-1];
ctl.IsChecked = true;
ctl.RaiseEvent(new RoutedEventArgs { RoutedEvent = ButtonBase.ClickEvent });
_secValue = time.Second;
Update();
}
private void ButtonConfirm_OnClick(object sender, RoutedEventArgs e)
{
SelectedTime = DisplayTime;
Confirmed?.Invoke();
}
/// <summary>
/// 获取显示时间
/// </summary>
/// <returns></returns>
private DateTime GetDisplayTime()
{
var hValue = _currentButton.Num;
if (_buttonPm.IsChecked == true)
{
hValue += 12;
if (hValue == 24) hValue = 12;
}
else if (hValue == 12)
{
hValue = 0;
}
var now = DateTime.Now;
return new DateTime(now.Year, now.Month, now.Day, hValue, (int)Math.Abs(_rotateTransformClock.Angle) % 360 / 6, _secValue);
}
private void ButtonAm_OnClick(object sender, RoutedEventArgs e) => Update();
private void ButtonPm_OnClick(object sender, RoutedEventArgs e) => Update();
#endregion Private Methods
}
}
+11
View File
@@ -0,0 +1,11 @@
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
namespace HandyControl.Controls
{
public class ClockRadioButton : RadioButton
{
public int Num { get; set; }
}
}
+3 -2
View File
@@ -3,6 +3,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:langs="clr-namespace:HandyControl.Properties.Langs"
mc:Ignorable="d"
MinHeight="60"
Name="UserControlThis"
@@ -50,10 +51,10 @@
</Button>
<StackPanel Name="PanelMore" IsEnabled="False" Visibility="Collapsed" Orientation="Horizontal" Grid.Row="1" Grid.ColumnSpan="3" Height="28" Grid.Column="0">
<Button Click="ButtonCancel_OnClick" Style="{StaticResource ButtonCustom}" Width="160">
<TextBlock Text="取消" HorizontalAlignment="Center" Foreground="{StaticResource DangerBrush}"></TextBlock>
<TextBlock Text="{x:Static langs:Lang.Cancel}" HorizontalAlignment="Center" Foreground="{StaticResource DangerBrush}"></TextBlock>
</Button>
<Button Click="ButtonOk_OnClick" Style="{StaticResource ButtonCustom}" Width="160">
<TextBlock Text="确定" HorizontalAlignment="Center" Foreground="{StaticResource PrimaryBrush}"></TextBlock>
<TextBlock Text="{x:Static langs:Lang.Confirm}" HorizontalAlignment="Center" Foreground="{StaticResource PrimaryBrush}"></TextBlock>
</Button>
</StackPanel>
</Grid>
+1 -1
View File
@@ -11,7 +11,7 @@ using HandyControl.Tools.Extension;
// ReSharper disable once CheckNamespace
namespace HandyControl.Controls
{
public abstract class InfoControl : UserControl
internal abstract class InfoControl : UserControl
{
private bool _isFocused;
@@ -1,10 +1,11 @@
<controls:InfoControl x:Class="HandyControl.Controls.InfoNumericUpDown"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:controls="clr-namespace:HandyControl.Controls"
mc:Ignorable="d"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:ClassModifier="internal"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:controls="clr-namespace:HandyControl.Controls"
mc:Ignorable="d"
Validation.ErrorTemplate="{x:Null}"
FontSize="14"
MinHeight="24"
@@ -44,7 +45,7 @@
</Grid.RowDefinitions>
<StackPanel Name="StackPanelTitle" Grid.Row="1" HorizontalAlignment="Right" Orientation="Horizontal">
<TextBlock Visibility="{Binding IsNeedly,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl},Converter={StaticResource Boolean2VisibilityConverter}}" VerticalAlignment="Center" Margin="0,0,6,0" Text="*" Foreground="{DynamicResource DangerBrush}"></TextBlock>
<TextBlock Style="{StaticResource TextBlockDefault}" Visibility="{Binding Text,RelativeSource={RelativeSource Mode=Self},Converter={StaticResource String2VisibilityReConverter}}" Margin="0,0,10,0" Text="{Binding Title,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl}}"></TextBlock>
<TextBlock Style="{StaticResource TextBlockDefault}" Visibility="{Binding Text,RelativeSource={RelativeSource Mode=Self},Converter={StaticResource String2VisibilityConverter}}" Margin="0,0,10,0" Text="{Binding Title,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl}}"></TextBlock>
</StackPanel>
<TextBlock Margin="4,0,0,1" Grid.Row="1" Name="TextBlockError" Grid.Column="1" VerticalAlignment="Bottom" FontSize="12" Foreground="{DynamicResource DangerBrush}" Text="{Binding ErrorStr,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl}}"></TextBlock>
<Border Grid.Row="1" Name="Border" Background="White" Grid.Column="1" CornerRadius="{Binding CornerRadius,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl}}" BorderThickness="1" BorderBrush="Transparent">
@@ -54,9 +55,9 @@
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding PlaceHolder,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl}}" HorizontalAlignment="Left" Padding="10,0" FontSize="14" Visibility="{Binding Text,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl},Converter={StaticResource String2VisibilityConverter}}" VerticalAlignment="Center" Foreground="{DynamicResource ThirdlyTextBrush}"/>
<TextBlock Text="{Binding PlaceHolder,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl}}" HorizontalAlignment="Left" Padding="10,0" FontSize="14" Visibility="{Binding Text,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl},Converter={StaticResource String2VisibilityReConverter}}" VerticalAlignment="Center" Foreground="{DynamicResource ThirdlyTextBrush}"/>
<TextBox Grid.Column="0" MouseWheel="MyTextBox_OnMouseWheel" HorizontalContentAlignment="{Binding HorizontalTextAlignment,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl}}" TextChanged="InputBox_OnTextChanged" MouseLeave="InputBox_OnMouseLeave" MouseEnter="InputBox_OnMouseEnter" GotFocus="InputBox_OnGotFocus" LostFocus="InputBox_OnLostFocus" Name="MyTextBox" Margin="4,0" BorderThickness="0" VerticalContentAlignment="Center" Padding="{Binding TextPadding,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl}}" Text="{Binding Value,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl},UpdateSourceTrigger=PropertyChanged}" Background="{x:Null}"></TextBox>
<Button Padding="7" Visibility="{Binding Text,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl},Converter={StaticResource String2VisibilityReConverter}}" Focusable="True" Grid.Column="1" Name="ButtonClear" Click="ButtonClear_OnClick" Foreground="{DynamicResource ThirdlyTextBrush}" controls:IconElement.Geometry="{StaticResource DeleteFillCircleGeometry}" Style="{StaticResource ButtonIcon}" Width="36" HorizontalAlignment="Right"></Button>
<Button Padding="7" Visibility="{Binding Text,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl},Converter={StaticResource String2VisibilityConverter}}" Focusable="True" Grid.Column="1" Name="ButtonClear" Click="ButtonClear_OnClick" Foreground="{DynamicResource ThirdlyTextBrush}" controls:IconElement.Geometry="{StaticResource DeleteFillCircleGeometry}" Style="{StaticResource ButtonIcon}" Width="36" HorizontalAlignment="Right"></Button>
<Button Visibility="{Binding ShowUpDownButton,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl},Converter={StaticResource Boolean2VisibilityConverter}}" Padding="7,7,7,3" Focusable="True" Grid.Column="2" Click="ButtonUp_OnClick" Foreground="{DynamicResource ThirdlyTextBrush}" controls:IconElement.Geometry="{StaticResource UpGeometry}" Style="{StaticResource ButtonIcon}" Width="36" HorizontalAlignment="Right" VerticalAlignment="Top" Height="17"></Button>
<Button Visibility="{Binding ShowUpDownButton,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl},Converter={StaticResource Boolean2VisibilityConverter}}" Padding="7,3,7,7" Focusable="True" Grid.Column="2" Click="ButtonDown_OnClick" Foreground="{DynamicResource ThirdlyTextBrush}" controls:IconElement.Geometry="{StaticResource DownGeometry}" Style="{StaticResource ButtonIcon}" Width="36" HorizontalAlignment="Right" VerticalAlignment="Bottom" Height="17"></Button>
</Grid>
@@ -3,6 +3,7 @@ using System.Windows;
using System.Windows.Input;
using System.Windows.Media.Animation;
using HandyControl.Data;
using HandyControl.Tools;
// ReSharper disable once CheckNamespace
namespace HandyControl.Controls
@@ -10,7 +11,7 @@ namespace HandyControl.Controls
/// <summary>
/// InfoNumericUpDown.xaml 的交互逻辑
/// </summary>
public partial class InfoNumericUpDown
internal partial class InfoNumericUpDown
{
public InfoNumericUpDown()
{
@@ -44,7 +45,7 @@ namespace HandyControl.Controls
var max = (double)value;
if (max < info.Minimum) max = info.Minimum;
return max;
}), ValidateValueCallback);
}), ValidateHelper.IsInRangeOfDouble);
/// <summary>
/// 最大值
@@ -69,7 +70,7 @@ namespace HandyControl.Controls
var min = (double)value;
if (min > info.Maximum) min = info.Maximum;
return min;
}), ValidateValueCallback);
}), ValidateHelper.IsInRangeOfDouble);
/// <summary>
/// 最小值
@@ -102,18 +103,7 @@ namespace HandyControl.Controls
if (current > info.Maximum) current = info.Maximum;
return current;
}), ValidateValueCallback);
/// <summary>
/// 值验证回调
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
private static bool ValidateValueCallback(object value)
{
var v = (double)value;
return !(double.IsNaN(v) || double.IsInfinity(v));
}
}), ValidateHelper.IsInRangeOfDouble);
/// <summary>
/// 当前值
@@ -128,7 +118,7 @@ namespace HandyControl.Controls
/// 最小改变值
/// </summary>
public static readonly DependencyProperty SmallChangeProperty = DependencyProperty.Register(
"SmallChange", typeof(double), typeof(InfoNumericUpDown), new PropertyMetadata(1.0), ValidateValueCallback);
"SmallChange", typeof(double), typeof(InfoNumericUpDown), new PropertyMetadata(1.0), ValidateHelper.IsInRangeOfDouble);
/// <summary>
/// 最小改变值
+15 -14
View File
@@ -1,15 +1,16 @@
<controls:InfoControl x:Class="HandyControl.Controls.InfoTextBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:controls="clr-namespace:HandyControl.Controls"
mc:Ignorable="d"
FontSize="14"
MinHeight="24"
Height="36"
MaxHeight="54"
d:DesignWidth="300">
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:controls="clr-namespace:HandyControl.Controls"
x:ClassModifier="internal"
mc:Ignorable="d"
FontSize="14"
MinHeight="24"
Height="36"
MaxHeight="54"
d:DesignWidth="300">
<controls:InfoControl.Resources>
<Storyboard x:Key="Storyboard1">
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Border.BorderBrush).(SolidColorBrush.Color)" Storyboard.TargetName="Border">
@@ -43,7 +44,7 @@
</Grid.RowDefinitions>
<StackPanel Name="StackPanelTitle" Grid.Row="1" HorizontalAlignment="Right" Orientation="Horizontal">
<TextBlock Visibility="{Binding IsNeedly,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl},Converter={StaticResource Boolean2VisibilityConverter}}" VerticalAlignment="Center" Margin="0,0,6,0" Text="*" Foreground="{DynamicResource DangerBrush}"></TextBlock>
<TextBlock Style="{StaticResource TextBlockDefault}" Visibility="{Binding Text,RelativeSource={RelativeSource Mode=Self},Converter={StaticResource String2VisibilityReConverter}}" Margin="0,0,10,0" Text="{Binding Title,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl}}"></TextBlock>
<TextBlock Style="{StaticResource TextBlockDefault}" Visibility="{Binding Text,RelativeSource={RelativeSource Mode=Self},Converter={StaticResource String2VisibilityConverter}}" Margin="0,0,10,0" Text="{Binding Title,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl}}"></TextBlock>
</StackPanel>
<TextBlock Margin="4,0,0,1" Grid.Row="1" Name="TextBlockError" Grid.Column="1" VerticalAlignment="Bottom" FontSize="12" Foreground="{DynamicResource DangerBrush}" Text="{Binding ErrorStr,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl}}"></TextBlock>
<Border Grid.Row="1" Name="Border" Background="White" Grid.Column="1" CornerRadius="{Binding CornerRadius,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl}}" BorderThickness="1" BorderBrush="Transparent">
@@ -52,9 +53,9 @@
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding PlaceHolder,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl}}" HorizontalAlignment="Left" Padding="10,0" FontSize="14" Visibility="{Binding Text,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl},Converter={StaticResource String2VisibilityConverter}}" VerticalAlignment="Center" Foreground="{DynamicResource ThirdlyTextBrush}"/>
<TextBlock Text="{Binding PlaceHolder,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl}}" HorizontalAlignment="Left" Padding="10,0" FontSize="14" Visibility="{Binding Text,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl},Converter={StaticResource String2VisibilityReConverter}}" VerticalAlignment="Center" Foreground="{DynamicResource ThirdlyTextBrush}"/>
<TextBox MaxLines="1" MaxLength="{Binding MaxLength,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl}}" HorizontalContentAlignment="{Binding HorizontalTextAlignment,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl}}" Grid.Column="0" TextChanged="InputBox_OnTextChanged" MouseLeave="InputBox_OnMouseLeave" MouseEnter="InputBox_OnMouseEnter" GotFocus="InputBox_OnGotFocus" LostFocus="InputBox_OnLostFocus" Name="MyTextBox" Margin="4,0" BorderThickness="0" VerticalContentAlignment="Center" Padding="{Binding TextPadding,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl}}" Text="{Binding Text,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl},UpdateSourceTrigger=PropertyChanged}" Background="{x:Null}"></TextBox>
<Button Padding="7" Visibility="{Binding Text,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl},Converter={StaticResource String2VisibilityReConverter}}" Focusable="True" Grid.Column="1" Name="ButtonClear" Click="ButtonClear_OnClick" Foreground="{DynamicResource ThirdlyTextBrush}" controls:IconElement.Geometry="{StaticResource DeleteFillCircleGeometry}" Style="{StaticResource ButtonIcon}" Width="36" HorizontalAlignment="Right"></Button>
<Button Padding="7" Visibility="{Binding Text,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl},Converter={StaticResource String2VisibilityConverter}}" Focusable="True" Grid.Column="1" Name="ButtonClear" Click="ButtonClear_OnClick" Foreground="{DynamicResource ThirdlyTextBrush}" controls:IconElement.Geometry="{StaticResource DeleteFillCircleGeometry}" Style="{StaticResource ButtonIcon}" Width="36" HorizontalAlignment="Right"></Button>
</Grid>
</Border>
</Grid>
@@ -7,7 +7,7 @@ namespace HandyControl.Controls
/// <summary>
/// InfoTextBox.xaml 的交互逻辑
/// </summary>
public partial class InfoTextBox
internal partial class InfoTextBox
{
/// <summary>
/// 可输入的最大字符数
+6 -2
View File
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Linq;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Markup;
@@ -50,6 +51,11 @@ namespace HandyControl.Controls
UniformGridMain.Children.Add(item);
index++;
}
if (list.FirstOrDefault() is StepItem stepItem)
{
stepItem.Status = false;
}
}
protected override void OnRender(DrawingContext drawingContext)
@@ -63,8 +69,6 @@ namespace HandyControl.Controls
ProgressBarBack.Maximum = colCount - 1;
}
public void Next()
{
StepIndex++;
+2 -2
View File
@@ -57,11 +57,11 @@ namespace HandyControl.Controls
{
if (Status == true)
{
Foreground = TryFindResource("PrimaryBrush") as Brush;
Foreground = TryFindResource("PrimaryTextBrush") as Brush;
}
else if (Status == false)
{
Foreground = TryFindResource("PrimaryTextBrush") as Brush;
Foreground = TryFindResource("PrimaryBrush") as Brush;
}
else
{
+625
View File
@@ -0,0 +1,625 @@
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Threading;
using HandyControl.Data;
namespace HandyControl.Controls
{
[TemplatePart(Name = ElementRoot, Type = typeof(Grid))]
[TemplatePart(Name = ElementTextBox, Type = typeof(WatermarkTextBox))]
[TemplatePart(Name = ElementButton, Type = typeof(Button))]
[TemplatePart(Name = ElementPopup, Type = typeof(Popup))]
[TemplatePart(Name = ElementClock, Type = typeof(Clock))]
public class TimePicker : Control
{
#region Constants
private const string ElementRoot = "PART_Root";
private const string ElementTextBox = "PART_TextBox";
private const string ElementButton = "PART_Button";
private const string ElementPopup = "PART_Popup";
private const string ElementClock = "PART_Clock";
#endregion Constants
#region Data
private Clock _clock;
private string _defaultText;
private ButtonBase _dropDownButton;
private Popup _popUp;
private bool _disablePopupReopen;
private WatermarkTextBox _textBox;
private IDictionary<DependencyProperty, bool> _isHandlerSuspended;
private DateTime? _originalSelectedTime;
#endregion Data
#region Public Events
public static readonly RoutedEvent SelectedTimeChangedEvent =
EventManager.RegisterRoutedEvent("SelectedTimeChanged", RoutingStrategy.Direct,
typeof(EventHandler<FunctionEventArgs<DateTime?>>), typeof(TimePicker));
public event EventHandler<FunctionEventArgs<DateTime?>> SelectedTimeChanged
{
add => AddHandler(SelectedTimeChangedEvent, value);
remove => RemoveHandler(SelectedTimeChangedEvent, value);
}
public event RoutedEventHandler ClockClosed;
public event RoutedEventHandler ClockOpened;
#endregion Public Events
static TimePicker()
{
EventManager.RegisterClassHandler(typeof(TimePicker), GotFocusEvent, new RoutedEventHandler(OnGotFocus));
KeyboardNavigation.TabNavigationProperty.OverrideMetadata(typeof(TimePicker), new FrameworkPropertyMetadata(KeyboardNavigationMode.Once));
KeyboardNavigation.IsTabStopProperty.OverrideMetadata(typeof(TimePicker), new FrameworkPropertyMetadata(false));
}
#region Public Properties
#region TimeFormat
public static readonly DependencyProperty TimeFormatProperty = DependencyProperty.Register(
"TimeFormat", typeof(string), typeof(TimePicker), new PropertyMetadata("HH:mm:ss"));
public string TimeFormat
{
get => (string)GetValue(TimeFormatProperty);
set => SetValue(TimeFormatProperty, value);
}
#endregion TimeFormat
#region ClockStyle
public Style ClockStyle
{
get => (Style)GetValue(ClockStyleProperty);
set => SetValue(ClockStyleProperty, value);
}
public static readonly DependencyProperty ClockStyleProperty = DependencyProperty.Register("ClockStyle", typeof(Style), typeof(TimePicker));
#endregion CalendarStyle
#region DisplayTime
public DateTime DisplayTime
{
get => (DateTime)GetValue(DisplayTimeProperty);
set => SetValue(DisplayTimeProperty, value);
}
public static readonly DependencyProperty DisplayTimeProperty =
DependencyProperty.Register(
"DisplayTime",
typeof(DateTime),
typeof(TimePicker),
new FrameworkPropertyMetadata(DateTime.Now, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, null, CoerceDisplayTime));
private static object CoerceDisplayTime(DependencyObject d, object value)
{
var dp = (TimePicker)d;
dp._clock.DisplayTime = (DateTime)value;
return dp._clock.DisplayTime;
}
#endregion DisplayTime
#region IsDropDownOpen
public bool IsDropDownOpen
{
get => (bool)GetValue(IsDropDownOpenProperty);
set => SetValue(IsDropDownOpenProperty, value);
}
public static readonly DependencyProperty IsDropDownOpenProperty =
DependencyProperty.Register(
"IsDropDownOpen",
typeof(bool),
typeof(TimePicker),
new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnIsDropDownOpenChanged, OnCoerceIsDropDownOpen));
private static object OnCoerceIsDropDownOpen(DependencyObject d, object baseValue) => d is TimePicker dp && !dp.IsEnabled ? false : baseValue;
private static void OnIsDropDownOpenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var dp = d as TimePicker;
var newValue = (bool)e.NewValue;
if (dp?._popUp != null && dp._popUp.IsOpen != newValue)
{
dp._popUp.IsOpen = newValue;
if (newValue)
{
dp._originalSelectedTime = dp.SelectedTime;
dp.Dispatcher.BeginInvoke(DispatcherPriority.Input, (Action)delegate
{
dp._clock.Focus();
});
}
}
}
#endregion IsDropDownOpen
#region SelectedTime
public DateTime? SelectedTime
{
get => (DateTime?)GetValue(SelectedTimeProperty);
set => SetValue(SelectedTimeProperty, value);
}
public static readonly DependencyProperty SelectedTimeProperty =
DependencyProperty.Register(
"SelectedTime",
typeof(DateTime?),
typeof(TimePicker),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, OnSelectedTimeChanged, CoerceSelectedTime));
private static void OnSelectedTimeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (!(d is TimePicker dp)) return;
if (dp.SelectedTime.HasValue)
{
var time = dp.SelectedTime.Value;
dp.SetTextInternal(dp.DateTimeToString(time));
}
dp.RaiseEvent(new FunctionEventArgs<DateTime?>(SelectedTimeChangedEvent, dp)
{
Info = dp.SelectedTime
});
}
private static object CoerceSelectedTime(DependencyObject d, object value)
{
var dp = (TimePicker)d;
dp._clock.SelectedTime = (DateTime?)value;
return dp._clock.SelectedTime;
}
#endregion SelectedDate
#region Text
public string Text
{
get => (string)GetValue(TextProperty);
set => SetValue(TextProperty, value);
}
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register(
"Text",
typeof(string),
typeof(TimePicker),
new FrameworkPropertyMetadata(string.Empty, OnTextChanged));
private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is TimePicker dp && !dp.IsHandlerSuspended(TextProperty))
{
if (e.NewValue is string newValue)
{
if (dp._textBox != null)
{
dp._textBox.Text = newValue;
}
else
{
dp._defaultText = newValue;
}
dp.SetSelectedTime();
}
else
{
dp.SetValueNoCallback(SelectedTimeProperty, null);
}
}
}
/// <summary>
/// Sets the local Text property without breaking bindings
/// </summary>
/// <param name="value"></param>
private void SetTextInternal(string value)
{
SetCurrentValue(TextProperty, value);
}
#endregion Text
#endregion Public Properties
#region Public Methods
public override void OnApplyTemplate()
{
if (_popUp != null)
{
_popUp.RemoveHandler(PreviewMouseLeftButtonDownEvent, new MouseButtonEventHandler(PopUp_PreviewMouseLeftButtonDown));
_popUp.Opened -= PopUp_Opened;
_popUp.Closed -= PopUp_Closed;
_popUp.Child = null;
}
if (_dropDownButton != null)
{
_dropDownButton.Click -= DropDownButton_Click;
_dropDownButton.RemoveHandler(MouseLeaveEvent, new MouseEventHandler(DropDownButton_MouseLeave));
}
if (_textBox != null)
{
_textBox.RemoveHandler(KeyDownEvent, new KeyEventHandler(TextBox_KeyDown));
_textBox.RemoveHandler(TextBoxBase.TextChangedEvent, new TextChangedEventHandler(TextBox_TextChanged));
_textBox.RemoveHandler(LostFocusEvent, new RoutedEventHandler(TextBox_LostFocus));
}
if (_clock != null)
{
_clock.RemoveHandler(Clock.SelectedTimeChangedEvent, new EventHandler<FunctionEventArgs<DateTime?>>(Clock_SelectedTimeChangedEvent));
_clock.Confirmed -= Clock_Confirmed;
}
base.OnApplyTemplate();
_clock = GetTemplateChild(ElementClock) as Clock;
_popUp = GetTemplateChild(ElementPopup) as Popup;
_dropDownButton = GetTemplateChild(ElementButton) as Button;
_textBox = GetTemplateChild(ElementTextBox) as WatermarkTextBox;
CheckNull();
_clock.ApplyTemplate();
_clock.AddHandler(Clock.SelectedTimeChangedEvent, new EventHandler<FunctionEventArgs<DateTime?>>(Clock_SelectedTimeChangedEvent));
_clock.Confirmed += Clock_Confirmed;
_popUp.AddHandler(PreviewMouseLeftButtonDownEvent, new MouseButtonEventHandler(PopUp_PreviewMouseLeftButtonDown));
_popUp.Opened += PopUp_Opened;
_popUp.Closed += PopUp_Closed;
_popUp.Child = _clock;
if (IsDropDownOpen)
{
_popUp.IsOpen = true;
}
_dropDownButton.Click += DropDownButton_Click;
_dropDownButton.AddHandler(MouseLeaveEvent, new MouseEventHandler(DropDownButton_MouseLeave), true);
if (SelectedTime == null)
{
_textBox.Text = DateTime.Now.ToString(TimeFormat);
}
_textBox.AddHandler(KeyDownEvent, new KeyEventHandler(TextBox_KeyDown), true);
_textBox.AddHandler(TextBoxBase.TextChangedEvent, new TextChangedEventHandler(TextBox_TextChanged), true);
_textBox.AddHandler(LostFocusEvent, new RoutedEventHandler(TextBox_LostFocus), true);
if (SelectedTime == null)
{
if (!string.IsNullOrEmpty(_defaultText))
{
_textBox.Text = _defaultText;
SetSelectedTime();
}
}
else
{
_textBox.Text = DateTimeToString((DateTime)SelectedTime);
}
if (_originalSelectedTime == null)
{
_originalSelectedTime = DateTime.Now;
}
SetCurrentValue(DisplayTimeProperty, _originalSelectedTime);
}
public override string ToString() => SelectedTime?.ToString(TimeFormat) ?? string.Empty;
#endregion
#region Protected Methods
protected virtual void OnClockClosed(RoutedEventArgs e)
{
var handler = ClockClosed;
handler?.Invoke(this, e);
}
protected virtual void OnClockOpened(RoutedEventArgs e)
{
var handler = ClockOpened;
handler?.Invoke(this, e);
}
#endregion Protected Methods
#region Private Methods
private void CheckNull()
{
if (_clock == null || _dropDownButton == null || _popUp == null || _textBox == null) throw new Exception();
}
private void TextBox_LostFocus(object sender, RoutedEventArgs e)
{
SetSelectedTime();
}
private void SetIsHandlerSuspended(DependencyProperty property, bool value)
{
if (value)
{
if (_isHandlerSuspended == null)
{
_isHandlerSuspended = new Dictionary<DependencyProperty, bool>(2);
}
_isHandlerSuspended[property] = true;
}
else
{
_isHandlerSuspended?.Remove(property);
}
}
private void SetValueNoCallback(DependencyProperty property, object value)
{
SetIsHandlerSuspended(property, true);
try
{
SetCurrentValue(property, value);
}
finally
{
SetIsHandlerSuspended(property, false);
}
}
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
SetValueNoCallback(TextProperty, _textBox.Text);
}
private bool ProcessTimePickerKey(KeyEventArgs e)
{
switch (e.Key)
{
case Key.System:
{
switch (e.SystemKey)
{
case Key.Down:
{
if ((Keyboard.Modifiers & ModifierKeys.Alt) == ModifierKeys.Alt)
{
TogglePopUp();
return true;
}
break;
}
}
break;
}
case Key.Enter:
{
SetSelectedTime();
return true;
}
}
return false;
}
private void TextBox_KeyDown(object sender, KeyEventArgs e)
{
e.Handled = ProcessTimePickerKey(e) || e.Handled;
}
private void DropDownButton_MouseLeave(object sender, MouseEventArgs e)
{
_disablePopupReopen = false;
}
private bool IsHandlerSuspended(DependencyProperty property)
{
return _isHandlerSuspended != null && _isHandlerSuspended.ContainsKey(property);
}
private void PopUp_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (sender is Popup popup && !popup.StaysOpen)
{
if (_dropDownButton?.InputHitTest(e.GetPosition(_dropDownButton)) != null)
{
_disablePopupReopen = true;
}
}
}
private void Clock_SelectedTimeChangedEvent(object sender, FunctionEventArgs<DateTime?> e) => SelectedTime = e.Info;
private void Clock_Confirmed() => TogglePopUp();
private void PopUp_Opened(object sender, EventArgs e)
{
if (!IsDropDownOpen)
{
SetCurrentValue(IsDropDownOpenProperty, BooleanBoxes.TrueBox);
}
_clock?.MoveFocus(new TraversalRequest(FocusNavigationDirection.First));
OnClockOpened(new RoutedEventArgs());
}
private void PopUp_Closed(object sender, EventArgs e)
{
if (IsDropDownOpen)
{
SetCurrentValue(IsDropDownOpenProperty, BooleanBoxes.FalseBox);
}
if (_clock.IsKeyboardFocusWithin)
{
MoveFocus(new TraversalRequest(FocusNavigationDirection.First));
}
OnClockClosed(new RoutedEventArgs());
}
private void DropDownButton_Click(object sender, RoutedEventArgs e) => TogglePopUp();
private void TogglePopUp()
{
if (IsDropDownOpen)
{
SetCurrentValue(IsDropDownOpenProperty, BooleanBoxes.FalseBox);
}
else
{
if (_disablePopupReopen)
{
_disablePopupReopen = false;
}
else
{
SetSelectedTime();
SetCurrentValue(IsDropDownOpenProperty, BooleanBoxes.TrueBox);
}
}
}
private void SafeSetText(string s)
{
if (string.Compare(Text, s, StringComparison.Ordinal) != 0)
{
SetCurrentValue(TextProperty, s);
}
}
private DateTime? ParseText(string text)
{
try
{
return DateTime.Parse(text);
}
catch
{
// ignored
}
return null;
}
private DateTime? SetTextBoxValue(string s)
{
if (string.IsNullOrEmpty(s))
{
SafeSetText(s);
return SelectedTime;
}
var d = ParseText(s);
if (d != null)
{
SafeSetText(DateTimeToString((DateTime)d));
return d;
}
if (SelectedTime != null)
{
var newtext = DateTimeToString((DateTime) SelectedTime);
SafeSetText(newtext);
return SelectedTime;
}
SafeSetText(DateTimeToString(DisplayTime));
return DisplayTime;
}
private void SetSelectedTime()
{
if (_textBox != null)
{
if (!string.IsNullOrEmpty(_textBox.Text))
{
var s = _textBox.Text;
if (SelectedTime != null)
{
var selectedTime = DateTimeToString(SelectedTime.Value);
if (string.Compare(selectedTime, s, StringComparison.Ordinal) == 0)
{
return;
}
}
var d = SetTextBoxValue(s);
if (!SelectedTime.Equals(d))
{
SetCurrentValue(SelectedTimeProperty, d);
SetCurrentValue(DisplayTimeProperty, d);
}
}
else
{
if (SelectedTime.HasValue)
{
SetCurrentValue(SelectedTimeProperty, null);
}
}
}
else
{
var d = SetTextBoxValue(_defaultText);
if (!SelectedTime.Equals(d))
{
SetCurrentValue(SelectedTimeProperty, d);
}
}
}
private string DateTimeToString(DateTime d) => d.ToString(TimeFormat);
private static void OnGotFocus(object sender, RoutedEventArgs e)
{
var picker = (TimePicker)sender;
if (!e.Handled && picker._textBox != null)
{
if (Equals(e.OriginalSource, picker))
{
picker._textBox.Focus();
e.Handled = true;
}
else if (Equals(e.OriginalSource, picker._textBox))
{
picker._textBox.SelectAll();
e.Handled = true;
}
}
}
#endregion Private Methods
}
}
+77
View File
@@ -0,0 +1,77 @@
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
namespace HandyControl.Controls
{
[TemplatePart(Name = ElementContentName, Type = typeof(ContentControl))]
public class WatermarkTextBox : TextBox
{
#region Constants
private const string ElementContentName = "PART_Watermark";
#endregion Constants
#region Data
private ContentControl _elementContent;
#endregion Data
#region Public Properties
#region Watermark
public static readonly DependencyProperty WatermarkProperty = DependencyProperty.Register(
"Watermark", typeof(object), typeof(WatermarkTextBox), new PropertyMetadata(default(object), OnWatermarkChanged));
private static void OnWatermarkChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var ctl = (WatermarkTextBox) d;
ctl.OnWatermarkChanged();
}
public object Watermark
{
get => GetValue(WatermarkProperty);
set => SetValue(WatermarkProperty, value);
}
#endregion Watermark
#endregion Public Properties
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
_elementContent = GetTemplateChild(ElementContentName) as ContentControl;
_elementContent?.SetBinding(ContentControl.ContentProperty, new Binding(WatermarkProperty.Name) {Source = this});
OnWatermarkChanged();
}
private void OnWatermarkChanged()
{
if (_elementContent == null) return;
if (Watermark is Control watermarkControl)
{
watermarkControl.IsTabStop = false;
watermarkControl.IsHitTestVisible = false;
}
}
protected override void OnGotFocus(RoutedEventArgs e)
{
base.OnGotFocus(e);
if (IsEnabled)
{
if (!string.IsNullOrEmpty(Text))
{
Select(0, Text.Length);
}
}
}
}
}
+13
View File
@@ -0,0 +1,13 @@
namespace HandyControl.Data
{
/// <summary>
/// 装箱后的布尔值(用于提高效率)
/// </summary>
internal static class BooleanBoxes
{
internal static object TrueBox = true;
internal static object FalseBox = false;
internal static object Box(bool value) => value ? TrueBox : FalseBox;
}
}
+5
View File
@@ -5,6 +5,11 @@ namespace HandyControl.Data
{
public class FunctionEventArgs<T> : RoutedEventArgs
{
public FunctionEventArgs(T info)
{
Info = info;
}
public FunctionEventArgs(RoutedEvent routedEvent, object source) : base(routedEvent, source)
{
}
+31
View File
@@ -37,12 +37,16 @@
<Compile Include="Controls\Attach\BackgroundSwitchElement.cs" />
<Compile Include="Controls\Attach\BorderElement.cs" />
<Compile Include="Controls\Attach\IconSwitchElement.cs" />
<Compile Include="Controls\Attach\InfoElement.cs" />
<Compile Include="Controls\Attach\StatusSwitchElement.cs" />
<Compile Include="Controls\Button\ContextMenuButton.cs" />
<Compile Include="Controls\Button\ContextMenuToggleButton.cs" />
<Compile Include="Controls\Carousel.xaml.cs">
<DependentUpon>Carousel.xaml</DependentUpon>
</Compile>
<Compile Include="Controls\CirclePanel.cs" />
<Compile Include="Controls\Clock.cs" />
<Compile Include="Controls\ClockRadioButton.cs" />
<Compile Include="Controls\ColorPicker.xaml.cs">
<DependentUpon>ColorPicker.xaml</DependentUpon>
</Compile>
@@ -78,7 +82,9 @@
<Compile Include="Controls\TimeBar\TimeBar.xaml.cs">
<DependentUpon>TimeBar.xaml</DependentUpon>
</Compile>
<Compile Include="Controls\TimePicker.cs" />
<Compile Include="Controls\TransitioningContentControl.cs" />
<Compile Include="Controls\WatermarkTextBox.cs" />
<Compile Include="Controls\Window\ImageBrowser.xaml.cs">
<DependentUpon>ImageBrowser.xaml</DependentUpon>
</Compile>
@@ -86,6 +92,7 @@
<DependentUpon>PopupWindow.xaml</DependentUpon>
</Compile>
<Compile Include="Controls\Window\WindowBorderless.cs" />
<Compile Include="Data\BooleanBoxes.cs" />
<Compile Include="Data\ColorRange.cs" />
<Compile Include="Data\Enum\IpType.cs" />
<Compile Include="Data\Enum\TextType.cs" />
@@ -98,6 +105,7 @@
<Compile Include="Interactivity\BehaviorCollection.cs" />
<Compile Include="Interactivity\ControlCommands.cs" />
<Compile Include="Interactivity\DefaultTriggerAttribute.cs" />
<Compile Include="Interactivity\EventToCommand.cs" />
<Compile Include="Interactivity\EventTrigger.cs" />
<Compile Include="Interactivity\EventTriggerBase!1.cs" />
<Compile Include="Interactivity\EventTriggerBase.cs" />
@@ -107,12 +115,14 @@
<Compile Include="Interactivity\FluidMoveBehaviorBase.cs" />
<Compile Include="Interactivity\FluidMoveScope.cs" />
<Compile Include="Interactivity\IAttachedObject.cs" />
<Compile Include="Interactivity\IEventArgsConverter.cs" />
<Compile Include="Interactivity\Interaction.cs" />
<Compile Include="Interactivity\InvokeCommandAction.cs" />
<Compile Include="Interactivity\MouseDragElementBehavior.cs" />
<Compile Include="Interactivity\NameResolvedEventArgs.cs" />
<Compile Include="Interactivity\NameResolver.cs" />
<Compile Include="Interactivity\PreviewInvokeEventArgs.cs" />
<Compile Include="Interactivity\RoutedEventTrigger.cs" />
<Compile Include="Interactivity\TagType.cs" />
<Compile Include="Interactivity\TransitionEffect.cs" />
<Compile Include="Interactivity\TriggerAction!1.cs" />
@@ -153,6 +163,7 @@
<Compile Include="Tools\RegularJudgment.cs" />
<Compile Include="Tools\RegularPatterns.cs" />
<Compile Include="Tools\ResourceHelper.cs" />
<Compile Include="Tools\ValidateHelper.cs" />
<Compile Include="Tools\VisualStates.cs" />
</ItemGroup>
<ItemGroup>
@@ -295,6 +306,14 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Themes\Styles\Calendar.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Themes\Styles\Clock.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Themes\Styles\ContentControl.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
@@ -303,6 +322,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Themes\Styles\DatePicker.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Themes\Styles\Expander.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
@@ -343,6 +366,14 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Themes\Styles\TextBox.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Themes\Styles\TimePicker.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Themes\Styles\TreeView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
@@ -31,5 +31,40 @@ namespace HandyControl.Interactivity
/// 下一个
/// </summary>
public static RoutedCommand Next { get; } = new RoutedCommand("Next", typeof(ControlCommands));
/// <summary>
/// 上午
/// </summary>
public static RoutedCommand Am { get; } = new RoutedCommand("Am", typeof(ControlCommands));
/// <summary>
/// 下午
/// </summary>
public static RoutedCommand Pm { get; } = new RoutedCommand("Pm", typeof(ControlCommands));
/// <summary>
/// 确认
/// </summary>
public static RoutedCommand Sure { get; } = new RoutedCommand("Sure", typeof(ControlCommands));
/// <summary>
/// 小时改变
/// </summary>
public static RoutedCommand HourChange { get; } = new RoutedCommand("HourChange", typeof(ControlCommands));
/// <summary>
/// 分钟改变
/// </summary>
public static RoutedCommand MinuteChange { get; } = new RoutedCommand("MinuteChange", typeof(ControlCommands));
/// <summary>
/// 秒改变
/// </summary>
public static RoutedCommand SecondChange { get; } = new RoutedCommand("SecondChange", typeof(ControlCommands));
/// <summary>
/// 鼠标移动
/// </summary>
public static RoutedCommand MouseMove { get; } = new RoutedCommand("MouseMove", typeof(ControlCommands));
}
}
@@ -0,0 +1,194 @@
/*refrence from https://github.com/lbugnion/mvvmlight*/
//The MIT License(MIT)
//Copyright(c) 2009 - 2018 Laurent Bugnion
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//SOFTWARE.
using System;
using System.Windows;
using System.Windows.Input;
namespace HandyControl.Interactivity
{
public class EventToCommand : TriggerAction<DependencyObject>
{
public const string EventArgsConverterParameterPropertyName = "EventArgsConverterParameter";
public const string AlwaysInvokeCommandPropertyName = "AlwaysInvokeCommand";
public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.Register(
nameof(CommandParameter), typeof(object), typeof(EventToCommand), new PropertyMetadata(null,
(s, e) =>
{
var eventToCommand = s as EventToCommand;
if (eventToCommand?.AssociatedObject == null)
return;
eventToCommand.EnableDisableElement();
}));
public static readonly DependencyProperty CommandProperty =
DependencyProperty.Register(nameof(Command), typeof(ICommand), typeof(EventToCommand),
new PropertyMetadata(null, (s, e) => OnCommandChanged(s as EventToCommand, e)));
public static readonly DependencyProperty MustToggleIsEnabledProperty = DependencyProperty.Register(
nameof(MustToggleIsEnabled), typeof(bool), typeof(EventToCommand), new PropertyMetadata(false,
(s, e) =>
{
var eventToCommand = s as EventToCommand;
if (eventToCommand?.AssociatedObject == null)
return;
eventToCommand.EnableDisableElement();
}));
public static readonly DependencyProperty EventArgsConverterParameterProperty =
DependencyProperty.Register(nameof(EventArgsConverterParameter), typeof(object),
typeof(EventToCommand), new PropertyMetadata(null));
public static readonly DependencyProperty AlwaysInvokeCommandProperty =
DependencyProperty.Register(nameof(AlwaysInvokeCommand), typeof(bool), typeof(EventToCommand),
new PropertyMetadata(false));
private object _commandParameterValue;
private bool? _mustToggleValue;
public ICommand Command
{
get => (ICommand) GetValue(CommandProperty);
set => SetValue(CommandProperty, value);
}
public object CommandParameter
{
get => GetValue(CommandParameterProperty);
set => SetValue(CommandParameterProperty, value);
}
public object CommandParameterValue
{
get => _commandParameterValue ?? CommandParameter;
set
{
_commandParameterValue = value;
EnableDisableElement();
}
}
public bool MustToggleIsEnabled
{
get => (bool) GetValue(MustToggleIsEnabledProperty);
set => SetValue(MustToggleIsEnabledProperty, value);
}
public bool MustToggleIsEnabledValue
{
get
{
if (_mustToggleValue.HasValue)
return _mustToggleValue.Value;
return MustToggleIsEnabled;
}
set
{
_mustToggleValue = value;
EnableDisableElement();
}
}
public bool PassEventArgsToCommand { get; set; }
public IEventArgsConverter EventArgsConverter { get; set; }
public object EventArgsConverterParameter
{
get => GetValue(EventArgsConverterParameterProperty);
set => SetValue(EventArgsConverterParameterProperty, value);
}
public bool AlwaysInvokeCommand
{
get => (bool) GetValue(AlwaysInvokeCommandProperty);
set => SetValue(AlwaysInvokeCommandProperty, value);
}
protected override void OnAttached()
{
base.OnAttached();
EnableDisableElement();
}
private FrameworkElement GetAssociatedObject() => AssociatedObject as FrameworkElement;
private ICommand GetCommand() => Command;
public void Invoke() => Invoke(null);
protected override void Invoke(object parameter)
{
if (AssociatedElementIsDisabled() && !AlwaysInvokeCommand)
return;
var command = GetCommand();
var parameter1 = CommandParameterValue;
if (parameter1 == null && PassEventArgsToCommand)
parameter1 = EventArgsConverter == null
? parameter
: EventArgsConverter.Convert(parameter, EventArgsConverterParameter);
if (command == null || !command.CanExecute(parameter1))
return;
command.Execute(parameter1);
}
private static void OnCommandChanged(EventToCommand element, DependencyPropertyChangedEventArgs e)
{
if (element == null)
return;
if (e.OldValue != null)
((ICommand) e.OldValue).CanExecuteChanged -= element.OnCommandCanExecuteChanged;
var newValue = (ICommand) e.NewValue;
if (newValue != null)
newValue.CanExecuteChanged += element.OnCommandCanExecuteChanged;
element.EnableDisableElement();
}
private bool AssociatedElementIsDisabled()
{
var associatedObject = GetAssociatedObject();
if (AssociatedObject == null)
return true;
if (associatedObject != null)
return !associatedObject.IsEnabled;
return false;
}
private void EnableDisableElement()
{
var associatedObject = GetAssociatedObject();
if (associatedObject == null)
return;
var command = GetCommand();
if (!MustToggleIsEnabledValue || command == null)
return;
associatedObject.IsEnabled = command.CanExecute(CommandParameterValue);
}
private void OnCommandCanExecuteChanged(object sender, EventArgs e) => EnableDisableElement();
}
}
@@ -0,0 +1,31 @@
/*refrence from https://github.com/lbugnion/mvvmlight*/
//The MIT License(MIT)
//Copyright(c) 2009 - 2018 Laurent Bugnion
//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:
//The above copyright notice and this permission notice shall be included in all
//copies or substantial portions of the Software.
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//SOFTWARE.
namespace HandyControl.Interactivity
{
public interface IEventArgsConverter
{
object Convert(object value, object parameter);
}
}
@@ -0,0 +1,29 @@
using System;
using System.Windows;
namespace HandyControl.Interactivity
{
public class RoutedEventTrigger : EventTriggerBase<DependencyObject>
{
public RoutedEvent RoutedEvent { get; set; }
protected override void OnAttached()
{
var behavior = AssociatedObject as Behavior;
var associatedElement = AssociatedObject as FrameworkElement;
if (behavior != null) associatedElement = ((IAttachedObject)behavior).AssociatedObject as FrameworkElement;
if (associatedElement == null) throw new ArgumentException();
if (RoutedEvent != null) associatedElement.AddHandler(RoutedEvent, new RoutedEventHandler(OnRoutedEvent));
}
private void OnRoutedEvent(object sender, RoutedEventArgs args)
{
OnEvent(args);
}
protected override string GetEventName()
{
return RoutedEvent.Name;
}
}
}
+3 -3
View File
@@ -6,9 +6,9 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("HandyControl")]
[assembly: AssemblyCopyright("Copyright © 纳边 2018")]
[assembly: AssemblyCopyright("Copyright © NaBian 2018")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: AssemblyVersion("1.2.2.1")]
[assembly: AssemblyFileVersion("1.2.2.1")]
[assembly: AssemblyVersion("1.3.0.0")]
[assembly: AssemblyFileVersion("1.3.0.0")]
+18
View File
@@ -60,6 +60,15 @@ namespace HandyControl.Properties.Langs {
}
}
/// <summary>
/// 查找类似 上午 的本地化字符串。
/// </summary>
public static string Am {
get {
return ResourceManager.GetString("Am", resourceCulture);
}
}
/// <summary>
/// 查找类似 取消 的本地化字符串。
/// </summary>
@@ -195,6 +204,15 @@ namespace HandyControl.Properties.Langs {
}
}
/// <summary>
/// 查找类似 下午 的本地化字符串。
/// </summary>
public static string Pm {
get {
return ResourceManager.GetString("Pm", resourceCulture);
}
}
/// <summary>
/// 查找类似 PNG图片 的本地化字符串。
/// </summary>
@@ -177,4 +177,10 @@
<data name="CloseOther" xml:space="preserve">
<value>Close other</value>
</data>
<data name="Am" xml:space="preserve">
<value>Am</value>
</data>
<data name="Pm" xml:space="preserve">
<value>Pm</value>
</data>
</root>
+6
View File
@@ -157,4 +157,10 @@
<data name="CloseOther" xml:space="preserve">
<value>关闭其他</value>
</data>
<data name="Am" xml:space="preserve">
<value>上午</value>
</data>
<data name="Pm" xml:space="preserve">
<value>下午</value>
</data>
</root>
+1 -1
View File
@@ -3,7 +3,7 @@
xmlns:controls="clr-namespace:HandyControl.Controls">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Base/ButtonBaseStyle.xaml"></ResourceDictionary>
<ResourceDictionary Source="Base/ButtonBaseStyle.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Style BasedOn="{StaticResource ButtonBaseStyle}" TargetType="{x:Type Button}">
+241
View File
@@ -0,0 +1,241 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:HandyControl.Controls">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="../Basic/Geometries.xaml"/>
<ResourceDictionary Source="Button.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Style x:Key="CalendarButtonStyle" TargetType="{x:Type CalendarButton}">
<Setter Property="MinWidth" Value="10"/>
<Setter Property="MinHeight" Value="10"/>
<Setter Property="FontSize" Value="12"/>
<Setter Property="Width" Value="40"/>
<Setter Property="Height" Value="32"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type CalendarButton}">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="SelectionStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="Unselected"/>
<VisualState x:Name="Selected">
<Storyboard>
<DoubleAnimation Duration="0:0:.2" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="SelectedBackground"/>
<ColorAnimation Duration="0" To="#FFFFFFFF" Storyboard.TargetProperty="(TextElement.Foreground).(SolidColorBrush.Color)" Storyboard.TargetName="NormalText"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="ActiveStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="Active"/>
<VisualState x:Name="Inactive">
<Storyboard>
<ColorAnimation Duration="0" To="{DynamicResource ThirdlyTextColor}" Storyboard.TargetProperty="(TextElement.Foreground).(SolidColorBrush.Color)" Storyboard.TargetName="NormalText"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Rectangle x:Name="SelectedBackground" Fill="{DynamicResource DangerBrush}" Opacity="0" RadiusY="16" RadiusX="16"/>
<Rectangle x:Name="Background" Fill="{TemplateBinding Background}" Opacity="0" RadiusY="16" RadiusX="16"/>
<ContentPresenter x:Name="NormalText" TextElement.Foreground="#212121" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
<Rectangle x:Name="CalendarButtonFocusVisual" IsHitTestVisible="false" RadiusY="16" RadiusX="16" Stroke="{DynamicResource PrimaryBrush}" Visibility="Collapsed"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsFocused" Value="True">
<Setter Property="Visibility" TargetName="CalendarButtonFocusVisual" Value="Visible"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="CalendarDayButtonStyle" TargetType="{x:Type CalendarDayButton}">
<Setter Property="MinWidth" Value="10"/>
<Setter Property="MinHeight" Value="10"/>
<Setter Property="FontSize" Value="12"/>
<Setter Property="Width" Value="32"/>
<Setter Property="Height" Value="32"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type CalendarDayButton}">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:0.1"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="Normal"/>
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation Duration="0" To=".35" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="NormalText"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="SelectionStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="Unselected"/>
<VisualState x:Name="Selected">
<Storyboard>
<DoubleAnimation Duration="0:0:.2" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="SelectedBackground"/>
<ColorAnimation Duration="0" To="#FFFFFFFF" Storyboard.TargetProperty="(TextElement.Foreground).(SolidColorBrush.Color)" Storyboard.TargetName="NormalText"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="ActiveStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="Active"/>
<VisualState x:Name="Inactive">
<Storyboard>
<ColorAnimation Duration="0" To="{DynamicResource ThirdlyTextColor}" Storyboard.TargetProperty="(TextElement.Foreground).(SolidColorBrush.Color)" Storyboard.TargetName="NormalText"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="DayStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="RegularDay"/>
<VisualState x:Name="Today">
<Storyboard>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="TodayBackground"/>
<ColorAnimation Duration="0" To="#FFFFFFFF" Storyboard.TargetProperty="(TextElement.Foreground).(SolidColorBrush.Color)" Storyboard.TargetName="NormalText"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Rectangle RadiusX="16" RadiusY="16" x:Name="TodayBackground" Fill="{DynamicResource DangerBrush}" Opacity="0"/>
<Rectangle x:Name="SelectedBackground" Fill="{DynamicResource PrimaryBrush}" Opacity="0" RadiusY="16" RadiusX="16"/>
<ContentPresenter x:Name="NormalText" TextElement.Foreground="#212121" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type CalendarItem}">
<Setter Property="Margin" Value="0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type CalendarItem}">
<ControlTemplate.Resources>
<DataTemplate x:Key="{x:Static CalendarItem.DayTitleTemplateResourceKey}">
<TextBlock Foreground="#FF333333" FontWeight="Bold" FontSize="12" HorizontalAlignment="Center" Margin="0,6,0,6" Text="{Binding}" VerticalAlignment="Center"/>
</DataTemplate>
</ControlTemplate.Resources>
<Grid x:Name="PART_Root">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PART_DisabledVisual"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}">
<Border BorderBrush="#FFFFFFFF">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Border Background="{DynamicResource PrimaryBrush}" Grid.ColumnSpan="3"/>
<Button x:Name="PART_PreviousButton" Width="50" HorizontalAlignment="Left" Grid.Column="0" Height="50" Padding="16" Focusable="False" Grid.Row="0" Style="{StaticResource ButtonIcon}" controls:IconElement.Geometry="{StaticResource LeftGeometry}"/>
<Button x:Name="PART_HeaderButton" Foreground="White" Grid.Column="1" FontWeight="Bold" FontSize="16" HorizontalAlignment="Center" Grid.Row="0" Style="{StaticResource ButtonCustom}"/>
<Button x:Name="PART_NextButton" Width="50" HorizontalAlignment="Right" Height="50" Padding="16" Grid.Column="2" Focusable="False" Grid.Row="0" Style="{StaticResource ButtonIcon}" controls:IconElement.Geometry="{StaticResource RightGeometry}"/>
<Grid Width="240" Height="240" x:Name="PART_MonthView" Margin="10" Grid.ColumnSpan="3" Grid.Column="0" HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Row="1" Visibility="Visible">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
</Grid>
<Grid Width="240" Height="240" x:Name="PART_YearView" Margin="10" Grid.ColumnSpan="3" Grid.Column="0" HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Row="1" Visibility="Hidden">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
</Grid>
</Grid>
</Border>
</Border>
</Grid>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding DisplayMode, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Calendar}}}" Value="Year">
<Setter Property="Visibility" TargetName="PART_MonthView" Value="Hidden"/>
<Setter Property="Visibility" TargetName="PART_YearView" Value="Visible"/>
</DataTrigger>
<DataTrigger Binding="{Binding DisplayMode, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Calendar}}}" Value="Decade">
<Setter Property="Visibility" TargetName="PART_MonthView" Value="Hidden"/>
<Setter Property="Visibility" TargetName="PART_YearView" Value="Visible"/>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="CalendarBaseStyle" TargetType="{x:Type Calendar}">
<Setter Property="Foreground" Value="White"/>
<Setter Property="Background" Value="White"/>
<Setter Property="BorderBrush" Value="{DynamicResource BorderBrush}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="CalendarDayButtonStyle" Value="{StaticResource CalendarDayButtonStyle}"/>
<Setter Property="CalendarButtonStyle" Value="{StaticResource CalendarButtonStyle}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Calendar}">
<StackPanel x:Name="PART_Root" HorizontalAlignment="Center">
<CalendarItem x:Name="PART_CalendarItem" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}"/>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type Calendar}" BasedOn="{StaticResource CalendarBaseStyle}"/>
</ResourceDictionary>
+105
View File
@@ -0,0 +1,105 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:langs="clr-namespace:HandyControl.Properties.Langs"
xmlns:controls="clr-namespace:HandyControl.Controls">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="../Basic/Effects.xaml"/>
<ResourceDictionary Source="../Basic/Converters.xaml"/>
<ResourceDictionary Source="Button.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Style x:Key="ClockRadioButtonStyle" TargetType="controls:ClockRadioButton">
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="Foreground" Value="{DynamicResource PrimaryTextBrush}"/>
<Setter Property="Focusable" Value="False"/>
<Setter Property="Width" Value="28"/>
<Setter Property="Height" Value="28"/>
<Setter Property="Background" Value="{DynamicResource DangerBrush}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="controls:ClockRadioButton">
<ControlTemplate.Resources>
<Storyboard x:Key="Storyboard1">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Storyboard.TargetName="optionMark">
<EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="Storyboard2">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Storyboard.TargetName="optionMark">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</ControlTemplate.Resources>
<Grid x:Name="templateRoot" Background="Transparent" SnapsToDevicePixels="True">
<Ellipse x:Name="optionMark" Fill="{TemplateBinding Background}" MinWidth="6" MinHeight="6" Opacity="0"/>
<ContentPresenter x:Name="contentPresenter" Focusable="False" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="true">
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource Storyboard1}"></BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource Storyboard2}"></BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Foreground" Value="{DynamicResource TextIconBrush}"/>
</Trigger>
</Style.Triggers>
</Style>
<Style TargetType="controls:Clock">
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="BorderBrush" Value="{DynamicResource BorderBrush}"/>
<Setter Property="Width" Value="210"/>
<Setter Property="Height" Value="290"/>
<Setter Property="VerticalAlignment" Value="Top"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="ClockRadioButtonStyle" Value="{StaticResource ClockRadioButtonStyle}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="controls:Clock">
<Border BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Border Background="{DynamicResource PrimaryBrush}" Name="PART_BorderTitle">
<TextBlock x:Name="PART_TimeStr" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="30" Foreground="White"></TextBlock>
</Border>
<Border Grid.Row="1" Background="White">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Canvas Grid.ColumnSpan="3" Margin="0,16,0,0" VerticalAlignment="Top" Name="PART_Canvas" Width="178" Height="178">
<Border Background="{DynamicResource DarkDefaultBrush}" Width="178" Height="178" CornerRadius="89"/>
<controls:CirclePanel Diameter="130" x:Name="PART_PanelNum" KeepVertical="True" Margin="24,24,0,0" OffsetAngle="-60"/>
<Border Focusable="False" Name="PART_BorderClock" Background="{DynamicResource PrimaryBrush}" RenderTransformOrigin="0.5,1" Height="63" Width="2" Canvas.Left="88" Canvas.Top="26"/>
<Ellipse Fill="White" Width="8" Height="8" StrokeThickness="2" Stroke="{DynamicResource PrimaryBrush}" Canvas.Top="85" Canvas.Left="85"></Ellipse>
</Canvas>
<controls:ClockRadioButton Background="{DynamicResource PrimaryBrush}" Grid.Column="0" x:Name="PART_ButtonAm" IsChecked="True" Height="30" Width="30" HorizontalAlignment="Left" VerticalAlignment="Bottom" Margin="16,0,0,16" Content="{x:Static langs:Lang.Am}" Style="{StaticResource ClockRadioButtonStyle}"></controls:ClockRadioButton>
<controls:ClockRadioButton Background="{DynamicResource PrimaryBrush}" Grid.Column="2" x:Name="PART_ButtonPm" Height="30" Width="30" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="0,0,16,16" Content="{x:Static langs:Lang.Pm}" Style="{DynamicResource ClockRadioButtonStyle}"></controls:ClockRadioButton>
<Button Grid.Column="1" Visibility="{TemplateBinding ShowConfirmButton,Converter={StaticResource Boolean2VisibilityConverter}}" Name="PART_ButtonConfirm" Content="{x:Static langs:Lang.Confirm}" Foreground="{DynamicResource PrimaryBrush}" HorizontalAlignment="Center" Margin="0,0,0,19" Height="24" Width="60" VerticalAlignment="Bottom" Background="Transparent" Style="{StaticResource ButtonCustom}"/>
</Grid>
</Border>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
@@ -0,0 +1,62 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:HandyControl.Controls">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="../Basic/Geometries.xaml"/>
<ResourceDictionary Source="../Basic/Converters.xaml"/>
<ResourceDictionary Source="Calendar.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Style x:Key="DatePickerTextBoxStyle" TargetType="{x:Type DatePickerTextBox}">
<Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst"/>
<Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DatePickerTextBox}">
<Grid x:Name="WatermarkContent" Margin="10,0" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
<Border x:Name="ContentElement"/>
<Border x:Name="watermark_decorator">
<ContentControl x:Name="PART_Watermark" Focusable="False" IsHitTestVisible="False" Visibility="{TemplateBinding Text,Converter={StaticResource String2VisibilityReConverter}}" Padding="0"/>
</Border>
<ScrollViewer x:Name="PART_ContentHost" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="0" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type DatePicker}">
<Setter Property="Foreground" Value="{DynamicResource PrimaryTextBrush}"/>
<Setter Property="CalendarStyle" Value="{StaticResource CalendarBaseStyle}"/>
<Setter Property="controls:BorderElement.CornerRadius" Value="4"/>
<Setter Property="IsTodayHighlighted" Value="True"/>
<Setter Property="SelectedDateFormat" Value="Short"/>
<Setter Property="Background" Value="{DynamicResource DefaultBrush}"/>
<Setter Property="BorderBrush" Value="{DynamicResource BorderBrush}"/>
<Setter Property="Width" Value="240"/>
<Setter Property="Height" Value="30"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DatePicker}">
<Border x:Name="templateRoot" CornerRadius="{Binding Path=(controls:BorderElement.CornerRadius),RelativeSource={RelativeSource TemplatedParent}}" BorderBrush="{DynamicResource BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}">
<Grid x:Name="PART_Root" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="30"/>
</Grid.ColumnDefinitions>
<Button Style="{StaticResource ButtonIcon}" Padding="7" controls:IconElement.Geometry="{StaticResource CalendarGeometry}" x:Name="PART_Button" Grid.Column="1" Foreground="{DynamicResource ThirdlyTextBrush}" Focusable="False" Grid.Row="0"/>
<DatePickerTextBox x:Name="PART_TextBox" Grid.Column="0" Focusable="{TemplateBinding Focusable}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" Grid.Row="0" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" Style="{DynamicResource DatePickerTextBoxStyle}"/>
<Popup Grid.Column="0" x:Name="PART_Popup" PopupAnimation="Fade" AllowsTransparency="True" Placement="Bottom" PlacementTarget="{Binding ElementName=PART_TextBox}" StaysOpen="False"/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
+5 -2
View File
@@ -13,7 +13,7 @@
<ResourceDictionary Source="ProgressBar.xaml"/>
<ResourceDictionary Source="ScrollViewer.xaml"/>
<ResourceDictionary Source="Slider.xaml"/>
<!--<ResourceDictionary Source="Clock.xaml"/>-->
<ResourceDictionary Source="Clock.xaml"/>
<ResourceDictionary Source="TreeView.xaml"/>
<!--<ResourceDictionary Source="DataGrid.xaml"/>-->
<!--<ResourceDictionary Source="GroupBox.xaml"/>-->
@@ -27,7 +27,10 @@
<!--<ResourceDictionary Source="ToolTip.xaml"/>-->
<!--<ResourceDictionary Source="InfoBrief.xaml"/>-->
<ResourceDictionary Source="Expander.xaml"/>
<!--<ResourceDictionary Source="TextBox.xaml"/>-->
<ResourceDictionary Source="TextBox.xaml"/>
<ResourceDictionary Source="Calendar.xaml"/>
<ResourceDictionary Source="DatePicker.xaml"/>
<ResourceDictionary Source="TimePicker.xaml"/>
<ResourceDictionary Source="ContentControl.xaml"/>
</ResourceDictionary.MergedDictionaries>
+30
View File
@@ -0,0 +1,30 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:HandyControl.Controls">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="../Basic/Converters.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Style x:Key="WatermarkTextBoxStyle" TargetType="controls:WatermarkTextBox">
<Setter Property="ScrollViewer.PanningMode" Value="VerticalFirst"/>
<Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="controls:WatermarkTextBox">
<Grid x:Name="WatermarkContent" Margin="10,0" VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
<Border x:Name="ContentElement"/>
<Border x:Name="watermark_decorator">
<ContentControl x:Name="PART_Watermark" Focusable="False" IsHitTestVisible="False" Visibility="{TemplateBinding Text,Converter={StaticResource String2VisibilityReConverter}}" Padding="0"/>
</Border>
<ScrollViewer x:Name="PART_ContentHost" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="0" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style BasedOn="{StaticResource WatermarkTextBoxStyle}" TargetType="controls:WatermarkTextBox"/>
</ResourceDictionary>
@@ -0,0 +1,41 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:HandyControl.Controls">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="../Basic/Geometries.xaml"/>
<ResourceDictionary Source="Button.xaml"/>
</ResourceDictionary.MergedDictionaries>
<Style TargetType="{x:Type controls:TimePicker}">
<Setter Property="Foreground" Value="{DynamicResource PrimaryTextBrush}"/>
<Setter Property="controls:BorderElement.CornerRadius" Value="4"/>
<Setter Property="Background" Value="{DynamicResource DefaultBrush}"/>
<Setter Property="BorderBrush" Value="{DynamicResource BorderBrush}"/>
<Setter Property="Width" Value="240"/>
<Setter Property="Height" Value="30"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type controls:TimePicker}">
<Border x:Name="templateRoot" CornerRadius="{Binding Path=(controls:BorderElement.CornerRadius),RelativeSource={RelativeSource TemplatedParent}}" BorderBrush="{DynamicResource BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}">
<Grid x:Name="PART_Root" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="30"/>
</Grid.ColumnDefinitions>
<Button Style="{StaticResource ButtonIcon}" Padding="7" controls:IconElement.Geometry="{StaticResource ClockGeometry}" x:Name="PART_Button" Grid.Column="1" Foreground="{DynamicResource ThirdlyTextBrush}" Focusable="False" Grid.Row="0"/>
<controls:WatermarkTextBox x:Name="PART_TextBox" HorizontalAlignment="Stretch" Grid.Column="0" Focusable="{TemplateBinding Focusable}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" Grid.Row="0" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
<Popup Grid.Column="0" x:Name="PART_Popup" PopupAnimation="Fade" Placement="Bottom" PlacementTarget="{Binding ElementName=PART_TextBox}" StaysOpen="False">
<controls:Clock x:Name="PART_Clock" ShowConfirmButton="True"/>
</Popup>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
+8
View File
@@ -113,5 +113,13 @@ namespace HandyControl.Tools
}
return new Rect(x, y, width, height);
}
/// <summary>
/// 计算两点的连线和x轴的夹角
/// </summary>
/// <param name="center"></param>
/// <param name="p"></param>
/// <returns></returns>
public static double CalAngle(Point center, Point p) => Math.Atan2(p.Y - center.Y, p.X - center.X) * 180 / Math.PI;
}
}
@@ -9,12 +9,12 @@ namespace HandyControl.Tools.Converter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return string.IsNullOrEmpty((string)value) ? Visibility.Visible : Visibility.Collapsed;
return string.IsNullOrEmpty((string)value) ? Visibility.Collapsed : Visibility.Visible;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return value != null && (Visibility)value == Visibility.Visible;
return value != null && (Visibility)value == Visibility.Collapsed;
}
}
}
@@ -9,12 +9,12 @@ namespace HandyControl.Tools.Converter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return string.IsNullOrEmpty((string)value) ? Visibility.Collapsed : Visibility.Visible;
return string.IsNullOrEmpty((string)value) ? Visibility.Visible : Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return value != null && (Visibility)value == Visibility.Visible;
return value != null && (Visibility)value == Visibility.Collapsed;
}
}
}
+19
View File
@@ -0,0 +1,19 @@
namespace HandyControl.Tools
{
/// <summary>
/// 验证帮助类
/// </summary>
internal class ValidateHelper
{
/// <summary>
/// 是否在浮点数范围内
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
internal static bool IsInRangeOfDouble(object value)
{
var v = (double)value;
return !(double.IsNaN(v) || double.IsInfinity(v));
}
}
}
+8
View File
@@ -22,6 +22,10 @@
public static readonly string StepBarDemoCtl = nameof(StepBarDemoCtl);
public static readonly string ClockDemoCtl = nameof(ClockDemoCtl);
public static readonly string TimePickerDemoCtl = nameof(TimePickerDemoCtl);
public static readonly string ButtonDemoCtl = nameof(ButtonDemoCtl);
public static readonly string ToggleButtonDemoCtl = nameof(ToggleButtonDemoCtl);
@@ -32,6 +36,10 @@
public static readonly string TabControlDemoCtl = nameof(TabControlDemoCtl);
public static readonly string CalendarDemoCtl = nameof(CalendarDemoCtl);
public static readonly string DatePickerDemoCtl = nameof(DatePickerDemoCtl);
public static readonly string LoadShowContent = nameof(LoadShowContent);
}
}
+6 -2
View File
@@ -13,7 +13,9 @@ var controlList = new List<string>
"TimeBarDemoCtl",
"PaginationDemoCtl",
"AnimationPathDemoCtl",
"StepBarDemoCtl"
"StepBarDemoCtl",
"ClockDemoCtl",
"TimePickerDemoCtl"
};
var styleList = new List<string>
{
@@ -21,7 +23,9 @@ var styleList = new List<string>
"ToggleButtonDemoCtl",
"ExpanderDemoCtl",
"ProgressBarDemoCtl",
"TabControlDemoCtl"
"TabControlDemoCtl",
"CalendarDemoCtl",
"DatePickerDemoCtl"
};
#>
namespace HandyControlDemo.Data
+28
View File
@@ -84,6 +84,9 @@
<Compile Include="UserControl\Controls\CarouselDemoCtl.xaml.cs">
<DependentUpon>CarouselDemoCtl.xaml</DependentUpon>
</Compile>
<Compile Include="UserControl\Controls\ClockDemoCtl.xaml.cs">
<DependentUpon>ClockDemoCtl.xaml</DependentUpon>
</Compile>
<Compile Include="UserControl\Controls\ColorPickerDemoCtl.xaml.cs">
<DependentUpon>ColorPickerDemoCtl.xaml</DependentUpon>
</Compile>
@@ -102,12 +105,21 @@
<Compile Include="UserControl\Controls\StepBarDemoCtl.xaml.cs">
<DependentUpon>StepBarDemoCtl.xaml</DependentUpon>
</Compile>
<Compile Include="UserControl\Controls\TimePickerDemoCtl.xaml.cs">
<DependentUpon>TimePickerDemoCtl.xaml</DependentUpon>
</Compile>
<Compile Include="UserControl\Main\NoUserContent.xaml.cs">
<DependentUpon>NoUserContent.xaml</DependentUpon>
</Compile>
<Compile Include="UserControl\Styles\ButtonDemoCtl.xaml.cs">
<DependentUpon>ButtonDemoCtl.xaml</DependentUpon>
</Compile>
<Compile Include="UserControl\Styles\CalendarDemoCtl.xaml.cs">
<DependentUpon>CalendarDemoCtl.xaml</DependentUpon>
</Compile>
<Compile Include="UserControl\Styles\DatePickerDemoCtl.xaml.cs">
<DependentUpon>DatePickerDemoCtl.xaml</DependentUpon>
</Compile>
<Compile Include="UserControl\Styles\ExpanderDemoCtl.xaml.cs">
<DependentUpon>ExpanderDemoCtl.xaml</DependentUpon>
</Compile>
@@ -180,6 +192,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="UserControl\Controls\ClockDemoCtl.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="UserControl\Controls\ColorPickerDemoCtl.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
@@ -204,6 +220,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="UserControl\Controls\TimePickerDemoCtl.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="UserControl\Main\NoUserContent.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
@@ -212,6 +232,14 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="UserControl\Styles\CalendarDemoCtl.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="UserControl\Styles\DatePickerDemoCtl.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="UserControl\Styles\ExpanderDemoCtl.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
+3 -3
View File
@@ -7,10 +7,10 @@ using System.Windows;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("HandyControlDemo")]
[assembly: AssemblyCopyright("Copyright © 纳边 2018")]
[assembly: AssemblyCopyright("Copyright © NaBian 2018")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)]
[assembly: AssemblyVersion("1.2.2.1")]
[assembly: AssemblyFileVersion("1.2.2.1")]
[assembly: AssemblyVersion("1.3.0.0")]
[assembly: AssemblyFileVersion("1.3.0.0")]
+19 -1
View File
@@ -177,6 +177,15 @@ namespace HandyControlDemo.Properties.Langs {
}
}
/// <summary>
/// 查找类似 日期选择器 的本地化字符串。
/// </summary>
public static string DatePicker {
get {
return ResourceManager.GetString("DatePicker", resourceCulture);
}
}
/// <summary>
/// 查找类似 默认 的本地化字符串。
/// </summary>
@@ -205,7 +214,7 @@ namespace HandyControlDemo.Properties.Langs {
}
/// <summary>
/// 查找类似 检测到有新版本! 的本地化字符串。
/// 查找类似 检测到有新版本!是否更新? 的本地化字符串。
/// </summary>
public static string GrowlAsk {
get {
@@ -402,6 +411,15 @@ namespace HandyControlDemo.Properties.Langs {
}
}
/// <summary>
/// 查找类似 时间选择器 的本地化字符串。
/// </summary>
public static string TimePicker {
get {
return ResourceManager.GetString("TimePicker", resourceCulture);
}
}
/// <summary>
/// 查找类似 标题 的本地化字符串。
/// </summary>
@@ -142,7 +142,7 @@
<value>The program has crashed~~~</value>
</data>
<data name="GrowlAsk" xml:space="preserve">
<value>A new version has been detected!</value>
<value>A new version has been detected!Do you want to update?</value>
</data>
<data name="Loading" xml:space="preserve">
<value>Loading</value>
@@ -243,4 +243,10 @@
<data name="Calendar" xml:space="preserve">
<value>Calendar</value>
</data>
<data name="DatePicker" xml:space="preserve">
<value>DatePicker</value>
</data>
<data name="TimePicker" xml:space="preserve">
<value>TimePicker</value>
</data>
</root>
+7 -1
View File
@@ -122,7 +122,7 @@
<value>程序已崩溃~~~</value>
</data>
<data name="GrowlAsk" xml:space="preserve">
<value>检测到有新版本!</value>
<value>检测到有新版本!是否更新?</value>
</data>
<data name="Loading" xml:space="preserve">
<value>加载条</value>
@@ -223,4 +223,10 @@
<data name="Calendar" xml:space="preserve">
<value>日历</value>
</data>
<data name="DatePicker" xml:space="preserve">
<value>日期选择器</value>
</data>
<data name="TimePicker" xml:space="preserve">
<value>时间选择器</value>
</data>
</root>
@@ -2,9 +2,9 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="LabelInfo" TargetType="{x:Type Label}">
<Setter Property="Margin" Value="0,32,16,0"></Setter>
<Setter Property="HorizontalAlignment" Value="Left"></Setter>
<Setter Property="Background" Value="{DynamicResource PrimaryBrush}"></Setter>
<Setter Property="Margin" Value="0,32,16,0"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="Background" Value="{DynamicResource PrimaryBrush}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Label}">
@@ -0,0 +1,9 @@
<UserControl x:Class="HandyControlDemo.UserControl.ClockDemoCtl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:HandyControl.Controls;assembly=HandyControl"
Background="White">
<controls:TransitioningContentControl>
<controls:Clock Margin="32"/>
</controls:TransitioningContentControl>
</UserControl>
@@ -0,0 +1,14 @@
// ReSharper disable once CheckNamespace
namespace HandyControlDemo.UserControl
{
/// <summary>
/// ClockDemoCtl.xaml 的交互逻辑
/// </summary>
public partial class ClockDemoCtl
{
public ClockDemoCtl()
{
InitializeComponent();
}
}
}
@@ -1,12 +1,9 @@
<UserControl x:Class="HandyControlDemo.UserControl.ColorPickerDemoCtl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Background="White"
Background="{Binding SelectedBrush,ElementName=ColorPicker}"
xmlns:controls="clr-namespace:HandyControl.Controls;assembly=HandyControl">
<controls:TransitioningContentControl>
<StackPanel Orientation="Horizontal" Margin="32" VerticalAlignment="Center">
<controls:ColorPicker Name="ColorPicker"/>
<Border Margin="32,0,0,0" Height="100" Width="100" BorderThickness="1" BorderBrush="{StaticResource BorderBrush}" CornerRadius="50" Background="{Binding SelectedBrush,ElementName=ColorPicker}"></Border>
</StackPanel>
<controls:ColorPicker Name="ColorPicker" Margin="32"/>
</controls:TransitioningContentControl>
</UserControl>
@@ -0,0 +1,9 @@
<UserControl x:Class="HandyControlDemo.UserControl.DatePickerDemoCtl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:HandyControl.Controls;assembly=HandyControl"
Background="White">
<controls:TransitioningContentControl>
<DatePicker Margin="32" SelectedDate="2018-10-01"/>
</controls:TransitioningContentControl>
</UserControl>
@@ -0,0 +1,14 @@
// ReSharper disable once CheckNamespace
namespace HandyControlDemo.UserControl
{
/// <summary>
/// DatePickerDemoCtl.xaml 的交互逻辑
/// </summary>
public partial class DatePickerDemoCtl
{
public DatePickerDemoCtl()
{
InitializeComponent();
}
}
}
@@ -0,0 +1,9 @@
<UserControl x:Class="HandyControlDemo.UserControl.TimePickerDemoCtl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:HandyControl.Controls;assembly=HandyControl"
Background="White">
<controls:TransitioningContentControl>
<controls:TimePicker Margin="32"/>
</controls:TransitioningContentControl>
</UserControl>
@@ -0,0 +1,14 @@
// ReSharper disable once CheckNamespace
namespace HandyControlDemo.UserControl
{
/// <summary>
/// TimePickerDemoCtl.xaml 的交互逻辑
/// </summary>
public partial class TimePickerDemoCtl
{
public TimePickerDemoCtl()
{
InitializeComponent();
}
}
}
@@ -18,9 +18,13 @@
<TreeViewItem Tag="{x:Static data:MessageToken.ToggleButtonDemoCtl}" Header="{x:Static langs:Lang.ToggleButton}"/>
<TreeViewItem Tag="{x:Static data:MessageToken.ExpanderDemoCtl}" Header="{x:Static langs:Lang.Expander}"/>
<TreeViewItem Tag="{x:Static data:MessageToken.ProgressBarDemoCtl}" Header="{x:Static langs:Lang.ProgressBar}"/>
<TreeViewItem Style="{StaticResource TreeViewItemNew}" Tag="{x:Static data:MessageToken.CalendarDemoCtl}" Header="{x:Static langs:Lang.Calendar}"/>
<TreeViewItem Style="{StaticResource TreeViewItemNew}" Tag="{x:Static data:MessageToken.DatePickerDemoCtl}" Header="{x:Static langs:Lang.DatePicker}"/>
</TreeViewItem>
<TreeViewItem IsExpanded="True" Header="{x:Static langs:Lang.Controls}">
<TreeViewItem Style="{StaticResource TreeViewItemNew}" Tag="{x:Static data:MessageToken.StepBarDemoCtl}" Header="{x:Static langs:Lang.StepBar}"/>
<TreeViewItem Style="{StaticResource TreeViewItemNew}" Tag="{x:Static data:MessageToken.ClockDemoCtl}" Header="{x:Static langs:Lang.Clock}"/>
<TreeViewItem Style="{StaticResource TreeViewItemNew}" Tag="{x:Static data:MessageToken.TimePickerDemoCtl}" Header="{x:Static langs:Lang.TimePicker}"/>
<TreeViewItem Tag="{x:Static data:MessageToken.StepBarDemoCtl}" Header="{x:Static langs:Lang.StepBar}"/>
<TreeViewItem Tag="{x:Static data:MessageToken.GrowlDemoCtl}" Header="{x:Static langs:Lang.Growl}"/>
<TreeViewItem Tag="{x:Static data:MessageToken.LoadingDemoCtl}" Header="{x:Static langs:Lang.Loading}"/>
<TreeViewItem Tag="{x:Static data:MessageToken.ImageBrowserDemoCtl}" Header="{x:Static langs:Lang.ImageBrowser}"/>
@@ -0,0 +1,9 @@
<UserControl x:Class="HandyControlDemo.UserControl.CalendarDemoCtl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:HandyControl.Controls;assembly=HandyControl"
Background="White">
<controls:TransitioningContentControl>
<Calendar Margin="32" SelectionMode="MultipleRange"/>
</controls:TransitioningContentControl>
</UserControl>
@@ -0,0 +1,14 @@
// ReSharper disable once CheckNamespace
namespace HandyControlDemo.UserControl
{
/// <summary>
/// CalendarDemoCtl.xaml 的交互逻辑
/// </summary>
public partial class CalendarDemoCtl
{
public CalendarDemoCtl()
{
InitializeComponent();
}
}
}
@@ -0,0 +1,10 @@
<UserControl x:Class="HandyControlDemo.UserControl.DatePickerDemoCtl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:HandyControl.Controls;assembly=HandyControl"
xmlns:system="clr-namespace:System;assembly=mscorlib"
Background="White">
<controls:TransitioningContentControl>
<DatePicker Margin="32" SelectedDate="{x:Static system:DateTime.Now}"/>
</controls:TransitioningContentControl>
</UserControl>
@@ -0,0 +1,14 @@
// ReSharper disable once CheckNamespace
namespace HandyControlDemo.UserControl
{
/// <summary>
/// DatePickerDemoCtl.xaml 的交互逻辑
/// </summary>
public partial class DatePickerDemoCtl
{
public DatePickerDemoCtl()
{
InitializeComponent();
}
}
}
+16 -2
View File
@@ -8,6 +8,16 @@
让我们开门见山,HandyControl已经开源的控件截图有:
##最新控件
### 1、日历Calendar
![日历Calendar](https://raw.githubusercontent.com/NaBian/HandyControl/master/Resources/Calendar.jpg)
### 2、时钟Clock
![时钟Clock](https://raw.githubusercontent.com/NaBian/HandyControl/master/Resources/Clock.jpg)
##历史发布
### 1、颜色拾取器ColorPicker
![颜色拾取器ColorPicker](https://raw.githubusercontent.com/NaBian/HandyControl/master/Resources/ColorPicker.gif)
@@ -95,6 +105,10 @@
* 为什么我连编译都无法通过:
编译之前,请确保IDE为vs2017且c#最低版本为7.0,HandyControl目前仅支持4.5以上的.net环境。
# v1.3.0版本计划
# v1.4.0 Plan
1、添加时间、日历控件;
- add ComboBox Style;
- add TextBox Style;
- add PasswordBox Style;
- add TabControl Style;
- add Black Theme
Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB