Merge branch 'master' into pr/84

This commit is contained in:
NaBian committed 2019-11-03 20:18:22 +08:00
commit e02b420634
375 files changed
+9510 -1366

No files matched your search

@@ -8,6 +8,44 @@ namespace HandyControl.Controls
{
public class DataGridAttach
{
public static readonly DependencyProperty ApplyDefaultStyleProperty = DependencyProperty.RegisterAttached(
"ApplyDefaultStyle", typeof(bool), typeof(DataGridAttach), new PropertyMetadata(ValueBoxes.FalseBox, OnApplyDefaultStyleChanged));
private static void OnApplyDefaultStyleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var grid = (DataGrid)d;
if ((bool)e.NewValue)
{
if (grid.AutoGenerateColumns)
{
grid.AutoGeneratedColumns += Grid_AutoGeneratedColumns;
return;
}
UpdateTextColumnStyles(grid);
UpdateComboBoxColumnStyles(grid);
UpdateCheckBoxColumnStyles(grid);
}
else
{
grid.AutoGeneratedColumns -= Grid_AutoGeneratedColumns;
}
}
private static void Grid_AutoGeneratedColumns(object sender, System.EventArgs e)
{
var grid = (DataGrid)sender;
UpdateTextColumnStyles(grid);
UpdateComboBoxColumnStyles(grid);
UpdateCheckBoxColumnStyles(grid);
}
public static void SetApplyDefaultStyle(DependencyObject element, bool value)
=> element.SetValue(ApplyDefaultStyleProperty, value);
public static bool GetApplyDefaultStyle(DependencyObject element)
=> (bool) element.GetValue(ApplyDefaultStyleProperty);
public static readonly DependencyProperty TextColumnStyleProperty = DependencyProperty.RegisterAttached(
"TextColumnStyle", typeof(Style), typeof(DataGridAttach), new PropertyMetadata(default(Style), OnTextColumnStyleChanged));
@@ -44,5 +44,29 @@ namespace HandyControl.Controls
public static void SetContentHeight(DependencyObject element, double value) => element.SetValue(ContentHeightProperty, value);
public static double GetContentHeight(DependencyObject element) => (double)element.GetValue(ContentHeightProperty);
/// <summary>
/// 最小内容高度
/// </summary>
public static readonly DependencyProperty MinContentHeightProperty = DependencyProperty.RegisterAttached(
"MinContentHeight", typeof(double), typeof(InfoElement), new PropertyMetadata(30.0));
public static void SetMinContentHeight(DependencyObject element, double value)
=> element.SetValue(MinContentHeightProperty, value);
public static double GetMinContentHeight(DependencyObject element)
=> (double) element.GetValue(MinContentHeightProperty);
/// <summary>
/// 最大内容高度
/// </summary>
public static readonly DependencyProperty MaxContentHeightProperty = DependencyProperty.RegisterAttached(
"MaxContentHeight", typeof(double), typeof(InfoElement), new PropertyMetadata(double.PositiveInfinity));
public static void SetMaxContentHeight(DependencyObject element, double value)
=> element.SetValue(MaxContentHeightProperty, value);
public static double GetMaxContentHeight(DependencyObject element)
=> (double) element.GetValue(MaxContentHeightProperty);
}
}
@@ -0,0 +1,53 @@
using System.Windows;
using System.Windows.Controls;
using HandyControl.Data;
namespace HandyControl.Controls
{
public class TextBlockAttach
{
public static readonly DependencyProperty AutoTooltipProperty = DependencyProperty.RegisterAttached(
"AutoTooltip", typeof(bool), typeof(TextBlockAttach), new PropertyMetadata(ValueBoxes.FalseBox, OnAutoTooltipChanged));
private static void OnAutoTooltipChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is TextBlock ctl)
{
if ((bool)e.NewValue)
{
ctl.TextTrimming = TextTrimming.WordEllipsis;
UpdateTooltip(ctl);
ctl.SizeChanged += TextBlock_SizeChanged;
}
else
{
ctl.ClearValue(TextBlock.TextTrimmingProperty);
ctl.SizeChanged -= TextBlock_SizeChanged;
}
}
}
public static void SetAutoTooltip(DependencyObject element, bool value)
=> element.SetValue(AutoTooltipProperty, value);
public static bool GetAutoTooltip(DependencyObject element)
=> (bool) element.GetValue(AutoTooltipProperty);
private static void TextBlock_SizeChanged(object sender, SizeChangedEventArgs e)
{
if (sender is TextBlock textBlock)
{
UpdateTooltip(textBlock);
}
}
private static void UpdateTooltip(TextBlock textBlock)
{
textBlock.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
var width = textBlock.DesiredSize.Width - textBlock.Margin.Left - textBlock.Margin.Right;
ToolTipService.SetToolTip(textBlock,
textBlock.RenderSize.Width > width || textBlock.ActualWidth < width ? textBlock.Text : null);
}
}
}
@@ -1,6 +1,9 @@
using System.Windows;
using System;
using System.Windows;
using System.Windows.Input;
using System.Windows.Interop;
using HandyControl.Data;
using HandyControl.Tools.Interop;
namespace HandyControl.Controls
{
@@ -21,7 +24,7 @@ namespace HandyControl.Controls
{
if ((bool)e.NewValue)
{
ctl.MouseLeftButtonDown += DragElement_MouseLeftButtonDown; ;
ctl.MouseLeftButtonDown += DragElement_MouseLeftButtonDown;
}
else
{
@@ -37,5 +40,72 @@ namespace HandyControl.Controls
System.Windows.Window.GetWindow(obj)?.DragMove();
}
}
public static readonly DependencyProperty IgnoreAltF4Property = DependencyProperty.RegisterAttached(
"IgnoreAltF4", typeof(bool), typeof(WindowAttach), new PropertyMetadata(ValueBoxes.FalseBox, OnIgnoreAltF4Changed));
private static void OnIgnoreAltF4Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is System.Windows.Window window)
{
if ((bool)e.NewValue)
{
window.PreviewKeyDown += Window_PreviewKeyDown;
}
else
{
window.PreviewKeyDown -= Window_PreviewKeyDown;
}
}
}
private static void Window_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.System && e.SystemKey == Key.F4)
{
e.Handled = true;
}
}
public static void SetIgnoreAltF4(DependencyObject element, bool value)
=> element.SetValue(IgnoreAltF4Property, value);
public static bool GetIgnoreAltF4(DependencyObject element)
=> (bool) element.GetValue(IgnoreAltF4Property);
public static readonly DependencyProperty ShowInTaskManagerProperty = DependencyProperty.RegisterAttached(
"ShowInTaskManager", typeof(bool), typeof(WindowAttach), new PropertyMetadata(ValueBoxes.TrueBox, OnShowInTaskManagerChanged));
private static void OnShowInTaskManagerChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is System.Windows.Window window)
{
if ((bool)e.NewValue)
{
window.SourceInitialized -= Window_SourceInitialized;
}
else
{
window.SourceInitialized += Window_SourceInitialized;
}
}
}
private static void Window_SourceInitialized(object sender, EventArgs e)
{
if (sender is System.Windows.Window window)
{
var _ = new WindowInteropHelper(window)
{
Owner = NativeMethods.GetDesktopWindow()
};
}
}
public static void SetShowInTaskManager(DependencyObject element, bool value)
=> element.SetValue(ShowInTaskManagerProperty, value);
public static bool GetShowInTaskManager(DependencyObject element)
=> (bool) element.GetValue(ShowInTaskManagerProperty);
}
}
@@ -0,0 +1,188 @@
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using HandyControl.Data;
using HandyControl.Interactivity;
using HandyControl.Tools;
namespace HandyControl.Controls
{
public class FloatingBlock : Control
{
public static readonly DependencyProperty ToXProperty = DependencyProperty.RegisterAttached(
"ToX", typeof(double), typeof(FloatingBlock), new PropertyMetadata(ValueBoxes.Double0Box));
public static void SetToX(DependencyObject element, double value)
=> element.SetValue(ToXProperty, value);
public static double GetToX(DependencyObject element)
=> (double) element.GetValue(ToXProperty);
public static readonly DependencyProperty ToYProperty = DependencyProperty.RegisterAttached(
"ToY", typeof(double), typeof(FloatingBlock), new PropertyMetadata(-100.0));
public static void SetToY(DependencyObject element, double value)
=> element.SetValue(ToYProperty, value);
public static double GetToY(DependencyObject element)
=> (double)element.GetValue(ToYProperty);
public static readonly DependencyProperty DurationProperty = DependencyProperty.RegisterAttached(
"Duration", typeof(Duration), typeof(FloatingBlock), new PropertyMetadata(new Duration(TimeSpan.FromSeconds(2))));
public static void SetDuration(DependencyObject element, Duration value)
=> element.SetValue(DurationProperty, value);
public static Duration GetDuration(DependencyObject element)
=> (Duration) element.GetValue(DurationProperty);
public static readonly DependencyProperty HorizontalOffsetProperty = DependencyProperty.RegisterAttached(
"HorizontalOffset", typeof(double), typeof(FloatingBlock), new PropertyMetadata(ValueBoxes.Double0Box));
public static void SetHorizontalOffset(DependencyObject element, double value)
=> element.SetValue(HorizontalOffsetProperty, value);
public static double GetHorizontalOffset(DependencyObject element)
=> (double) element.GetValue(HorizontalOffsetProperty);
public static readonly DependencyProperty VerticalOffsetProperty = DependencyProperty.RegisterAttached(
"VerticalOffset", typeof(double), typeof(FloatingBlock), new PropertyMetadata(ValueBoxes.Double0Box));
public static void SetVerticalOffset(DependencyObject element, double value)
=> element.SetValue(VerticalOffsetProperty, value);
public static double GetVerticalOffset(DependencyObject element)
=> (double) element.GetValue(VerticalOffsetProperty);
public static readonly DependencyProperty ContentTemplateProperty = DependencyProperty.RegisterAttached(
"ContentTemplate", typeof(DataTemplate), typeof(FloatingBlock), new PropertyMetadata(default(DataTemplate), OnDataChanged));
public static void SetContentTemplate(DependencyObject element, DataTemplate value)
=> element.SetValue(ContentTemplateProperty, value);
public static DataTemplate GetContentTemplate(DependencyObject element)
=> (DataTemplate) element.GetValue(ContentTemplateProperty);
public DataTemplate ContentTemplate
{
get => (DataTemplate)GetValue(ContentTemplateProperty);
set => SetValue(ContentTemplateProperty, value);
}
private static readonly DependencyProperty ReadyToFloatProperty = DependencyProperty.RegisterAttached(
"ReadyToFloat", typeof(bool), typeof(FloatingBlock), new PropertyMetadata(ValueBoxes.FalseBox));
private static void SetReadyToFloat(DependencyObject element, bool value)
=> element.SetValue(ReadyToFloatProperty, value);
private static bool GetReadyToFloat(DependencyObject element)
=> (bool)element.GetValue(ReadyToFloatProperty);
public static readonly DependencyProperty ContentProperty = DependencyProperty.RegisterAttached(
"Content", typeof(object), typeof(FloatingBlock), new PropertyMetadata(default, OnDataChanged));
public static void SetContent(DependencyObject element, object value)
=> element.SetValue(ContentProperty, value);
public static object GetContent(DependencyObject element)
=> element.GetValue(ContentProperty);
public object Content
{
get => GetValue(ContentProperty);
set => SetValue(ContentProperty, value);
}
private static void OnDataChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (!(d is UIElement target)) return;
target.PreviewMouseLeftButtonDown -= Target_PreviewMouseLeftButtonDown;
target.PreviewMouseLeftButtonUp -= Target_PreviewMouseLeftButtonUp;
if (e.NewValue != null)
{
target.PreviewMouseLeftButtonDown += Target_PreviewMouseLeftButtonDown;
target.PreviewMouseLeftButtonUp += Target_PreviewMouseLeftButtonUp;
}
}
private static void Target_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) => SetReadyToFloat(sender as DependencyObject, true);
private static void Target_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (sender is UIElement element && GetReadyToFloat(element))
{
var layer = AdornerLayer.GetAdornerLayer(element);
if (layer != null)
{
var adorner = new AdornerContainer(layer)
{
IsHitTestVisible = false
};
var child = CreateBlock(element, adorner);
adorner.Child = child;
layer.Add(adorner);
}
SetReadyToFloat(element, false);
}
}
private static FloatingBlock CreateBlock(Visual element, AdornerContainer adorner)
{
var p = Mouse.GetPosition(adorner.AdornedElement);
var transform = new TranslateTransform
{
X = p.X + GetHorizontalOffset(element),
Y = p.Y + GetVerticalOffset(element)
};
var block = new FloatingBlock
{
Content = GetContent(element),
ContentTemplate = GetContentTemplate(element),
RenderTransform = new TransformGroup
{
Children =
{
transform
}
}
};
var milliseconds = GetDuration(element).TimeSpan.TotalMilliseconds;
var animationX = AnimationHelper.CreateAnimation(GetToX(element) + transform.X, milliseconds);
Storyboard.SetTargetProperty(animationX, new PropertyPath("(UIElement.RenderTransform).(TransformGroup.Children)[0].(TranslateTransform.X)"));
Storyboard.SetTarget(animationX, block);
var animationY = AnimationHelper.CreateAnimation(GetToY(element) + transform.Y, milliseconds);
Storyboard.SetTargetProperty(animationY, new PropertyPath("(UIElement.RenderTransform).(TransformGroup.Children)[0].(TranslateTransform.Y)"));
Storyboard.SetTarget(animationY, block);
var animationOpacity = AnimationHelper.CreateAnimation(0, milliseconds);
Storyboard.SetTargetProperty(animationOpacity, new PropertyPath("Opacity"));
Storyboard.SetTarget(animationOpacity, block);
var storyboard = new Storyboard();
storyboard.Completed += (s, e) =>
{
var layer = AdornerLayer.GetAdornerLayer(element);
if (layer == null) return;
adorner.Child = null;
layer.Remove(adorner);
};
storyboard.Children.Add(animationX);
storyboard.Children.Add(animationY);
storyboard.Children.Add(animationOpacity);
storyboard.Begin();
return block;
}
}
}
@@ -0,0 +1,172 @@
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using HandyControl.Data;
namespace HandyControl.Controls
{
[TemplatePart(Name = ElementContent, Type = typeof(FrameworkElement))]
[TemplatePart(Name = ElementPanel, Type = typeof(Panel))]
public class RunningBlock : ContentControl
{
private const string ElementContent = "PART_ContentElement";
private const string ElementPanel = "PART_Panel";
protected Storyboard _storyboard;
private FrameworkElement _elementContent;
private FrameworkElement _elementPanel;
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
_elementContent = GetTemplateChild(ElementContent) as FrameworkElement;
_elementPanel = GetTemplateChild(ElementPanel) as Panel;
}
public static readonly DependencyProperty RunawayProperty = DependencyProperty.Register(
"Runaway", typeof(bool), typeof(RunningBlock), new FrameworkPropertyMetadata(ValueBoxes.TrueBox, FrameworkPropertyMetadataOptions.AffectsRender));
public bool Runaway
{
get => (bool) GetValue(RunawayProperty);
set => SetValue(RunawayProperty, value);
}
public static readonly DependencyProperty AutoRunProperty = DependencyProperty.Register(
"AutoRun", typeof(bool), typeof(RunningBlock), new FrameworkPropertyMetadata(ValueBoxes.FalseBox, FrameworkPropertyMetadataOptions.AffectsRender));
public bool AutoRun
{
get => (bool) GetValue(AutoRunProperty);
set => SetValue(AutoRunProperty, value);
}
public static readonly DependencyProperty OrientationProperty = DependencyProperty.Register(
"Orientation", typeof(Orientation), typeof(RunningBlock), new FrameworkPropertyMetadata(default(Orientation), FrameworkPropertyMetadataOptions.AffectsRender));
public Orientation Orientation
{
get => (Orientation) GetValue(OrientationProperty);
set => SetValue(OrientationProperty, value);
}
public static readonly DependencyProperty DurationProperty = DependencyProperty.Register(
"Duration", typeof(Duration), typeof(RunningBlock), new FrameworkPropertyMetadata(new Duration(TimeSpan.FromSeconds(5)), FrameworkPropertyMetadataOptions.AffectsRender));
public Duration Duration
{
get => (Duration) GetValue(DurationProperty);
set => SetValue(DurationProperty, value);
}
public static readonly DependencyProperty IsRunningProperty = DependencyProperty.Register(
"IsRunning", typeof(bool), typeof(RunningBlock), new PropertyMetadata(ValueBoxes.TrueBox, (o, args) =>
{
var ctl = (RunningBlock)o;
var v = (bool)args.NewValue;
if (v)
{
ctl._storyboard?.Resume();
}
else
{
ctl._storyboard?.Pause();
}
}));
public bool IsRunning
{
get => (bool) GetValue(IsRunningProperty);
set => SetValue(IsRunningProperty, value);
}
public static readonly DependencyProperty AutoReverseProperty = DependencyProperty.Register(
"AutoReverse", typeof(bool), typeof(RunningBlock), new FrameworkPropertyMetadata(ValueBoxes.FalseBox, FrameworkPropertyMetadataOptions.AffectsRender));
public bool AutoReverse
{
get => (bool) GetValue(AutoReverseProperty);
set => SetValue(AutoReverseProperty, value);
}
private void UpdateContent()
{
if (_elementContent == null || _elementPanel == null) return;
_storyboard?.Stop();
_elementPanel.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
_elementPanel.Width = _elementPanel.DesiredSize.Width;
_elementPanel.Height = _elementPanel.DesiredSize.Height;
double from;
double to;
PropertyPath propertyPath;
if (Orientation == Orientation.Horizontal)
{
if (AutoRun && _elementPanel.Width < ActualWidth)
{
return;
}
if (Runaway)
{
from = -_elementPanel.Width;
to = ActualWidth;
}
else
{
from = 0;
to = ActualWidth - _elementPanel.Width;
SetCurrentValue(AutoReverseProperty, ValueBoxes.TrueBox);
}
propertyPath = new PropertyPath("(UIElement.RenderTransform).(TransformGroup.Children)[0].(TranslateTransform.X)");
}
else
{
if (AutoRun && _elementPanel.Height < ActualHeight)
{
return;
}
if (Runaway)
{
from = -_elementPanel.Height;
to = ActualHeight;
}
else
{
from = 0;
to = ActualHeight - _elementPanel.Height;
SetCurrentValue(AutoReverseProperty, ValueBoxes.TrueBox);
}
propertyPath = new PropertyPath("(UIElement.RenderTransform).(TransformGroup.Children)[0].(TranslateTransform.Y)");
}
var animation = new DoubleAnimation(from, to, Duration)
{
RepeatBehavior = RepeatBehavior.Forever,
AutoReverse = AutoReverse
};
Storyboard.SetTargetProperty(animation, propertyPath);
Storyboard.SetTarget(animation, _elementContent);
_storyboard = new Storyboard();
_storyboard.Children.Add(animation);
_storyboard.Begin();
}
protected override void OnRender(DrawingContext drawingContext)
{
base.OnRender(drawingContext);
UpdateContent();
}
}
}
@@ -0,0 +1,81 @@
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using HandyControl.Data;
using HandyControl.Data.Enum;
namespace HandyControl.Controls
{
public class SplitButton : ButtonBase
{
public static readonly DependencyProperty HitModeProperty = DependencyProperty.Register(
"HitMode", typeof(MouseHitMode), typeof(SplitButton), new PropertyMetadata(default(MouseHitMode)));
public MouseHitMode HitMode
{
get => (MouseHitMode) GetValue(HitModeProperty);
set => SetValue(HitModeProperty, value);
}
public static readonly DependencyProperty MaxDropDownHeightProperty = DependencyProperty.Register(
"MaxDropDownHeight", typeof(double), typeof(SplitButton), new PropertyMetadata(SystemParameters.PrimaryScreenHeight / 3.0));
public double MaxDropDownHeight
{
get => (double) GetValue(MaxDropDownHeightProperty);
set => SetValue(MaxDropDownHeightProperty, value);
}
public static readonly DependencyProperty IsDropDownOpenProperty = DependencyProperty.Register(
"IsDropDownOpen", typeof(bool), typeof(SplitButton), new PropertyMetadata(ValueBoxes.FalseBox));
public bool IsDropDownOpen
{
get => (bool) GetValue(IsDropDownOpenProperty);
set => SetValue(IsDropDownOpenProperty, value);
}
public static readonly DependencyProperty DropDownContentProperty = DependencyProperty.Register(
"DropDownContent", typeof(object), typeof(SplitButton), new PropertyMetadata(default(object)));
public object DropDownContent
{
get => GetValue(DropDownContentProperty);
set => SetValue(DropDownContentProperty, value);
}
public SplitButton()
{
AddHandler(MenuItem.ClickEvent, new RoutedEventHandler(ItemsOnClick));
}
private void ItemsOnClick(object sender, RoutedEventArgs e)
{
if (e.OriginalSource is MenuItem)
{
SetCurrentValue(IsDropDownOpenProperty, ValueBoxes.FalseBox);
}
}
protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e)
{
base.OnPreviewMouseLeftButtonDown(e);
if (HitMode == MouseHitMode.Hover)
{
e.Handled = true;
}
}
protected override void OnMouseEnter(MouseEventArgs e)
{
base.OnMouseEnter(e);
if (HitMode == MouseHitMode.Hover)
{
SetCurrentValue(IsDropDownOpenProperty, ValueBoxes.TrueBox);
}
}
}
}
@@ -223,7 +223,7 @@ namespace HandyControl.Controls
{
ItemsHost.Children.Remove(_viewContent);
}
var total = Items.Count + 1;
var total = _entryDic.Count + 1;
var totalRow = total / Groups + (total % Groups > 0 ? 1 : 0);
if (total <= Groups)
{
@@ -359,9 +359,9 @@ namespace HandyControl.Controls
private void GenerateIndex()
{
var index = 0;
foreach (var item in Items)
foreach (var item in _entryDic.Values)
{
_entryDic[item].Index = index++;
item.Index = index++;
}
}
@@ -1,4 +1,5 @@
using System.Windows;
using System;
using System.Windows;
using System.Windows.Controls;
using HandyControl.Data;
using HandyControl.Tools.Extension;
@@ -40,32 +41,48 @@ namespace HandyControl.Controls
set => SetValue(SpanProperty, value);
}
public static readonly DependencyProperty IsFixedProperty = DependencyProperty.Register(
"IsFixed", typeof(bool), typeof(Col), new PropertyMetadata(ValueBoxes.FalseBox));
public bool IsFixed
{
get => (bool) GetValue(IsFixedProperty);
set => SetValue(IsFixedProperty, value);
}
internal int GetLayoutCellCount(ColLayoutStatus status)
{
var result = 0;
if (Layout != null)
{
switch (status)
if (!IsFixed)
{
case ColLayoutStatus.Xs:
result = Layout.Xs;
break;
case ColLayoutStatus.Sm:
result = Layout.Sm;
break;
case ColLayoutStatus.Md:
result = Layout.Md;
break;
case ColLayoutStatus.Lg:
result = Layout.Lg;
break;
case ColLayoutStatus.Xl:
result = Layout.Xl;
break;
case ColLayoutStatus.Xxl:
result = Layout.Xxl;
break;
switch (status)
{
case ColLayoutStatus.Xs:
result = Layout.Xs;
break;
case ColLayoutStatus.Sm:
result = Layout.Sm;
break;
case ColLayoutStatus.Md:
result = Layout.Md;
break;
case ColLayoutStatus.Lg:
result = Layout.Lg;
break;
case ColLayoutStatus.Xl:
result = Layout.Xl;
break;
case ColLayoutStatus.Xxl:
result = Layout.Xxl;
break;
case ColLayoutStatus.Auto:
break;
default:
throw new ArgumentOutOfRangeException(nameof(status), status, null);
}
}
}
else
@@ -13,6 +13,8 @@ namespace HandyControl.Controls
private double _maxChildDesiredHeight;
private double _totalAutoWidth;
public static readonly DependencyProperty GutterProperty = DependencyProperty.Register(
"Gutter", typeof(double), typeof(Row), new PropertyMetadata(ValueBoxes.Double0Box, null, OnGutterCoerce), ValidateHelper.IsInRangeOfPosDoubleIncludeZero);
@@ -29,6 +31,7 @@ namespace HandyControl.Controls
var totalCellCount = 0;
var totalRowCount = 1;
var gutterHalf = Gutter / 2;
_totalAutoWidth = 0;
foreach (var child in InternalChildren.OfType<Col>())
{
@@ -40,12 +43,7 @@ namespace HandyControl.Controls
{
_maxChildDesiredHeight = childDesiredSize.Height;
}
}
_layoutStatus = ColLayout.GetLayoutStatus(constraint.Width);
foreach (var child in InternalChildren.OfType<Col>())
{
var cellCount = child.GetLayoutCellCount(_layoutStatus);
totalCellCount += cellCount;
@@ -54,16 +52,21 @@ namespace HandyControl.Controls
totalCellCount = cellCount;
totalRowCount++;
}
if (cellCount == 0 || child.IsFixed)
{
_totalAutoWidth += childDesiredSize.Width;
}
}
return new Size(0, _maxChildDesiredHeight * totalRowCount - Gutter);
return new Size(constraint.Width, _maxChildDesiredHeight * totalRowCount - Gutter);
}
protected override Size ArrangeOverride(Size finalSize)
{
var totalCellCount = 0;
var gutterHalf = Gutter / 2;
var itemWidth = (finalSize.Width + Gutter) / ColLayout.ColMaxCellCount;
var itemWidth = (finalSize.Width - _totalAutoWidth + Gutter) / ColLayout.ColMaxCellCount;
var childBounds = new Rect(-gutterHalf, -gutterHalf, 0, _maxChildDesiredHeight);
_layoutStatus = ColLayout.GetLayoutStatus(finalSize.Width);
@@ -72,7 +75,8 @@ namespace HandyControl.Controls
var cellCount = child.GetLayoutCellCount(_layoutStatus);
totalCellCount += cellCount;
var childWidth = cellCount * itemWidth;
var childWidth = cellCount > 0 ? cellCount * itemWidth : child.DesiredSize.Width;
childBounds.Width = childWidth;
childBounds.X += child.Offset * itemWidth;
if (totalCellCount > ColLayout.ColMaxCellCount)
@@ -31,6 +31,8 @@ namespace HandyControl.Controls
#region Data
private static GrowlWindow GrowlWindow;
private Panel _panelMore;
private Grid _gridMain;
@@ -293,6 +295,8 @@ namespace HandyControl.Controls
private static void InitGrowlPanel(Panel panel)
{
if (panel == null) return;
var menuItem = new MenuItem
{
Header = Properties.Langs.Lang.Clear
@@ -334,6 +338,61 @@ namespace HandyControl.Controls
if (!_staysOpen) StartTimer();
}
private static void ShowGlobal(GrowlInfo growlInfo)
{
if (GrowlWindow == null)
{
GrowlWindow = new GrowlWindow();
GrowlWindow.Show();
InitGrowlPanel(GrowlWindow.GrowlPanel);
GrowlWindow.Init();
}
GrowlWindow.Show(true);
#if netle40
Application.Current.Dispatcher?.Invoke(new Action(() =>
{
var ctl = new Growl
{
Message = growlInfo.Message,
Time = DateTime.Now,
Icon = ResourceHelper.GetResource<Geometry>(growlInfo.IconKey),
IconBrush = ResourceHelper.GetResource<Brush>(growlInfo.IconBrushKey),
_showCloseButton = growlInfo.ShowCloseButton,
ActionBeforeClose = growlInfo.ActionBeforeClose,
_staysOpen = growlInfo.StaysOpen,
ShowDateTime = growlInfo.ShowDateTime,
ConfirmStr = growlInfo.ConfirmStr,
CancelStr = growlInfo.CancelStr,
Type = growlInfo.Type,
_waitTime = Math.Max(growlInfo.WaitTime, 2)
};
GrowlWindow.GrowlPanel.Children.Insert(0, ctl);
}));
#else
Application.Current.Dispatcher?.Invoke(() =>
{
var ctl = new Growl
{
Message = growlInfo.Message,
Time = DateTime.Now,
Icon = ResourceHelper.GetResource<Geometry>(growlInfo.IconKey),
IconBrush = ResourceHelper.GetResource<Brush>(growlInfo.IconBrushKey),
_showCloseButton = growlInfo.ShowCloseButton,
ActionBeforeClose = growlInfo.ActionBeforeClose,
_staysOpen = growlInfo.StaysOpen,
ShowDateTime = growlInfo.ShowDateTime,
ConfirmStr = growlInfo.ConfirmStr,
CancelStr = growlInfo.CancelStr,
Type = growlInfo.Type,
_waitTime = Math.Max(growlInfo.WaitTime, 2)
};
GrowlWindow.GrowlPanel.Children.Insert(0, ctl);
});
#endif
}
/// <summary>
/// 显示信息
/// </summary>
@@ -341,7 +400,7 @@ namespace HandyControl.Controls
private static void Show(GrowlInfo growlInfo)
{
#if netle40
Application.Current.Dispatcher.Invoke(new Action(() =>
Application.Current.Dispatcher?.Invoke(new Action(() =>
{
var ctl = new Growl
{
@@ -371,7 +430,7 @@ namespace HandyControl.Controls
}
}));
#else
Application.Current.Dispatcher.Invoke(() =>
Application.Current.Dispatcher?.Invoke(() =>
{
var ctl = new Growl
{
@@ -430,6 +489,31 @@ namespace HandyControl.Controls
Show(growlInfo);
}
/// <summary>
/// 成功
/// </summary>
/// <param name="message"></param>
public static void SuccessGlobal(string message) => SuccessGlobal(new GrowlInfo
{
Message = message
});
/// <summary>
/// 成功
/// </summary>
/// <param name="growlInfo"></param>
public static void SuccessGlobal(GrowlInfo growlInfo)
{
if (growlInfo == null) throw new ArgumentNullException(nameof(growlInfo));
if (!growlInfo.IsCustom)
{
growlInfo.IconKey = ResourceToken.SuccessGeometry;
growlInfo.IconBrushKey = ResourceToken.SuccessBrush;
growlInfo.Type = InfoType.Success;
}
ShowGlobal(growlInfo);
}
/// <summary>
/// 消息
/// </summary>
@@ -457,6 +541,31 @@ namespace HandyControl.Controls
Show(growlInfo);
}
/// <summary>
/// 消息
/// </summary>
/// <param name="message"></param>
public static void InfoGlobal(string message) => InfoGlobal(new GrowlInfo
{
Message = message
});
/// <summary>
/// 消息
/// </summary>
/// <param name="growlInfo"></param>
public static void InfoGlobal(GrowlInfo growlInfo)
{
if (growlInfo == null) throw new ArgumentNullException(nameof(growlInfo));
if (!growlInfo.IsCustom)
{
growlInfo.IconKey = ResourceToken.InfoGeometry;
growlInfo.IconBrushKey = ResourceToken.InfoBrush;
growlInfo.Type = InfoType.Info;
}
ShowGlobal(growlInfo);
}
/// <summary>
/// 警告
/// </summary>
@@ -484,6 +593,31 @@ namespace HandyControl.Controls
Show(growlInfo);
}
/// <summary>
/// 警告
/// </summary>
/// <param name="message"></param>
public static void WarningGlobal(string message) => WarningGlobal(new GrowlInfo
{
Message = message
});
/// <summary>
/// 警告
/// </summary>
/// <param name="growlInfo"></param>
public static void WarningGlobal(GrowlInfo growlInfo)
{
if (growlInfo == null) throw new ArgumentNullException(nameof(growlInfo));
if (!growlInfo.IsCustom)
{
growlInfo.IconKey = ResourceToken.WarningGeometry;
growlInfo.IconBrushKey = ResourceToken.WarningBrush;
growlInfo.Type = InfoType.Warning;
}
ShowGlobal(growlInfo);
}
/// <summary>
/// 错误
/// </summary>
@@ -512,6 +646,32 @@ namespace HandyControl.Controls
Show(growlInfo);
}
/// <summary>
/// 错误
/// </summary>
/// <param name="message"></param>
public static void ErrorGlobal(string message) => ErrorGlobal(new GrowlInfo
{
Message = message
});
/// <summary>
/// 错误
/// </summary>
/// <param name="growlInfo"></param>
public static void ErrorGlobal(GrowlInfo growlInfo)
{
if (growlInfo == null) throw new ArgumentNullException(nameof(growlInfo));
if (!growlInfo.IsCustom)
{
growlInfo.IconKey = ResourceToken.ErrorGeometry;
growlInfo.IconBrushKey = ResourceToken.DangerBrush;
growlInfo.StaysOpen = true;
growlInfo.Type = InfoType.Error;
}
ShowGlobal(growlInfo);
}
/// <summary>
/// 严重
/// </summary>
@@ -542,6 +702,34 @@ namespace HandyControl.Controls
Show(growlInfo);
}
/// <summary>
/// 严重
/// </summary>
/// <param name="message"></param>
public static void FatalGlobal(string message) => FatalGlobal(new GrowlInfo
{
Message = message
});
/// <summary>
/// 严重
/// </summary>
/// <param name="growlInfo"></param>
public static void FatalGlobal(GrowlInfo growlInfo)
{
if (growlInfo == null) throw new ArgumentNullException(nameof(growlInfo));
if (!growlInfo.IsCustom)
{
growlInfo.IconKey = ResourceToken.FatalGeometry;
growlInfo.IconBrushKey = ResourceToken.PrimaryTextBrush;
growlInfo.StaysOpen = true;
growlInfo.ShowCloseButton = false;
growlInfo.Type = InfoType.Fatal;
if (GrowlPanel.ContextMenu != null) GrowlPanel.ContextMenu.Opacity = 0;
}
ShowGlobal(growlInfo);
}
/// <summary>
/// 询问
/// </summary>
@@ -573,6 +761,35 @@ namespace HandyControl.Controls
Show(growlInfo);
}
/// <summary>
/// 询问
/// </summary>
/// <param name="message"></param>
/// <param name="actionBeforeClose"></param>
public static void AskGlobal(string message, Func<bool, bool> actionBeforeClose) => AskGlobal(new GrowlInfo
{
Message = message,
ActionBeforeClose = actionBeforeClose
});
/// <summary>
/// 询问
/// </summary>
/// <param name="growlInfo"></param>
public static void AskGlobal(GrowlInfo growlInfo)
{
if (growlInfo == null) throw new ArgumentNullException(nameof(growlInfo));
if (!growlInfo.IsCustom)
{
growlInfo.IconKey = ResourceToken.AskGeometry;
growlInfo.IconBrushKey = ResourceToken.AccentBrush;
growlInfo.StaysOpen = true;
growlInfo.ShowCloseButton = false;
growlInfo.Type = InfoType.Ask;
}
ShowGlobal(growlInfo);
}
private void ButtonClose_OnClick(object sender, RoutedEventArgs e) => Close();
/// <summary>
@@ -589,6 +806,12 @@ namespace HandyControl.Controls
if (Parent is Panel panel)
{
panel.Children.Remove(this);
if (GrowlWindow?.GrowlPanel != null && GrowlWindow.GrowlPanel.Children.Count == 0)
{
GrowlWindow.Close();
GrowlWindow = null;
}
}
};
transform.BeginAnimation(TranslateTransform.XProperty, animation);
@@ -619,6 +842,7 @@ namespace HandyControl.Controls
/// <param name="panel"></param>
private static void Clear(Panel panel)
{
if (panel == null) return;
panel.Children.Clear();
if (panel.ContextMenu != null)
{
@@ -627,6 +851,17 @@ namespace HandyControl.Controls
}
}
/// <summary>
/// 清除
/// </summary>
public static void ClearGlobal()
{
if (GrowlWindow == null) return;
Clear(GrowlWindow.GrowlPanel);
GrowlWindow.Close();
GrowlWindow = null;
}
private void ButtonCancel_OnClick(object sender, RoutedEventArgs e)
{
if (ActionBeforeClose?.Invoke(false) == true)
@@ -0,0 +1,34 @@
using System.Windows;
using System.Windows.Controls;
namespace HandyControl.Controls
{
[TemplatePart(Name = ElementGrowPanel, Type = typeof(Panel))]
internal class GrowlWindow : Window
{
private const string ElementGrowPanel = "PART_GrowPanel";
public Panel GrowlPanel { get; set; }
public GrowlWindow()
{
WindowStyle = WindowStyle.None;
AllowsTransparency = true;
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
GrowlPanel = GetTemplateChild(ElementGrowPanel) as Panel;
}
public void Init()
{
var desktopWorkingArea = SystemParameters.WorkArea;
Height = desktopWorkingArea.Height;
Left = desktopWorkingArea.Right - Width;
Top = 0;
}
}
}
@@ -83,6 +83,8 @@ namespace HandyControl.Controls
StartAnimate();
}
};
Unloaded += (s, e) => Dispose();
}
public GifImage(string filename)
@@ -25,7 +25,7 @@ namespace HandyControl.Controls
public ImageBlock()
{
_dispatcherTimer = new DispatcherTimer
_dispatcherTimer = new DispatcherTimer(DispatcherPriority.Render)
{
Interval = Interval
};
@@ -187,4 +187,4 @@ namespace HandyControl.Controls
return rect;
}
}
}
}
@@ -43,10 +43,10 @@ namespace HandyControl.Controls
{
CommandBindings.Add(new CommandBinding(ControlCommands.Clear, (s, e) =>
{
ClearValue(SelectedValueProperty);
ClearValue(SelectedItemProperty);
ClearValue(SelectedIndexProperty);
ClearValue(TextProperty);
SetCurrentValue(SelectedValueProperty, null);
SetCurrentValue(SelectedItemProperty, null);
SetCurrentValue(SelectedIndexProperty, -1);
SetCurrentValue(TextProperty, "");
}));
}
@@ -85,7 +85,7 @@ namespace HandyControl.Controls
UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,
Mode = BindingMode.OneWayToSource,
#if !netle40
Delay = 500,
Delay = 500,
#endif
Source = this
});
@@ -20,8 +20,8 @@ namespace HandyControl.Controls
{
CommandBindings.Add(new CommandBinding(ControlCommands.Clear, (s, e) =>
{
ClearValue(SelectedDateProperty);
ClearValue(TextProperty);
SetCurrentValue(SelectedDateProperty, null);
SetCurrentValue(TextProperty, "");
}));
}
@@ -82,8 +82,8 @@ namespace HandyControl.Controls
InitCalendarWithClock();
CommandBindings.Add(new CommandBinding(ControlCommands.Clear, (s, e) =>
{
ClearValue(SelectedDateTimeProperty);
ClearValue(TextProperty);
SetCurrentValue(SelectedDateTimeProperty, null);
SetCurrentValue(TextProperty, "");
_textBox.Text = string.Empty;
}));
}
@@ -147,7 +147,6 @@ namespace HandyControl.Controls
dp._calendarWithClock.Focus();
});
}
}
}
@@ -43,7 +43,7 @@ namespace HandyControl.Controls
}));
CommandBindings.Add(new CommandBinding(ControlCommands.Clear, (s, e) =>
{
ClearValue(ValueProperty);
SetCurrentValue(ValueProperty, 0d);
_textBox.Text = string.Empty;
}));
@@ -65,7 +65,8 @@ namespace HandyControl.Controls
{
if (_textBox != null)
{
_textBox.TextChanged -= TextBox_TextChanged;
TextCompositionManager.RemovePreviewTextInputHandler(_textBox, PreviewTextInputHandler);
_textBox.TextChanged -= _textBox_TextChanged;
_textBox.PreviewKeyDown -= TextBox_PreviewKeyDown;
_textBox.LostFocus -= TextBox_LostFocus;
}
@@ -76,13 +77,27 @@ namespace HandyControl.Controls
if (_textBox != null)
{
_textBox.TextChanged += TextBox_TextChanged;
TextCompositionManager.AddPreviewTextInputHandler(_textBox, PreviewTextInputHandler);
_textBox.TextChanged += _textBox_TextChanged;
_textBox.PreviewKeyDown += TextBox_PreviewKeyDown;
_textBox.LostFocus += TextBox_LostFocus;
_textBox.Text = CurrentText;
}
}
private void _textBox_TextChanged(object sender, TextChangedEventArgs e) => UpdateData();
private void UpdateData()
{
if (!VerifyData()) return;
if (double.TryParse(_textBox.Text, out var value))
{
Value = value;
}
}
private void PreviewTextInputHandler(object sender, TextCompositionEventArgs e) => UpdateData();
private void TextBox_LostFocus(object sender, RoutedEventArgs e)
{
if (IsError) return;
@@ -103,15 +118,6 @@ namespace HandyControl.Controls
}
}
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
if (!VerifyData()) return;
if (double.TryParse(_textBox.Text, out var value))
{
Value = value;
}
}
protected override void OnMouseWheel(MouseWheelEventArgs e)
{
base.OnMouseWheel(e);
@@ -52,14 +52,16 @@ namespace HandyControl.Controls
Info = Text
});
if (Command == null) return;
if (Command is RoutedCommand command)
switch (Command)
{
command.Execute(CommandParameter, CommandTarget);
}
else
{
Command.Execute(CommandParameter);
case null:
return;
case RoutedCommand command:
command.Execute(CommandParameter, CommandTarget);
break;
default:
Command.Execute(CommandParameter);
break;
}
}
@@ -15,7 +15,7 @@ namespace HandyControl.Controls
{
CommandBindings.Add(new CommandBinding(ControlCommands.Clear, (s, e) =>
{
ClearValue(TextProperty);
SetCurrentValue(TextProperty, "");
}));
}
@@ -80,8 +80,8 @@ namespace HandyControl.Controls
Clock = new Clock();
CommandBindings.Add(new CommandBinding(ControlCommands.Clear, (s, e) =>
{
ClearValue(SelectedTimeProperty);
ClearValue(TextProperty);
SetCurrentValue(SelectedTimeProperty, null);
SetCurrentValue(TextProperty, "");
_textBox.Text = string.Empty;
}));
}
@@ -261,7 +261,7 @@ namespace HandyControl.Controls
public bool IsError
{
get => (bool) GetValue(IsErrorProperty);
get => (bool)GetValue(IsErrorProperty);
set => SetValue(IsErrorProperty, value);
}
@@ -270,7 +270,7 @@ namespace HandyControl.Controls
public string ErrorStr
{
get => (string) GetValue(ErrorStrProperty);
get => (string)GetValue(ErrorStrProperty);
set => SetValue(ErrorStrProperty, value);
}
@@ -279,7 +279,7 @@ namespace HandyControl.Controls
public TextType TextType
{
get => (TextType) GetValue(TextTypeProperty);
get => (TextType)GetValue(TextTypeProperty);
set => SetValue(TextTypeProperty, value);
}
@@ -288,7 +288,7 @@ namespace HandyControl.Controls
public bool ShowClearButton
{
get => (bool) GetValue(ShowClearButtonProperty);
get => (bool)GetValue(ShowClearButtonProperty);
set => SetValue(ShowClearButtonProperty, value);
}
@@ -297,7 +297,7 @@ namespace HandyControl.Controls
private static void OnClockChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var ctl = (TimePicker) d;
var ctl = (TimePicker)d;
var oldClock = e.OldValue as ClockBase;
var newClock = e.NewValue as ClockBase;
@@ -317,7 +317,7 @@ namespace HandyControl.Controls
public ClockBase Clock
{
get => (ClockBase) GetValue(ClockProperty);
get => (ClockBase)GetValue(ClockProperty);
set => SetValue(ClockProperty, value);
}
@@ -497,29 +497,29 @@ namespace HandyControl.Controls
switch (e.Key)
{
case Key.System:
{
switch (e.SystemKey)
{
case Key.Down:
switch (e.SystemKey)
{
if ((Keyboard.Modifiers & ModifierKeys.Alt) == ModifierKeys.Alt)
{
TogglePopUp();
return true;
}
case Key.Down:
{
if ((Keyboard.Modifiers & ModifierKeys.Alt) == ModifierKeys.Alt)
{
TogglePopUp();
return true;
}
break;
break;
}
}
break;
}
break;
}
case Key.Enter:
{
SetSelectedTime();
return true;
}
{
SetSelectedTime();
return true;
}
}
return false;
@@ -644,7 +644,7 @@ namespace HandyControl.Controls
if (SelectedTime != null)
{
var newtext = DateTimeToString((DateTime) SelectedTime);
var newtext = DateTimeToString((DateTime)SelectedTime);
SafeSetText(newtext);
return SelectedTime;
}
@@ -12,8 +12,6 @@ namespace HandyControl.Controls
{
public class AnimationPath : Shape
{
private bool _isLoaded;
/// <summary>
/// 故事板
/// </summary>
@@ -126,15 +124,7 @@ namespace HandyControl.Controls
OnPropertiesChanged));
}
public AnimationPath()
{
Loaded += (s, e) =>
{
if (_isLoaded) return;
UpdatePath();
_isLoaded = true;
};
}
public AnimationPath() => Loaded += (s, e) => UpdatePath();
/// <summary>
/// 动画完成事件
@@ -213,15 +213,8 @@ namespace HandyControl.Controls
_panelPage.Children.Add(CreatePateButton());
}
if (index == -1)
{
if (count > 0)
{
var button = _panelPage.Children[0];
button.RaiseEvent(new RoutedEventArgs(ButtonBase.ClickEvent, button));
}
}
else if (index >= 0 && index < count)
if (index == -1 && count > 0) index = 0;
if (index >= 0 && index < count)
{
var button = _panelPage.Children[index];
button.RaiseEvent(new RoutedEventArgs(ButtonBase.ClickEvent, button));
@@ -109,7 +109,7 @@ namespace HandyControl.Controls
if (string.IsNullOrEmpty(token))
{
window = VisualHelper.GetActiveWindow();
window = WindowHelper.GetActiveWindow();
}
else
{
@@ -146,7 +146,7 @@ namespace HandyControl.Controls
{
if (string.IsNullOrEmpty(_token))
{
Close(VisualHelper.GetActiveWindow());
Close(WindowHelper.GetActiveWindow());
}
else if (WindowDic.TryGetValue(_token, out var window))
{
@@ -0,0 +1,82 @@
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using HandyControl.Data;
namespace HandyControl.Controls
{
public class Divider : Control
{
public static readonly DependencyProperty ContentProperty = DependencyProperty.Register(
"Content", typeof(object), typeof(Divider), new PropertyMetadata(default(object)));
public object Content
{
get => GetValue(ContentProperty);
set => SetValue(ContentProperty, value);
}
public static readonly DependencyProperty OrientationProperty = DependencyProperty.Register(
"Orientation", typeof(Orientation), typeof(Divider), new PropertyMetadata(default(Orientation)));
public Orientation Orientation
{
get => (Orientation) GetValue(OrientationProperty);
set => SetValue(OrientationProperty, value);
}
public static readonly DependencyProperty ContentTemplateProperty = DependencyProperty.Register(
"ContentTemplate", typeof(DataTemplate), typeof(Divider), new PropertyMetadata(default(DataTemplate)));
public DataTemplate ContentTemplate
{
get => (DataTemplate) GetValue(ContentTemplateProperty);
set => SetValue(ContentTemplateProperty, value);
}
public static readonly DependencyProperty ContentStringFormatProperty = DependencyProperty.Register(
"ContentStringFormat", typeof(string), typeof(Divider), new PropertyMetadata(default(string)));
public string ContentStringFormat
{
get => (string) GetValue(ContentStringFormatProperty);
set => SetValue(ContentStringFormatProperty, value);
}
public static readonly DependencyProperty ContentTemplateSelectorProperty = DependencyProperty.Register(
"ContentTemplateSelector", typeof(DataTemplateSelector), typeof(Divider), new PropertyMetadata(default(DataTemplateSelector)));
public DataTemplateSelector ContentTemplateSelector
{
get => (DataTemplateSelector) GetValue(ContentTemplateSelectorProperty);
set => SetValue(ContentTemplateSelectorProperty, value);
}
public static readonly DependencyProperty LineStrokeProperty = DependencyProperty.Register(
"LineStroke", typeof(Brush), typeof(Divider), new PropertyMetadata(default(Brush)));
public Brush LineStroke
{
get => (Brush) GetValue(LineStrokeProperty);
set => SetValue(LineStrokeProperty, value);
}
public static readonly DependencyProperty LineStrokeThicknessProperty = DependencyProperty.Register(
"LineStrokeThickness", typeof(double), typeof(Divider), new PropertyMetadata(ValueBoxes.Double1Box));
public double LineStrokeThickness
{
get => (double) GetValue(LineStrokeThicknessProperty);
set => SetValue(LineStrokeThicknessProperty, value);
}
public static readonly DependencyProperty LineStrokeDashArrayProperty = DependencyProperty.Register(
"LineStrokeDashArray", typeof(DoubleCollection), typeof(Divider), new PropertyMetadata(new DoubleCollection()));
public DoubleCollection LineStrokeDashArray
{
get => (DoubleCollection) GetValue(LineStrokeDashArrayProperty);
set => SetValue(LineStrokeDashArrayProperty, value);
}
}
}
@@ -0,0 +1,154 @@
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Threading;
using HandyControl.Data;
using HandyControl.Tools;
namespace HandyControl.Controls
{
public sealed class Notification : System.Windows.Window
{
private const int WaitTime = 6;
/// <summary>
/// 计数
/// </summary>
private int _tickCount;
/// <summary>
/// 关闭计时器
/// </summary>
private DispatcherTimer _timerClose;
private ShowAnimation ShowAnimation { get; set; }
private bool _shouldBeClosed;
public Notification()
{
WindowStyle = WindowStyle.None;
AllowsTransparency = true;
}
public static Notification Show(object content, ShowAnimation showAnimation = ShowAnimation.None, bool staysOpen = false)
{
var notification = new Notification
{
Content = content,
Opacity = 0,
ShowAnimation = showAnimation
};
notification.Show();
var desktopWorkingArea = SystemParameters.WorkArea;
var leftMax = desktopWorkingArea.Width - notification.ActualWidth;
var topMax = desktopWorkingArea.Height - notification.ActualHeight;
switch (showAnimation)
{
case ShowAnimation.None:
notification.Opacity = 1;
notification.Left = leftMax;
notification.Top = topMax;
break;
case ShowAnimation.HorizontalMove:
notification.Opacity = 1;
notification.Left = desktopWorkingArea.Width;
notification.Top = topMax;
notification.BeginAnimation(LeftProperty, AnimationHelper.CreateAnimation(leftMax));
break;
case ShowAnimation.VerticalMove:
notification.Opacity = 1;
notification.Left = leftMax;
notification.Top = desktopWorkingArea.Height;
notification.BeginAnimation(TopProperty, AnimationHelper.CreateAnimation(topMax));
break;
case ShowAnimation.Fade:
notification.Left = leftMax;
notification.Top = topMax;
notification.BeginAnimation(OpacityProperty, AnimationHelper.CreateAnimation(1));
break;
default:
notification.Opacity = 1;
notification.Left = leftMax;
notification.Top = topMax;
break;
}
if (!staysOpen) notification.StartTimer();
return notification;
}
protected override void OnClosing(CancelEventArgs e)
{
base.OnClosing(e);
if (_shouldBeClosed)
{
return;
}
var desktopWorkingArea = SystemParameters.WorkArea;
switch (ShowAnimation)
{
case ShowAnimation.None:
break;
case ShowAnimation.HorizontalMove:
{
var animation = AnimationHelper.CreateAnimation(desktopWorkingArea.Width);
animation.Completed += Animation_Completed;
BeginAnimation(LeftProperty, animation);
e.Cancel = true;
_shouldBeClosed = true;
}
break;
case ShowAnimation.VerticalMove:
{
var animation = AnimationHelper.CreateAnimation(desktopWorkingArea.Height);
animation.Completed += Animation_Completed;
BeginAnimation(TopProperty, animation);
e.Cancel = true;
_shouldBeClosed = true;
}
break;
case ShowAnimation.Fade:
{
var animation = AnimationHelper.CreateAnimation(0);
animation.Completed += Animation_Completed;
BeginAnimation(OpacityProperty, animation);
e.Cancel = true;
_shouldBeClosed = true;
}
break;
}
}
private void Animation_Completed(object sender, EventArgs e) => Close();
/// <summary>
/// 开始计时器
/// </summary>
private void StartTimer()
{
_timerClose = new DispatcherTimer
{
Interval = TimeSpan.FromSeconds(1)
};
_timerClose.Tick += delegate
{
if (IsMouseOver)
{
_tickCount = 0;
return;
}
_tickCount++;
if (_tickCount >= WaitTime) Close();
};
_timerClose.Start();
}
}
}
@@ -1,11 +1,12 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Threading;
using HandyControl.Data;
@@ -24,8 +25,6 @@ namespace HandyControl.Controls
private readonly int _id;
private static int NextId;
private ImageSource _icon;
private IntPtr _iconCurrentHandle;
@@ -56,6 +55,10 @@ namespace HandyControl.Controls
private bool _isDisposed;
private static int NextId;
private static readonly Dictionary<string, NotifyIcon> NotifyIconDic = new Dictionary<string, NotifyIcon>();
static NotifyIcon()
{
VisibilityProperty.OverrideMetadata(typeof(NotifyIcon), new PropertyMetadata(Visibility.Visible, OnVisibilityChanged));
@@ -111,6 +114,127 @@ namespace HandyControl.Controls
_dispatcherTimerPos.Tick += DispatcherTimerPos_Tick;
}
public static void Register(string token, NotifyIcon notifyIcon)
{
if (string.IsNullOrEmpty(token) || notifyIcon == null) return;
NotifyIconDic[token] = notifyIcon;
}
public static void Unregister(string token, NotifyIcon notifyIcon)
{
if (string.IsNullOrEmpty(token) || notifyIcon == null) return;
if (NotifyIconDic.ContainsKey(token))
{
if (ReferenceEquals(NotifyIconDic[token], notifyIcon))
{
NotifyIconDic.Remove(token);
}
}
}
public static void Unregister(NotifyIcon notifyIcon)
{
if (notifyIcon == null) return;
var first = NotifyIconDic.FirstOrDefault(item => ReferenceEquals(notifyIcon, item.Value));
if (!string.IsNullOrEmpty(first.Key))
{
NotifyIconDic.Remove(first.Key);
}
}
public static void Unregister(string token)
{
if (string.IsNullOrEmpty(token)) return;
if (NotifyIconDic.ContainsKey(token))
{
NotifyIconDic.Remove(token);
}
}
public static void ShowBalloonTip(string title, string content, NotifyIconInfoType infoType, string token)
{
if (NotifyIconDic.TryGetValue(token, out var notifyIcon))
{
notifyIcon.ShowBalloonTip(title, content, infoType);
}
}
public void ShowBalloonTip(string title, string content, NotifyIconInfoType infoType)
{
if (!_added || DesignerHelper.IsInDesignMode) return;
var data = new NOTIFYICONDATA
{
uFlags = NativeMethods.NIF_INFO,
hWnd = _messageWindowHandle,
uID = _id,
szInfoTitle = title ?? string.Empty,
szInfo = content ?? string.Empty
};
switch (infoType)
{
case NotifyIconInfoType.Info:
data.dwInfoFlags = NativeMethods.NIIF_INFO;
break;
case NotifyIconInfoType.Warning:
data.dwInfoFlags = NativeMethods.NIIF_WARNING;
break;
case NotifyIconInfoType.Error:
data.dwInfoFlags = NativeMethods.NIIF_ERROR;
break;
case NotifyIconInfoType.None:
data.dwInfoFlags = NativeMethods.NIIF_NONE;
break;
}
UnsafeNativeMethods.Shell_NotifyIcon(NativeMethods.NIM_MODIFY, data);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
public void CloseContextControl()
{
if (_contextContent != null)
{
_contextContent.IsOpen = false;
}
else if (ContextMenu != null)
{
ContextMenu.IsOpen = false;
}
}
public static readonly DependencyProperty TokenProperty = DependencyProperty.Register(
"Token", typeof(string), typeof(NotifyIcon), new PropertyMetadata(default(string), OnTokenChanged));
private static void OnTokenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is NotifyIcon notifyIcon)
{
if (e.NewValue == null)
{
Unregister(notifyIcon);
}
else
{
Register(e.NewValue.ToString(), notifyIcon);
}
}
}
public string Token
{
get => (string) GetValue(TokenProperty);
set => SetValue(TokenProperty, value);
}
public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
"Text", typeof(string), typeof(NotifyIcon), new PropertyMetadata(default(string)));
@@ -190,6 +314,12 @@ namespace HandyControl.Controls
}
}
public bool IsBlink
{
get => (bool)GetValue(IsBlinkProperty);
set => SetValue(IsBlinkProperty, value);
}
private void DispatcherTimerBlinkTick(object sender, EventArgs e)
{
if (Visibility != Visibility.Visible || _iconCurrentHandle == IntPtr.Zero) return;
@@ -341,12 +471,6 @@ namespace HandyControl.Controls
return isFind;
}
public bool IsBlink
{
get => (bool) GetValue(IsBlinkProperty);
set => SetValue(IsBlinkProperty, value);
}
private void OnIconChanged()
{
if (_icon != null)
@@ -508,26 +632,14 @@ namespace HandyControl.Controls
Content = ContextContent
};
_contextContent.IsOpen = true;
var handle = IntPtr.Zero;
var hwndSource = (HwndSource)PresentationSource.FromVisual(_contextContent.Child);
if (hwndSource != null)
{
handle = hwndSource.Handle;
}
UnsafeNativeMethods.SetForegroundWindow(handle);
UnsafeNativeMethods.SetForegroundWindow(_contextContent.Child.GetHandle());
}
else if (ContextMenu != null)
{
ContextMenu.Placement = PlacementMode.Mouse;
ContextMenu.IsOpen = true;
var handle = IntPtr.Zero;
var hwndSource = (HwndSource)PresentationSource.FromVisual(ContextMenu);
if (hwndSource != null)
{
handle = hwndSource.Handle;
}
UnsafeNativeMethods.SetForegroundWindow(handle);
UnsafeNativeMethods.SetForegroundWindow(ContextMenu.GetHandle());
}
}
@@ -565,23 +677,5 @@ namespace HandyControl.Controls
_isDisposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
public void CloseContextControl()
{
if (_contextContent != null)
{
_contextContent.IsOpen = false;
}
else if (ContextMenu != null)
{
ContextMenu.IsOpen = false;
}
}
}
}
@@ -0,0 +1,64 @@
using System.Windows;
using System.Windows.Input;
namespace HandyControl.Controls
{
public sealed class Sprite : System.Windows.Window
{
private bool _isLeftButtonPressed;
private double _leftMax;
private double _topMax;
private Sprite()
{
WindowStyle = WindowStyle.None;
AllowsTransparency = true;
InputManager.Current.PostProcessInput += Current_PostProcessInput;
}
private void Current_PostProcessInput(object sender, ProcessInputEventArgs e)
{
if (Mouse.LeftButton == MouseButtonState.Pressed)
{
_isLeftButtonPressed = true;
}
else if(_isLeftButtonPressed)
{
if (Left < 0)
{
Left = 0;
}
if (Left > _leftMax)
{
Left = _leftMax;
}
if (Top > _topMax)
{
Top = _topMax;
}
}
}
public static Sprite Show(object content)
{
var sprite = new Sprite
{
Content = content
};
sprite.Show();
var desktopWorkingArea = SystemParameters.WorkArea;
sprite._leftMax = desktopWorkingArea.Width - sprite.ActualWidth;
sprite._topMax = desktopWorkingArea.Height - sprite.ActualHeight;
sprite.Left = sprite._leftMax - 50;
sprite.Top = 50 - sprite.Padding.Top;
return sprite;
}
}
}
@@ -4,6 +4,7 @@ using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Markup;
using System.Windows.Media.Animation;
using HandyControl.Data;
using HandyControl.Tools;
@@ -14,7 +15,8 @@ namespace HandyControl.Controls
[TemplateVisualState(GroupName = PresentationGroup, Name = DefaultTransitionState)]
[TemplatePart(Name = PreviousContentPresentationSitePartName, Type = typeof(ContentControl))]
[TemplatePart(Name = CurrentContentPresentationSitePartName, Type = typeof(ContentControl))]
public class TransitioningContentControl : ContentControl
[ContentProperty("Content")]
public class TransitioningContentControl : Control
{
private Storyboard _currentTransition;
@@ -76,11 +78,28 @@ namespace HandyControl.Controls
VisualStateManager.GoToState(this, Transition, true);
}
protected override void OnContentChanged(object oldContent, object newContent)
{
base.OnContentChanged(oldContent, newContent);
public static readonly DependencyProperty ContentProperty = DependencyProperty.Register(
"Content", typeof(object), typeof(TransitioningContentControl), new PropertyMetadata(default(object), OnContentChanged));
StartTransition(oldContent, newContent);
private static void OnContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var ctl = (TransitioningContentControl) d;
ctl.StartTransition(e.OldValue, e.NewValue);
}
public static readonly DependencyProperty ContentTemplateProperty = DependencyProperty.Register(
"ContentTemplate", typeof(DataTemplate), typeof(TransitioningContentControl), new PropertyMetadata(default(DataTemplate)));
public DataTemplate ContentTemplate
{
get => (DataTemplate) GetValue(ContentTemplateProperty);
set => SetValue(ContentTemplateProperty, value);
}
public object Content
{
get => GetValue(ContentProperty);
set => SetValue(ContentProperty, value);
}
[SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "newContent", Justification = "Should be used in the future.")]
@@ -35,18 +35,28 @@ namespace HandyControl.Controls
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 newSize = new Size(Diameter, Diameter);
foreach (UIElement element in Children)
{
element.Measure(newSize);
}
return newSize;
}
protected override Size ArrangeOverride(Size finalSize)
{
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;
@@ -60,11 +70,12 @@ namespace HandyControl.Controls
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;
var rectX = x + finalSize.Width / 2 - centerX;
var rectY = y + finalSize.Height / 2 - centerY;
element.Arrange(new Rect(rectX, rectY, element.DesiredSize.Width, element.DesiredSize.Height));
}
return availableSize;
return finalSize;
}
}
}
@@ -0,0 +1,166 @@
using System;
using System.Windows;
using System.Windows.Controls;
namespace HandyControl.Controls
{
public class HoneycombPanel : Panel
{
private double _unitLength;
private HoneycombStuffer _stuffer;
private static int GetXCount(int count)
{
if (count == 0) return 0;
count -= 1;
var index = (int) Math.Floor(Math.Pow((12.0 * count + 25) / 36, 0.5) - 5.0 / 6);
var valeIndex = 3 * index * index + 5 * index;
var centerValue = valeIndex + 2;
return count >= centerValue
? 4 * index + 6
: count > valeIndex
? 4 * index + 4
: 4 * index + 2;
}
private static int GetYCount(int count)
{
if (count == 0) return 0;
count -= 1;
var index = (int)Math.Floor(Math.Pow(count / 3.0 + 0.25, 0.5) - 0.5);
var valeIndex = 3 * index * index + 3 * index;
return count > valeIndex
? 2 * index + 2
: 2 * index;
}
/*
* layout order
*
* ● ●
* (7) (8)
*
* ● ● ●
* (6) (1) (9)
*
* ● ● ● ...
* (5) (0) (2)
*
* ● ● ...
* (4) (3)
*
*/
protected override Size MeasureOverride(Size availableSize)
{
var maxSize = new Size();
foreach (UIElement child in InternalChildren)
{
if (child != null)
{
child.Measure(availableSize);
maxSize.Width = Math.Max(maxSize.Width, child.DesiredSize.Width);
maxSize.Height = Math.Max(maxSize.Height, child.DesiredSize.Height);
}
}
_unitLength = Math.Max(maxSize.Width, maxSize.Height) / 2;
var xCount = GetXCount(InternalChildren.Count);
var yCount = GetYCount(InternalChildren.Count);
var availableWidth = xCount * _unitLength;
var availableHeight = yCount * Math.Pow(3, 0.5) * _unitLength + _unitLength * 2;
return new Size(availableWidth, availableHeight);
}
protected override Size ArrangeOverride(Size finalSize)
{
var childLength = _unitLength * 2;
_stuffer = new HoneycombStuffer(new Rect(finalSize.Width / 2 - _unitLength,
finalSize.Height / 2 - _unitLength, childLength, childLength));
foreach (UIElement child in InternalChildren)
{
child.Arrange(_stuffer.Move());
}
return finalSize;
}
private class HoneycombStuffer
{
private int _turns;
private int _maxIndex;
private int _currentIndex = -1;
private readonly double _offsetX;
private readonly double _offsetY;
private Rect _childBounds;
private readonly double[] _offsetXArr;
private readonly double[] _offsetYArr;
public HoneycombStuffer(Rect childBounds)
{
_childBounds = childBounds;
_offsetX = childBounds.Width / 2;
_offsetY = Math.Pow(3, 0.5) * _offsetX;
_offsetXArr = new[]
{
2 * _offsetX,
_offsetX,
-_offsetX,
-2 * _offsetX,
-_offsetX,
_offsetX
};
_offsetYArr = new[]
{
0,
_offsetY,
_offsetY,
0,
-_offsetY,
-_offsetY
};
}
public Rect Move()
{
_currentIndex++;
if (_currentIndex > _maxIndex)
{
_turns++;
_maxIndex = _turns * 6 - 1;
_currentIndex = 0;
_childBounds.Offset(_offsetX, -_offsetY);
return _childBounds;
}
if (_turns > 0)
{
var index = _currentIndex / _turns;
_childBounds.Offset(_offsetXArr[index], _offsetYArr[index]);
}
return _childBounds;
}
}
}
}
@@ -1,4 +1,5 @@
using System.Linq;
using System;
using System.Linq;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
@@ -31,7 +32,15 @@ namespace HandyControl.Controls
"DefaultValue", typeof(double), typeof(Rate), new PropertyMetadata(ValueBoxes.Double0Box));
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
"Value", typeof(double), typeof(Rate), new PropertyMetadata(ValueBoxes.Double0Box));
"Value", typeof(double), typeof(Rate), new PropertyMetadata(ValueBoxes.Double0Box, OnValueChanged));
private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) =>
((Rate) d).OnValueChanged(new FunctionEventArgs<double>(ValueChangedEvent, d)
{
Info = (double)e.NewValue
});
protected virtual void OnValueChanged(FunctionEventArgs<double> e) => RaiseEvent(e);
public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
"Text", typeof(string), typeof(Rate), new PropertyMetadata(default(string)));
@@ -44,6 +53,22 @@ namespace HandyControl.Controls
private bool _isLoaded;
private bool _updateItems;
#region Public Events
public static readonly RoutedEvent ValueChangedEvent =
EventManager.RegisterRoutedEvent("ValueChanged", RoutingStrategy.Bubble,
typeof(EventHandler<FunctionEventArgs<double>>), typeof(Rate));
public event EventHandler<FunctionEventArgs<double>> ValueChanged
{
add => AddHandler(ValueChangedEvent, value);
remove => RemoveHandler(ValueChangedEvent, value);
}
#endregion Public Events
public Rate()
{
AddHandler(RateItem.SelectedChangedEvent, new RoutedEventHandler(RateItemSelectedChanged));
@@ -52,8 +77,15 @@ namespace HandyControl.Controls
Loaded += (s, e) =>
{
if (DesignerHelper.IsInDesignMode) return;
_updateItems = false;
OnApplyTemplateInternal();
_updateItems = true;
UpdateItems();
if (_isLoaded) return;
_isLoaded = true;
if (Value <= 0)
{
if (DefaultValue > 0)
@@ -123,11 +155,8 @@ namespace HandyControl.Controls
set => SetValue(IsReadOnlyProperty, value);
}
private void RateItemValueChanged(object sender, RoutedEventArgs e)
{
Value =
(from RateItem item in Items where item.IsSelected select item.IsHalf ? 0.5 : 1).Sum();
}
private void RateItemValueChanged(object sender, RoutedEventArgs e) =>
Value = (from RateItem item in Items where item.IsSelected select item.IsHalf ? 0.5 : 1).Sum();
private void RateItemSelectedChanged(object sender, RoutedEventArgs e)
{
@@ -154,29 +183,32 @@ namespace HandyControl.Controls
}
}
protected override bool IsItemItsOwnContainerOverride(object item)
{
return item is RateItem;
}
protected override bool IsItemItsOwnContainerOverride(object item) => item is RateItem;
protected override DependencyObject GetContainerForItemOverride()
protected override DependencyObject GetContainerForItemOverride() => new RateItem();
private void OnApplyTemplateInternal()
{
return new RateItem();
Items.Clear();
for (var i = 1; i <= Count; i++)
{
var item = new RateItem
{
Index = i
};
Items.Add(item);
}
}
public override void OnApplyTemplate()
{
if (!_isLoaded)
{
Items.Clear();
for (var i = 1; i <= Count; i++)
{
Items.Add(new RateItem
{
Index = i
});
}
_updateItems = true;
OnApplyTemplateInternal();
_updateItems = false;
}
base.OnApplyTemplate();
@@ -191,7 +223,7 @@ namespace HandyControl.Controls
protected override void UpdateItems()
{
if (!_isLoaded) return;
if (!_isLoaded || !_updateItems) return;
var count = (int) Value;
for (var i = 0; i < count; i++)
@@ -224,9 +256,6 @@ namespace HandyControl.Controls
}
}
public void Reset()
{
Value = DefaultValue;
}
public void Reset() => Value = DefaultValue;
}
}
@@ -46,7 +46,13 @@ namespace HandyControl.Controls
public RateItem()
{
Loaded += (s, e) => _isLoaded = true;
Loaded += (s, e) =>
{
if (_isLoaded) return;
_isLoaded = true;
OnApplyTemplate();
};
}
public bool AllowClear
@@ -87,7 +93,7 @@ namespace HandyControl.Controls
if (_isHalf == value) return;
_isHalf = value;
if (_icon == null) return;
_icon.Width = value ? ActualWidth / 2 : ActualWidth;
_icon.Width = value ? Width / 2 : Width;
}
}
@@ -134,7 +140,7 @@ namespace HandyControl.Controls
if (IsReadOnly) return;
if (!AllowHalf) return;
var p = e.GetPosition(this);
IsHalf = p.X < ActualWidth / 2;
IsHalf = p.X < Width / 2;
}
public override void OnApplyTemplate()
@@ -147,7 +153,7 @@ namespace HandyControl.Controls
{
if (_icon == null) return;
_icon.Show(IsSelected);
_icon.Width = IsHalf ? ActualWidth / 2 : ActualWidth;
_icon.Width = IsHalf ? Width / 2 : Width;
}
}
@@ -202,7 +208,7 @@ namespace HandyControl.Controls
if (AllowHalf)
{
var p = e.GetPosition(this);
IsHalf = p.X < ActualWidth / 2;
IsHalf = p.X < Width / 2;
}
}
}
@@ -1,4 +1,5 @@
using System.Linq;
using System;
using System.Linq;
using System.Windows;
using System.Windows.Data;
using System.Windows.Input;
@@ -7,7 +8,7 @@ using HandyControl.Tools.Extension;
namespace HandyControl.Controls
{
public class SideMenuItem : HeaderedSimpleItemsControl, ISelectable
public class SideMenuItem : HeaderedSimpleItemsControl, ISelectable, ICommandSource
{
private bool _isMouseLeftButtonDown;
@@ -68,7 +69,22 @@ namespace HandyControl.Controls
}
}
protected virtual void OnSelected(RoutedEventArgs e) => RaiseEvent(e);
protected virtual void OnSelected(RoutedEventArgs e)
{
RaiseEvent(e);
switch (Command)
{
case null:
return;
case RoutedCommand command:
command.Execute(CommandParameter, CommandTarget);
break;
default:
Command.Execute(CommandParameter);
break;
}
}
public static readonly RoutedEvent SelectedEvent =
EventManager.RegisterRoutedEvent("Selected", RoutingStrategy.Bubble,
@@ -148,5 +164,54 @@ namespace HandyControl.Controls
ItemsHost.Show(isShow);
}
}
public static readonly DependencyProperty CommandProperty = DependencyProperty.Register(
"Command", typeof(ICommand), typeof(SideMenuItem), new PropertyMetadata(default(ICommand), OnCommandChanged));
private static void OnCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var ctl = (SideMenuItem)d;
if (e.OldValue is ICommand oldCommand)
{
oldCommand.CanExecuteChanged -= ctl.CanExecuteChanged;
}
if (e.NewValue is ICommand newCommand)
{
newCommand.CanExecuteChanged += ctl.CanExecuteChanged;
}
}
public ICommand Command
{
get => (ICommand) GetValue(CommandProperty);
set => SetValue(CommandProperty, value);
}
public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.Register(
"CommandParameter", typeof(object), typeof(SideMenuItem), new PropertyMetadata(default(object)));
public object CommandParameter
{
get => GetValue(CommandParameterProperty);
set => SetValue(CommandParameterProperty, value);
}
public static readonly DependencyProperty CommandTargetProperty = DependencyProperty.Register(
"CommandTarget", typeof(IInputElement), typeof(SideMenuItem), new PropertyMetadata(default(IInputElement)));
public IInputElement CommandTarget
{
get => (IInputElement) GetValue(CommandTargetProperty);
set => SetValue(CommandTargetProperty, value);
}
private void CanExecuteChanged(object sender, EventArgs e)
{
if (Command == null) return;
IsEnabled = Command is RoutedCommand command
? command.CanExecute(CommandParameter, CommandTarget)
: Command.CanExecute(CommandParameter);
}
}
}
@@ -80,8 +80,14 @@ namespace HandyControl.Controls
/// <summary>
/// 是否显示关闭按钮
/// </summary>
public static readonly DependencyProperty ShowCloseButtonProperty = DependencyProperty.Register(
"ShowCloseButton", typeof(bool), typeof(TabControl), new PropertyMetadata(ValueBoxes.FalseBox));
public static readonly DependencyProperty ShowCloseButtonProperty = DependencyProperty.RegisterAttached(
"ShowCloseButton", typeof(bool), typeof(TabControl), new FrameworkPropertyMetadata(ValueBoxes.FalseBox, FrameworkPropertyMetadataOptions.Inherits));
public static void SetShowCloseButton(DependencyObject element, bool value)
=> element.SetValue(ShowCloseButtonProperty, value);
public static bool GetShowCloseButton(DependencyObject element)
=> (bool) element.GetValue(ShowCloseButtonProperty);
/// <summary>
/// 是否显示关闭按钮
@@ -92,6 +98,27 @@ namespace HandyControl.Controls
set => SetValue(ShowCloseButtonProperty, value);
}
/// <summary>
/// 是否显示上下文菜单
/// </summary>
public static readonly DependencyProperty ShowContextMenuProperty = DependencyProperty.RegisterAttached(
"ShowContextMenu", typeof(bool), typeof(TabControl), new FrameworkPropertyMetadata(ValueBoxes.TrueBox, FrameworkPropertyMetadataOptions.Inherits));
public static void SetShowContextMenu(DependencyObject element, bool value)
=> element.SetValue(ShowContextMenuProperty, value);
public static bool GetShowContextMenu(DependencyObject element)
=> (bool) element.GetValue(ShowContextMenuProperty);
/// <summary>
/// 是否显示上下文菜单
/// </summary>
public bool ShowContextMenu
{
get => (bool)GetValue(ShowContextMenuProperty);
set => SetValue(ShowContextMenuProperty, value);
}
/// <summary>
/// 是否将标签填充
/// </summary>
@@ -210,7 +237,7 @@ namespace HandyControl.Controls
}
if (IsEnableAnimation)
{
_headerPanel.ClearValue(TabPanel.FluidMoveDurationProperty);
_headerPanel.SetCurrentValue(TabPanel.FluidMoveDurationProperty, new Duration(TimeSpan.FromMilliseconds(200)));
}
else
{
@@ -311,7 +338,7 @@ namespace HandyControl.Controls
Items.Insert(0, item);
if (IsEnableAnimation)
{
_headerPanel.ClearValue(TabPanel.FluidMoveDurationProperty);
_headerPanel.SetCurrentValue(TabPanel.FluidMoveDurationProperty, new Duration(TimeSpan.FromMilliseconds(200)));
}
else
{
@@ -1,12 +1,14 @@
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using HandyControl.Data;
using HandyControl.Interactivity;
using HandyControl.Tools;
using HandyControl.Tools.Extension;
namespace HandyControl.Controls
{
@@ -112,6 +114,91 @@ namespace HandyControl.Controls
}
}
/// <summary>
/// 是否显示关闭按钮
/// </summary>
public static readonly DependencyProperty ShowCloseButtonProperty =
TabControl.ShowCloseButtonProperty.AddOwner(typeof(TabItem));
/// <summary>
/// 是否显示关闭按钮
/// </summary>
public bool ShowCloseButton
{
get => (bool)GetValue(ShowCloseButtonProperty);
set => SetValue(ShowCloseButtonProperty, value);
}
public static void SetShowCloseButton(DependencyObject element, bool value)
=> element.SetValue(ShowCloseButtonProperty, value);
public static bool GetShowCloseButton(DependencyObject element)
=> (bool)element.GetValue(ShowCloseButtonProperty);
/// <summary>
/// 是否显示上下文菜单
/// </summary>
public static readonly DependencyProperty ShowContextMenuProperty =
TabControl.ShowContextMenuProperty.AddOwner(typeof(TabItem), new FrameworkPropertyMetadata(OnShowContextMenuChanged));
private static void OnShowContextMenuChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var ctl = (TabItem) d;
if (ctl.Menu != null)
{
var show = (bool)e.NewValue;
ctl.Menu.IsEnabled = show;
ctl.Menu.Show(show);
}
}
/// <summary>
/// 是否显示上下文菜单
/// </summary>
public bool ShowContextMenu
{
get => (bool) GetValue(ShowContextMenuProperty);
set => SetValue(ShowContextMenuProperty, value);
}
public static void SetShowContextMenu(DependencyObject element, bool value)
=> element.SetValue(ShowContextMenuProperty, value);
public static bool GetShowContextMenu(DependencyObject element)
=> (bool)element.GetValue(ShowContextMenuProperty);
public static readonly DependencyProperty MenuProperty = DependencyProperty.Register(
"Menu", typeof(ContextMenu), typeof(TabItem), new PropertyMetadata(default(ContextMenu), OnMenuChanged));
private static void OnMenuChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var ctl = (TabItem) d;
ctl.OnMenuChanged(e.NewValue as ContextMenu);
}
private void OnMenuChanged(ContextMenu menu)
{
if (IsLoaded && menu != null)
{
menu.DataContext = this;
menu.SetBinding(IsEnabledProperty, new Binding(ShowContextMenuProperty.Name)
{
Source = this
});
menu.SetBinding(VisibilityProperty, new Binding(ShowContextMenuProperty.Name)
{
Source = this,
Converter = ResourceHelper.GetResource<IValueConverter>("Boolean2VisibilityConverter")
});
}
}
public ContextMenu Menu
{
get => (ContextMenu) GetValue(MenuProperty);
set => SetValue(MenuProperty, value);
}
/// <summary>
/// 更新选项卡横向偏移
/// </summary>
@@ -135,6 +222,8 @@ namespace HandyControl.Controls
(s, e) => { TabControlParent.CloseAllItems(); }));
CommandBindings.Add(new CommandBinding(ControlCommands.CloseOther,
(s, e) => { TabControlParent.CloseOtherItems(this); }));
Loaded += (s, e) => OnMenuChanged(Menu);
}
private TabControl TabControlParent => new Lazy<TabControl>(() => ItemsControl.ItemsControlFromItemContainer(this) as TabControl).Value;
@@ -146,20 +235,28 @@ namespace HandyControl.Controls
Focus();
}
protected override void OnHeaderChanged(object oldHeader, object newHeader)
{
base.OnHeaderChanged(oldHeader, newHeader);
if (TabPanel != null)
{
TabPanel.ForceUpdate = true;
InvalidateMeasure();
TabPanel.ForceUpdate = true;
}
}
internal void Close()
{
var argsClosing = new CancelRoutedEventArgs(ClosingEvent, this);
RaiseEvent(argsClosing);
if (argsClosing.Cancel) return;
if (TabControlParent.IsEnableAnimation)
{
TabPanel.ClearValue(TabPanel.FluidMoveDurationProperty);
}
else
{
TabPanel.FluidMoveDuration = new Duration(TimeSpan.FromSeconds(0));
}
TabPanel.SetCurrentValue(TabPanel.FluidMoveDurationProperty,
TabControlParent.IsEnableAnimation
? new Duration(TimeSpan.FromMilliseconds(200))
: new Duration(TimeSpan.FromMilliseconds(1)));
TabControlParent.IsInternalAction = true;
RaiseEvent(new RoutedEventArgs(ClosedEvent, this));
TabControlParent.Items.Remove(this);
@@ -1,5 +1,4 @@
using System.Runtime.InteropServices;
using System.Windows.Interop;
using System.Windows.Media;
using HandyControl.Data;
using HandyControl.Tools;
@@ -18,18 +17,8 @@ namespace HandyControl.Controls
internal static void EnableBlur(Window window)
{
var accentPolicy = new ExternDllHelper.ACCENTPOLICY();
var accentPolicySize = Marshal.SizeOf(accentPolicy);
if (SystemVersionInfo >= SystemVersionInfo.Windows10_1809)
{
accentPolicy.AccentState = ExternDllHelper.ACCENTSTATE.ACCENT_ENABLE_ACRYLICBLURBEHIND;
}
else if (SystemVersionInfo >= SystemVersionInfo.Windows10)
{
accentPolicy.AccentState = ExternDllHelper.ACCENTSTATE.ACCENT_ENABLE_BLURBEHIND;
}
else
if (SystemVersionInfo < SystemVersionInfo.Windows10 ||
SystemVersionInfo >= SystemVersionInfo.Windows10_1903)
{
var colorValue = ResourceHelper.GetResource<uint>(ResourceToken.BlurGradientValue);
var color = ColorHelper.ToColor(colorValue);
@@ -38,6 +27,13 @@ namespace HandyControl.Controls
return;
}
var accentPolicy = new ExternDllHelper.ACCENTPOLICY();
var accentPolicySize = Marshal.SizeOf(accentPolicy);
accentPolicy.AccentState = SystemVersionInfo < SystemVersionInfo.Windows10_1809
? ExternDllHelper.ACCENTSTATE.ACCENT_ENABLE_BLURBEHIND
: ExternDllHelper.ACCENTSTATE.ACCENT_ENABLE_ACRYLICBLURBEHIND;
accentPolicy.AccentFlags = 2;
accentPolicy.GradientColor = ResourceHelper.GetResource<uint>(ResourceToken.BlurGradientValue);
@@ -51,7 +47,7 @@ namespace HandyControl.Controls
Data = accentPtr
};
ExternDllHelper.SetWindowCompositionAttribute(new WindowInteropHelper(window).Handle, ref data);
ExternDllHelper.SetWindowCompositionAttribute(window.GetHandle(), ref data);
Marshal.FreeHGlobal(accentPtr);
}
@@ -267,7 +267,7 @@ namespace HandyControl.Controls
MessageBox messageBox = null;
Application.Current.Dispatcher.Invoke(new Action(() =>
{
messageBox = CreateMessageBox(null, info.MessageBoxText, info.Caption, info.Button, MessageBoxImage.None, info.DefaultResult);
messageBox = CreateMessageBox(null, info.Message, info.Caption, info.Button, MessageBoxImage.None, info.DefaultResult);
SetButtonStatus(messageBox, info.Button);
if (!string.IsNullOrEmpty(info.IconKey))
@@ -277,9 +277,9 @@ namespace HandyControl.Controls
messageBox.ImageBrush = ResourceHelper.GetResource<Brush>(info.IconBrushKey);
}
if (info.Style != null)
if (info.StyleKey != null)
{
messageBox.Style = info.Style;
messageBox.Style = ResourceHelper.GetResource<Style>(info.StyleKey);
}
SystemSounds.Asterisk.Play();
messageBox.ShowDialog();
@@ -348,7 +348,7 @@ namespace HandyControl.Controls
throw new InvalidEnumArgumentException(nameof(defaultResult), (int)defaultResult, typeof(MessageBoxResult));
}
var ownerWindow = owner ?? VisualHelper.GetActiveWindow();
var ownerWindow = owner ?? WindowHelper.GetActiveWindow();
var ownerIsNull = ownerWindow is null;
return new MessageBox