Merge branch 'master' into master

This commit is contained in:
NaBian authored and GitHub committed 2020-07-12 00:09:38 +08:00
commit ea8c8a9795
608 files changed
+11322 -6260

No files matched your search

@@ -9,7 +9,7 @@ namespace HandyControl.Collections
[Serializable]
public class ManualObservableCollection<T> : Collection<T>, INotifyCollectionChanged, INotifyPropertyChanged
{
private SimpleMonitor _monitor = new SimpleMonitor();
private readonly SimpleMonitor _monitor = new SimpleMonitor();
private const string CountString = "Count";
@@ -42,7 +42,7 @@ namespace HandyControl.Controls
}
public static void SetCircular(DependencyObject element, bool value)
=> element.SetValue(CircularProperty, value);
=> element.SetValue(CircularProperty, ValueBoxes.BooleanBox(value));
public static bool GetCircular(DependencyObject element)
=> (bool) element.GetValue(CircularProperty);
@@ -41,7 +41,7 @@ namespace HandyControl.Controls
}
public static void SetApplyDefaultStyle(DependencyObject element, bool value)
=> element.SetValue(ApplyDefaultStyleProperty, value);
=> element.SetValue(ApplyDefaultStyleProperty, ValueBoxes.BooleanBox(value));
public static bool GetApplyDefaultStyle(DependencyObject element)
=> (bool) element.GetValue(ApplyDefaultStyleProperty);
@@ -253,7 +253,7 @@ namespace HandyControl.Controls
public static bool GetShowRowNumber(DependencyObject target) => (bool)target.GetValue(ShowRowNumberProperty);
public static void SetShowRowNumber(DependencyObject target, bool value) => target.SetValue(ShowRowNumberProperty, value);
public static void SetShowRowNumber(DependencyObject target, bool value) => target.SetValue(ShowRowNumberProperty, ValueBoxes.BooleanBox(value));
private static void OnShowRowNumberChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
{
@@ -10,7 +10,7 @@ namespace HandyControl.Controls
new FrameworkPropertyMetadata(ValueBoxes.TrueBox, FrameworkPropertyMetadataOptions.Inherits));
public static void SetConsistentWidth(DependencyObject element, bool value)
=> element.SetValue(ConsistentWidthProperty, value);
=> element.SetValue(ConsistentWidthProperty, ValueBoxes.BooleanBox(value));
public static bool GetConsistentWidth(DependencyObject element)
=> (bool) element.GetValue(ConsistentWidthProperty);
@@ -36,7 +36,7 @@ namespace HandyControl.Controls
public static readonly DependencyProperty ShowEdgeContentProperty = DependencyProperty.RegisterAttached(
"ShowEdgeContent", typeof(bool), typeof(EdgeElement), new PropertyMetadata(ValueBoxes.FalseBox));
public static void SetShowEdgeContent(DependencyObject element, bool value) => element.SetValue(ShowEdgeContentProperty, value);
public static void SetShowEdgeContent(DependencyObject element, bool value) => element.SetValue(ShowEdgeContentProperty, ValueBoxes.BooleanBox(value));
public static bool GetShowEdgeContent(DependencyObject element) => (bool) element.GetValue(ShowEdgeContentProperty);
@@ -0,0 +1,42 @@
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace HandyControl.Controls
{
public class ImageAttach
{
public static readonly DependencyProperty SourceFailedProperty = DependencyProperty.RegisterAttached(
"SourceFailed", typeof(ImageSource), typeof(ImageAttach), new FrameworkPropertyMetadata(default(ImageSource), FrameworkPropertyMetadataOptions.Inherits, OnSourceFailedChanged));
private static void OnSourceFailedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is Image image)
{
if (e.NewValue is ImageSource)
{
image.ImageFailed += Image_ImageFailed;
}
else
{
image.ImageFailed -= Image_ImageFailed;
}
}
}
private static void Image_ImageFailed(object sender, ExceptionRoutedEventArgs e)
{
if (sender is Image image)
{
image.SetCurrentValue(Image.SourceProperty, GetSourceFailed(image));
image.ImageFailed -= Image_ImageFailed;
}
}
public static void SetSourceFailed(DependencyObject element, ImageSource value)
=> element.SetValue(SourceFailedProperty, value);
public static ImageSource GetSourceFailed(DependencyObject element)
=> (ImageSource) element.GetValue(SourceFailedProperty);
}
}
@@ -21,7 +21,7 @@ namespace HandyControl.Controls
public static readonly DependencyProperty NecessaryProperty = DependencyProperty.RegisterAttached(
"Necessary", typeof(bool), typeof(InfoElement), new FrameworkPropertyMetadata(ValueBoxes.FalseBox, FrameworkPropertyMetadataOptions.Inherits));
public static void SetNecessary(DependencyObject element, bool value) => element.SetValue(NecessaryProperty, value);
public static void SetNecessary(DependencyObject element, bool value) => element.SetValue(NecessaryProperty, ValueBoxes.BooleanBox(value));
public static bool GetNecessary(DependencyObject element) => (bool)element.GetValue(NecessaryProperty);
@@ -39,7 +39,7 @@ namespace HandyControl.Controls
}
}
public static void SetIsMonitoring(DependencyObject element, bool value) => element.SetValue(IsMonitoringProperty, value);
public static void SetIsMonitoring(DependencyObject element, bool value) => element.SetValue(IsMonitoringProperty, ValueBoxes.BooleanBox(value));
public static bool GetIsMonitoring(DependencyObject element) => (bool)element.GetValue(IsMonitoringProperty);
@@ -37,7 +37,7 @@ namespace HandyControl.Controls
}
public static void SetCircular(DependencyObject element, bool value)
=> element.SetValue(CircularProperty, value);
=> element.SetValue(CircularProperty, ValueBoxes.BooleanBox(value));
public static bool GetCircular(DependencyObject element)
=> (bool) element.GetValue(CircularProperty);
@@ -21,7 +21,7 @@ namespace HandyControl.Controls
public static readonly DependencyProperty HideUncheckedElementProperty = DependencyProperty.RegisterAttached(
"HideUncheckedElement", typeof(bool), typeof(StatusSwitchElement), new PropertyMetadata(ValueBoxes.FalseBox));
public static void SetHideUncheckedElement(DependencyObject element, bool value) => element.SetValue(HideUncheckedElementProperty, value);
public static void SetHideUncheckedElement(DependencyObject element, bool value) => element.SetValue(HideUncheckedElementProperty, ValueBoxes.BooleanBox(value));
public static bool GetHideUncheckedElement(DependencyObject element) => (bool) element.GetValue(HideUncheckedElementProperty);
}
@@ -28,7 +28,7 @@ namespace HandyControl.Controls
}
public static void SetAutoTooltip(DependencyObject element, bool value)
=> element.SetValue(AutoTooltipProperty, value);
=> element.SetValue(AutoTooltipProperty, ValueBoxes.BooleanBox(value));
public static bool GetAutoTooltip(DependencyObject element)
=> (bool) element.GetValue(AutoTooltipProperty);
@@ -45,14 +45,14 @@ namespace HandyControl.Controls
/// <summary>
/// 标题对齐方式
/// </summary>
public static readonly DependencyProperty TitleAlignmentProperty = DependencyProperty.RegisterAttached(
"TitleAlignment", typeof(TitleAlignment), typeof(TitleElement), new FrameworkPropertyMetadata(TitleAlignment.Top, FrameworkPropertyMetadataOptions.Inherits));
public static readonly DependencyProperty TitlePlacementProperty = DependencyProperty.RegisterAttached(
"TitlePlacement", typeof(TitlePlacementType), typeof(TitleElement), new FrameworkPropertyMetadata(TitlePlacementType.Top, FrameworkPropertyMetadataOptions.Inherits));
public static void SetTitleAlignment(DependencyObject element, TitleAlignment value)
=> element.SetValue(TitleAlignmentProperty, value);
public static void SetTitlePlacement(DependencyObject element, TitlePlacementType value)
=> element.SetValue(TitlePlacementProperty, value);
public static TitleAlignment GetTitleAlignment(DependencyObject element)
=> (TitleAlignment) element.GetValue(TitleAlignmentProperty);
public static TitlePlacementType GetTitlePlacement(DependencyObject element)
=> (TitlePlacementType) element.GetValue(TitlePlacementProperty);
/// <summary>
/// 标题宽度
@@ -13,7 +13,7 @@ namespace HandyControl.Controls
"IsDragElement", typeof(bool), typeof(WindowAttach), new PropertyMetadata(ValueBoxes.FalseBox, OnIsDragElementChanged));
public static void SetIsDragElement(DependencyObject element, bool value)
=> element.SetValue(IsDragElementProperty, value);
=> element.SetValue(IsDragElementProperty, ValueBoxes.BooleanBox(value));
public static bool GetIsDragElement(DependencyObject element)
=> (bool) element.GetValue(IsDragElementProperty);
@@ -68,7 +68,7 @@ namespace HandyControl.Controls
}
public static void SetIgnoreAltF4(DependencyObject element, bool value)
=> element.SetValue(IgnoreAltF4Property, value);
=> element.SetValue(IgnoreAltF4Property, ValueBoxes.BooleanBox(value));
public static bool GetIgnoreAltF4(DependencyObject element)
=> (bool) element.GetValue(IgnoreAltF4Property);
@@ -106,7 +106,7 @@ namespace HandyControl.Controls
}
public static void SetShowInTaskManager(DependencyObject element, bool value)
=> element.SetValue(ShowInTaskManagerProperty, value);
=> element.SetValue(ShowInTaskManagerProperty, ValueBoxes.BooleanBox(value));
public static bool GetShowInTaskManager(DependencyObject element)
=> (bool) element.GetValue(ShowInTaskManagerProperty);
@@ -50,7 +50,7 @@ namespace HandyControl.Controls
"IsInstance", typeof(bool), typeof(AdornerElement), new PropertyMetadata(ValueBoxes.TrueBox));
public static void SetIsInstance(DependencyObject element, bool value)
=> element.SetValue(IsInstanceProperty, value);
=> element.SetValue(IsInstanceProperty, ValueBoxes.BooleanBox(value));
public static bool GetIsInstance(DependencyObject element)
=> (bool) element.GetValue(IsInstanceProperty);
@@ -67,7 +67,7 @@ namespace HandyControl.Controls
public bool IsSelected
{
get => (bool)GetValue(IsSelectedProperty);
set => SetValue(IsSelectedProperty, value);
set => SetValue(IsSelectedProperty, ValueBoxes.BooleanBox(value));
}
public static readonly DependencyProperty SelfManageProperty = DependencyProperty.Register(
@@ -76,7 +76,7 @@ namespace HandyControl.Controls
public bool SelfManage
{
get => (bool) GetValue(SelfManageProperty);
set => SetValue(SelfManageProperty, value);
set => SetValue(SelfManageProperty, ValueBoxes.BooleanBox(value));
}
public static readonly DependencyProperty CanDeselectProperty = DependencyProperty.Register(
@@ -85,7 +85,7 @@ namespace HandyControl.Controls
public bool CanDeselect
{
get => (bool) GetValue(CanDeselectProperty);
set => SetValue(CanDeselectProperty, value);
set => SetValue(CanDeselectProperty, ValueBoxes.BooleanBox(value));
}
public static readonly RoutedEvent SelectedEvent =
@@ -38,7 +38,7 @@ namespace HandyControl.Controls
{
if (e.NewItems != null && e.NewItems.Count > 0)
{
SetValue(HasItemsPropertyKey, true);
SetValue(HasItemsPropertyKey, ValueBoxes.TrueBox);
}
OnItemsChanged(s, e);
};
@@ -77,7 +77,7 @@ namespace HandyControl.Controls
"ReadyToFloat", typeof(bool), typeof(FloatingBlock), new PropertyMetadata(ValueBoxes.FalseBox));
private static void SetReadyToFloat(DependencyObject element, bool value)
=> element.SetValue(ReadyToFloatProperty, value);
=> element.SetValue(ReadyToFloatProperty, ValueBoxes.BooleanBox(value));
private static bool GetReadyToFloat(DependencyObject element)
=> (bool)element.GetValue(ReadyToFloatProperty);
@@ -4,6 +4,7 @@ using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using HandyControl.Data;
using HandyControl.Expression.Drawing;
namespace HandyControl.Controls
{
@@ -27,6 +28,7 @@ namespace HandyControl.Controls
_elementContent = GetTemplateChild(ElementContent) as FrameworkElement;
_elementPanel = GetTemplateChild(ElementPanel) as Panel;
UpdateContent();
}
public static readonly DependencyProperty RunawayProperty = DependencyProperty.Register(
@@ -35,7 +37,7 @@ namespace HandyControl.Controls
public bool Runaway
{
get => (bool) GetValue(RunawayProperty);
set => SetValue(RunawayProperty, value);
set => SetValue(RunawayProperty, ValueBoxes.BooleanBox(value));
}
public static readonly DependencyProperty AutoRunProperty = DependencyProperty.Register(
@@ -44,7 +46,7 @@ namespace HandyControl.Controls
public bool AutoRun
{
get => (bool) GetValue(AutoRunProperty);
set => SetValue(AutoRunProperty, value);
set => SetValue(AutoRunProperty, ValueBoxes.BooleanBox(value));
}
public static readonly DependencyProperty OrientationProperty = DependencyProperty.Register(
@@ -65,6 +67,15 @@ namespace HandyControl.Controls
set => SetValue(DurationProperty, value);
}
public static readonly DependencyProperty SpeedProperty = DependencyProperty.Register(
"Speed", typeof(double), typeof(RunningBlock), new FrameworkPropertyMetadata(double.NaN, FrameworkPropertyMetadataOptions.AffectsRender));
public double Speed
{
get => (double) GetValue(SpeedProperty);
set => SetValue(SpeedProperty, value);
}
public static readonly DependencyProperty IsRunningProperty = DependencyProperty.Register(
"IsRunning", typeof(bool), typeof(RunningBlock), new PropertyMetadata(ValueBoxes.TrueBox, (o, args) =>
{
@@ -83,7 +94,7 @@ namespace HandyControl.Controls
public bool IsRunning
{
get => (bool) GetValue(IsRunningProperty);
set => SetValue(IsRunningProperty, value);
set => SetValue(IsRunningProperty, ValueBoxes.BooleanBox(value));
}
public static readonly DependencyProperty AutoReverseProperty = DependencyProperty.Register(
@@ -92,7 +103,7 @@ namespace HandyControl.Controls
public bool AutoReverse
{
get => (bool) GetValue(AutoReverseProperty);
set => SetValue(AutoReverseProperty, value);
set => SetValue(AutoReverseProperty, ValueBoxes.BooleanBox(value));
}
private void UpdateContent()
@@ -150,11 +161,18 @@ namespace HandyControl.Controls
propertyPath = new PropertyPath("(UIElement.RenderTransform).(TransformGroup.Children)[0].(TranslateTransform.Y)");
}
var animation = new DoubleAnimation(from, to, Duration)
var duration = double.IsNaN(Speed)
? Duration
: !MathHelper.IsVerySmall(Speed)
? TimeSpan.FromSeconds((to - from) / Speed)
: Duration;
var animation = new DoubleAnimation(from, to, duration)
{
RepeatBehavior = RepeatBehavior.Forever,
AutoReverse = AutoReverse
};
Storyboard.SetTargetProperty(animation, propertyPath);
Storyboard.SetTarget(animation, _elementContent);
@@ -163,10 +181,6 @@ namespace HandyControl.Controls
_storyboard.Begin();
}
protected override void OnRender(DrawingContext drawingContext)
{
base.OnRender(drawingContext);
UpdateContent();
}
protected override void OnRender(DrawingContext drawingContext) => UpdateContent();
}
}
@@ -8,9 +8,6 @@ namespace HandyControl.Controls
/// <summary>
/// 切换块
/// </summary>
/// <remarks>
/// 在不需要命中测试的情况下可代替ToggleButton或CheckBox,以减少内存用量。
/// </remarks>
public class ToggleBlock : Control
{
public static readonly DependencyProperty IsCheckedProperty = DependencyProperty.Register(
@@ -1,7 +1,6 @@
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using HandyControl.Tools;
namespace HandyControl.Controls
{
@@ -18,15 +17,6 @@ namespace HandyControl.Controls
set => SetValue(OrientationProperty, value);
}
public static readonly DependencyProperty ItemStyleSelectorProperty = DependencyProperty.Register(
"ItemStyleSelector", typeof(StyleSelector), typeof(ButtonGroup), new PropertyMetadata(new ButtonGroupItemStyleSelector()));
public StyleSelector ItemStyleSelector
{
get => (StyleSelector)GetValue(ItemStyleSelectorProperty);
set => SetValue(ItemStyleSelectorProperty, value);
}
protected override void OnVisualChildrenChanged(DependencyObject visualAdded, DependencyObject visualRemoved)
{
base.OnVisualChildrenChanged(visualAdded, visualRemoved);
@@ -35,7 +25,7 @@ namespace HandyControl.Controls
for (var i = 0; i < count; i++)
{
var item = (ButtonBase)Items[i];
item.Style = ItemStyleSelector?.SelectStyle(item, this);
item.Style = ItemContainerStyleSelector?.SelectStyle(item, this);
}
}
}
@@ -33,7 +33,7 @@ namespace HandyControl.Controls
public bool IsDropDownOpen
{
get => (bool) GetValue(IsDropDownOpenProperty);
set => SetValue(IsDropDownOpenProperty, value);
set => SetValue(IsDropDownOpenProperty, ValueBoxes.BooleanBox(value));
}
public static readonly DependencyProperty DropDownContentProperty = DependencyProperty.Register(
@@ -1,4 +1,5 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
@@ -21,13 +22,11 @@ namespace HandyControl.Controls
[DefaultProperty("Items")]
[ContentProperty("Items")]
[TemplatePart(Name = ElementPanelPage, Type = typeof(Panel))]
[TemplatePart(Name = ElementItemsControl, Type = typeof(ItemsPresenter))]
public class Carousel : ListBox, IDisposable
public class Carousel : SimpleItemsControl, IDisposable
{
#region Constants
private const string ElementPanelPage = "PART_PanelPage";
private const string ElementItemsControl = "PART_ItemsControl";
#endregion Constants
@@ -39,8 +38,6 @@ namespace HandyControl.Controls
private bool _appliedTemplate;
private ItemsPresenter _itemsControl;
private int _pageIndex = -1;
private RadioButton _selectedButton;
@@ -49,6 +46,12 @@ namespace HandyControl.Controls
private readonly List<double> _widthList = new List<double>();
private readonly Dictionary<object, CarouselItem> _entryDic = new Dictionary<object, CarouselItem>();
private bool _isRefresh;
private IEnumerable _itemsSourceInternal;
#endregion Data
public override void OnApplyTemplate()
@@ -59,7 +62,6 @@ namespace HandyControl.Controls
base.OnApplyTemplate();
_itemsControl = GetTemplateChild(ElementItemsControl) as ItemsPresenter;
_panelPage = GetTemplateChild(ElementPanelPage) as Panel;
if (!CheckNull()) return;
@@ -75,7 +77,7 @@ namespace HandyControl.Controls
UpdatePageButtons(_pageIndex);
}
private bool CheckNull() => !(_itemsControl == null || _panelPage == null);
private bool CheckNull() => _panelPage != null;
public static readonly DependencyProperty AutoRunProperty = DependencyProperty.Register(
"AutoRun", typeof(bool), typeof(Carousel), new PropertyMetadata(ValueBoxes.FalseBox, (o, args) =>
@@ -102,7 +104,7 @@ namespace HandyControl.Controls
public bool IsCenter
{
get => (bool)GetValue(IsCenterProperty);
set => SetValue(IsCenterProperty, value);
set => SetValue(IsCenterProperty, ValueBoxes.BooleanBox(value));
}
public static readonly DependencyProperty PageButtonStyleProperty = DependencyProperty.Register(
@@ -131,7 +133,7 @@ namespace HandyControl.Controls
if (_isDisposed) return;
IsVisibleChanged -= Carousel_IsVisibleChanged;
_updateTimer.Stop();
_updateTimer?.Stop();
_isDisposed = true;
GC.SuppressFinalize(this);
@@ -153,20 +155,13 @@ namespace HandyControl.Controls
}
}
protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e)
{
base.OnItemsChanged(e);
UpdatePageButtons();
}
/// <summary>
/// 是否自动跳转
/// </summary>
public bool AutoRun
{
get => (bool)GetValue(AutoRunProperty);
set => SetValue(AutoRunProperty, value);
set => SetValue(AutoRunProperty, ValueBoxes.BooleanBox(value));
}
/// <summary>
@@ -239,14 +234,14 @@ namespace HandyControl.Controls
_widthList.Clear();
_widthList.Add(0);
var width = .0;
foreach (FrameworkElement item in Items)
foreach (FrameworkElement item in ItemsHost.Children)
{
item.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
width += item.DesiredSize.Width;
_widthList.Add(width);
}
_itemsControl.Width = _widthList.Last() + ExtendWidth;
ItemsHost.Width = _widthList.Last() + ExtendWidth;
_panelPage.Children.Clear();
for (var i = 0; i < count; i++)
{
@@ -278,14 +273,14 @@ namespace HandyControl.Controls
if (Items.Count == 0) return;
if (!IsCenter)
{
_itemsControl.BeginAnimation(MarginProperty,
ItemsHost.BeginAnimation(MarginProperty,
AnimationHelper.CreateAnimation(new Thickness(-_widthList[PageIndex], 0, 0, 0)));
}
else
{
var ctl = (FrameworkElement)Items[PageIndex];
var ctl = (FrameworkElement)ItemsHost.Children[PageIndex];
var ctlWidth = ctl.DesiredSize.Width;
_itemsControl.BeginAnimation(MarginProperty,
ItemsHost.BeginAnimation(MarginProperty,
AnimationHelper.CreateAnimation(
new Thickness(-_widthList[PageIndex] + (ActualWidth - ctlWidth) / 2, 0, 0, 0)));
}
@@ -313,5 +308,149 @@ namespace HandyControl.Controls
private void ButtonPrev_OnClick(object sender, RoutedEventArgs e) => PageIndex--;
private void ButtonNext_OnClick(object sender, RoutedEventArgs e) => PageIndex++;
protected override DependencyObject GetContainerForItemOverride() => new CarouselItem();
protected override bool IsItemItsOwnContainerOverride(object item) => item is CarouselItem;
private void ClearItems()
{
ItemsHost?.Children.Clear();
_entryDic.Clear();
}
private void RemoveItem(object item)
{
if (_entryDic.TryGetValue(item, out var entry))
{
ItemsHost.Children.Remove(entry);
Items.Remove(item);
_entryDic.Remove(item);
}
}
protected override void Refresh()
{
if (ItemsHost == null) return;
_entryDic.Clear();
_isRefresh = true;
foreach (var item in Items)
{
AddItem(item);
}
_isRefresh = false;
}
private void AddItem(object item) => InsertItem(_entryDic.Count, item);
private void InsertItem(int index, object item)
{
if (ItemsHost == null)
{
Items.Insert(index, item);
_entryDic.Add(item, null);
}
else
{
DependencyObject container;
if (IsItemItsOwnContainerOverride(item))
{
container = item as DependencyObject;
}
else
{
container = GetContainerForItemOverride();
PrepareContainerForItemOverride(container, item);
}
if (container is CarouselItem element)
{
element.Style = ItemContainerStyle;
_entryDic[item] = element;
ItemsHost.Children.Insert(index, element);
if (IsLoaded && !_isRefresh && _itemsSourceInternal != null)
{
Items.Insert(index, item);
}
}
}
}
protected override void OnItemsSourceChanged(IEnumerable oldValue, IEnumerable newValue)
{
if (_itemsSourceInternal != null)
{
if (_itemsSourceInternal is INotifyCollectionChanged s)
{
s.CollectionChanged -= InternalCollectionChanged;
}
Items.Clear();
ClearItems();
}
_itemsSourceInternal = newValue;
if (_itemsSourceInternal != null)
{
if (_itemsSourceInternal is INotifyCollectionChanged s)
{
s.CollectionChanged += InternalCollectionChanged;
}
foreach (var item in _itemsSourceInternal)
{
AddItem(item);
}
}
}
private void InternalCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (ItemsHost == null) return;
if (e.Action == NotifyCollectionChangedAction.Reset)
{
if (_entryDic.Count == 0) return;
ClearItems();
Items.Clear();
return;
}
if (e.OldItems != null)
{
foreach (var item in e.OldItems)
{
RemoveItem(item);
}
}
if (e.NewItems != null)
{
var count = 0;
foreach (var item in e.NewItems)
{
var index = e.NewStartingIndex + count++;
InsertItem(index, item);
}
}
}
protected override void OnItemsChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (_itemsSourceInternal != null) return;
InternalCollectionChanged(sender, e);
}
protected override void OnItemTemplateChanged(DependencyPropertyChangedEventArgs e)
{
}
protected override void OnItemContainerStyleChanged(DependencyPropertyChangedEventArgs e)
{
}
}
}
@@ -0,0 +1,9 @@
using System.Windows.Controls;
namespace HandyControl.Controls
{
public class CarouselItem : ContentControl
{
}
}
@@ -123,7 +123,7 @@ namespace HandyControl.Controls
public bool Loop
{
get => (bool)GetValue(LoopProperty);
set => SetValue(LoopProperty, value);
set => SetValue(LoopProperty, ValueBoxes.BooleanBox(value));
}
public override void OnApplyTemplate()
@@ -76,10 +76,7 @@ namespace HandyControl.Controls
{
base.OnApplyTemplate();
if (_viewContent.Style == null)
{
_viewContent.Style = CoverViewContentStyle;
}
_viewContent.Style ??= CoverViewContentStyle;
if (_selectedItem != null)
{
@@ -149,7 +146,7 @@ namespace HandyControl.Controls
public bool ItemContentHeightFixed
{
get => (bool)GetValue(ItemContentHeightFixedProperty);
set => SetValue(ItemContentHeightFixedProperty, value);
set => SetValue(ItemContentHeightFixedProperty, ValueBoxes.BooleanBox(value));
}
public static readonly DependencyProperty ItemHeaderTemplateProperty = DependencyProperty.Register(
@@ -181,9 +178,7 @@ namespace HandyControl.Controls
}
_isRefresh = false;
GenerateIndex();
UpdateCoverViewContent(_viewContent.IsOpen);
}
@@ -338,10 +333,7 @@ namespace HandyControl.Controls
{
SetBindingForItem(element);
element.Style = ItemContainerStyle;
if (element.Header == null)
{
element.Header = item;
}
element.Header ??= item;
_entryDic[item] = element;
ItemsHost.Children.Insert(index, element);
@@ -14,7 +14,7 @@ namespace HandyControl.Controls
{
private string _token;
private Adorner _container;
private AdornerContainer _container;
private static readonly Dictionary<string, FrameworkElement> ContainerDic = new Dictionary<string, FrameworkElement>();
@@ -24,7 +24,7 @@ namespace HandyControl.Controls
public bool IsClosed
{
get => (bool)GetValue(IsClosedProperty);
internal set => SetValue(IsClosedProperty, value);
internal set => SetValue(IsClosedProperty, ValueBoxes.BooleanBox(value));
}
public static readonly DependencyProperty TokenProperty = DependencyProperty.RegisterAttached(
@@ -107,35 +107,36 @@ namespace HandyControl.Controls
FrameworkElement element;
AdornerDecorator decorator;
if (string.IsNullOrEmpty(token))
{
element = WindowHelper.GetActiveWindow();
decorator = VisualHelper.GetChild<AdornerDecorator>(element);
}
else
{
ContainerDic.TryGetValue(token, out element);
decorator = element is System.Windows.Window ?
VisualHelper.GetChild<AdornerDecorator>(element) :
VisualHelper.GetChild<DialogContainer>(element);
}
if (element != null)
if (decorator != null)
{
var decorator = VisualHelper.GetChild<AdornerDecorator>(element);
if (decorator != null)
if (decorator.Child != null)
{
if (decorator.Child != null)
decorator.Child.IsEnabled = false;
}
var layer = decorator.AdornerLayer;
if (layer != null)
{
var container = new AdornerContainer(layer)
{
decorator.Child.IsEnabled = false;
}
var layer = decorator.AdornerLayer;
if (layer != null)
{
var container = new AdornerContainer(layer)
{
Child = dialog
};
dialog._container = container;
dialog.IsClosed = false;
layer.Add(container);
}
Child = dialog
};
dialog._container = container;
dialog.IsClosed = false;
layer.Add(container);
}
}
@@ -156,7 +157,7 @@ namespace HandyControl.Controls
private void Close(DependencyObject element)
{
if (element != null)
if (element != null && _container != null)
{
var decorator = VisualHelper.GetChild<AdornerDecorator>(element);
if (decorator != null)
@@ -0,0 +1,9 @@
using System.Windows.Documents;
namespace HandyControl.Controls
{
public class DialogContainer : AdornerDecorator
{
}
}
@@ -207,9 +207,9 @@ namespace HandyControl.Controls
=> element.SetValue(TokenProperty, value);
public static string GetToken(DependencyObject element)
=> (string) element.GetValue(TokenProperty);
=> (string)element.GetValue(TokenProperty);
public static void SetGrowlParent(DependencyObject element, bool value) => element.SetValue(GrowlParentProperty, value);
public static void SetGrowlParent(DependencyObject element, bool value) => element.SetValue(GrowlParentProperty, ValueBoxes.BooleanBox(value));
public static bool GetGrowlParent(DependencyObject element) => (bool)element.GetValue(GrowlParentProperty);
@@ -234,7 +234,7 @@ namespace HandyControl.Controls
public bool ShowDateTime
{
get => (bool)GetValue(ShowDateTimeProperty);
set => SetValue(ShowDateTimeProperty, value);
set => SetValue(ShowDateTimeProperty, ValueBoxes.BooleanBox(value));
}
public string Message
@@ -348,47 +348,33 @@ namespace HandyControl.Controls
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
Application.Current.Dispatcher?.Invoke(
#if NET40
new Action(
#endif
() =>
{
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);
}
#if NET40
)
#endif
);
}
/// <summary>
@@ -397,67 +383,43 @@ namespace HandyControl.Controls
/// <param name="growlInfo"></param>
private static void Show(GrowlInfo growlInfo)
{
#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)
};
if (!string.IsNullOrEmpty(growlInfo.Token))
{
if (PanelDic.TryGetValue(growlInfo.Token, out var panel))
{
panel?.Children.Insert(0, ctl);
}
}
else
{
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)
};
if (!string.IsNullOrEmpty(growlInfo.Token))
{
if (PanelDic.TryGetValue(growlInfo.Token, out var panel))
{
panel?.Children.Insert(0, ctl);
}
}
else
{
GrowlPanel.Children.Insert(0, ctl);
}
});
#endif
Application.Current.Dispatcher?.Invoke(
#if NET40
new Action(
#endif
() =>
{
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)
};
if (!string.IsNullOrEmpty(growlInfo.Token))
{
if (PanelDic.TryGetValue(growlInfo.Token, out var panel))
{
panel?.Children.Insert(0, ctl);
}
}
else
{
GrowlPanel?.Children.Insert(0, ctl);
}
}
#if NET40
)
#endif
);
}
private static void InitGrowlInfo(ref GrowlInfo growlInfo, InfoType infoType)
@@ -143,7 +143,7 @@ namespace HandyControl.Controls
public bool IsPlaying
{
get => (bool) GetValue(IsPlayingProperty);
set => SetValue(IsPlayingProperty, value);
set => SetValue(IsPlayingProperty, ValueBoxes.BooleanBox(value));
}
public static readonly DependencyProperty ColumnsProperty = DependencyProperty.Register(
@@ -271,13 +271,13 @@ namespace HandyControl.Controls
public bool IsFullScreen
{
get => (bool)GetValue(IsFullScreenProperty);
set => SetValue(IsFullScreenProperty, value);
set => SetValue(IsFullScreenProperty, ValueBoxes.BooleanBox(value));
}
public bool ShowImgMap
{
get => (bool)GetValue(ShowImgMapProperty);
set => SetValue(ShowImgMapProperty, value);
set => SetValue(ShowImgMapProperty, ValueBoxes.BooleanBox(value));
}
public BitmapFrame ImageSource
@@ -310,7 +310,7 @@ namespace HandyControl.Controls
internal bool ShowFullScreenButton
{
get => (bool)GetValue(ShowFullScreenButtonProperty);
set => SetValue(ShowFullScreenButtonProperty, value);
set => SetValue(ShowFullScreenButtonProperty, ValueBoxes.BooleanBox(value));
}
internal Thickness ImageMargin
@@ -352,7 +352,7 @@ namespace HandyControl.Controls
internal bool ShowSmallImgInternal
{
get => (bool)GetValue(ShowSmallImgInternalProperty);
set => SetValue(ShowSmallImgInternalProperty, value);
set => SetValue(ShowSmallImgInternalProperty, ValueBoxes.BooleanBox(value));
}
/// <summary>
@@ -371,7 +371,7 @@ namespace HandyControl.Controls
internal bool ShowCloseButton
{
get => (bool)GetValue(ShowCloseButtonProperty);
set => SetValue(ShowCloseButtonProperty, value);
set => SetValue(ShowCloseButtonProperty, ValueBoxes.BooleanBox(value));
}
/// <summary>
@@ -0,0 +1,225 @@
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using HandyControl.Data;
using HandyControl.Interactivity;
namespace HandyControl.Controls
{
[TemplatePart(Name = ElementPanel, Type = typeof(Panel))]
[TemplatePart(Name = ElementSelectAll, Type = typeof(CheckComboBoxItem))]
public class CheckComboBox : ListBox, IDataInput
{
private const string ElementPanel = "PART_Panel";
private const string ElementSelectAll = "PART_SelectAll";
private Panel _panel;
private CheckComboBoxItem _selectAllItem;
private bool _isInternalAction;
public static readonly DependencyProperty IsErrorProperty = DependencyProperty.Register(
"IsError", typeof(bool), typeof(CheckComboBox), new PropertyMetadata(ValueBoxes.FalseBox));
public bool IsError
{
get => (bool) GetValue(IsErrorProperty);
set => SetValue(IsErrorProperty, ValueBoxes.BooleanBox(value));
}
public static readonly DependencyProperty ErrorStrProperty = DependencyProperty.Register(
"ErrorStr", typeof(string), typeof(CheckComboBox), new PropertyMetadata(default(string)));
public string ErrorStr
{
get => (string) GetValue(ErrorStrProperty);
set => SetValue(ErrorStrProperty, value);
}
public static readonly DependencyProperty TextTypeProperty = DependencyProperty.Register(
"TextType", typeof(TextType), typeof(CheckComboBox), new PropertyMetadata(default(TextType)));
public TextType TextType
{
get => (TextType) GetValue(TextTypeProperty);
set => SetValue(TextTypeProperty, value);
}
public static readonly DependencyProperty ShowClearButtonProperty = DependencyProperty.Register(
"ShowClearButton", typeof(bool), typeof(CheckComboBox), new PropertyMetadata(ValueBoxes.FalseBox));
public bool ShowClearButton
{
get => (bool) GetValue(ShowClearButtonProperty);
set => SetValue(ShowClearButtonProperty, ValueBoxes.BooleanBox(value));
}
public static readonly DependencyProperty MaxDropDownHeightProperty =
System.Windows.Controls.ComboBox.MaxDropDownHeightProperty.AddOwner(typeof(CheckComboBox),
new FrameworkPropertyMetadata(SystemParameters.PrimaryScreenHeight / 3));
[Bindable(true), Category("Layout")]
[TypeConverter(typeof(LengthConverter))]
public double MaxDropDownHeight
{
get => (double) GetValue(MaxDropDownHeightProperty);
set => SetValue(MaxDropDownHeightProperty, value);
}
public static readonly DependencyProperty IsDropDownOpenProperty = DependencyProperty.Register(
"IsDropDownOpen", typeof(bool), typeof(CheckComboBox), new PropertyMetadata(ValueBoxes.FalseBox));
public bool IsDropDownOpen
{
get => (bool) GetValue(IsDropDownOpenProperty);
set => SetValue(IsDropDownOpenProperty, ValueBoxes.BooleanBox(value));
}
public static readonly DependencyProperty TagStyleProperty = DependencyProperty.Register(
"TagStyle", typeof(Style), typeof(CheckComboBox), new PropertyMetadata(default(Style)));
public Style TagStyle
{
get => (Style) GetValue(TagStyleProperty);
set => SetValue(TagStyleProperty, value);
}
public static readonly DependencyProperty ShowSelectAllButtonProperty = DependencyProperty.Register(
"ShowSelectAllButton", typeof(bool), typeof(CheckComboBox), new PropertyMetadata(ValueBoxes.FalseBox));
public bool ShowSelectAllButton
{
get => (bool) GetValue(ShowSelectAllButtonProperty);
set => SetValue(ShowSelectAllButtonProperty, ValueBoxes.BooleanBox(value));
}
public CheckComboBox()
{
AddHandler(Controls.Tag.ClosedEvent, new RoutedEventHandler(Tags_OnClosed));
CommandBindings.Add(new CommandBinding(ControlCommands.Clear, (s, e) => SelectedItems.Clear()));
}
private void Tags_OnClosed(object sender, RoutedEventArgs e)
{
if (e.OriginalSource is Tag tag && tag.Tag is CheckComboBoxItem checkComboBoxItem)
{
checkComboBoxItem.SetCurrentValue(IsSelectedProperty, false);
}
}
public override void OnApplyTemplate()
{
if (_selectAllItem != null)
{
_selectAllItem.Selected -= SelectAllItem_Selected;
_selectAllItem.Unselected -= SelectAllItem_Unselected;
}
base.OnApplyTemplate();
_panel = GetTemplateChild(ElementPanel) as Panel;
_selectAllItem = GetTemplateChild(ElementSelectAll) as CheckComboBoxItem;
if (_selectAllItem != null)
{
_selectAllItem.Selected += SelectAllItem_Selected;
_selectAllItem.Unselected += SelectAllItem_Unselected;
}
}
public bool VerifyData()
{
OperationResult<bool> result;
if (VerifyFunc != null)
{
result = VerifyFunc.Invoke(null);
}
else
{
if (SelectedItems.Count > 0)
{
result = OperationResult.Success();
}
else if (InfoElement.GetNecessary(this))
{
result = OperationResult.Failed(Properties.Langs.Lang.IsNecessary);
}
else
{
result = OperationResult.Success();
}
}
IsError = !result.Data;
ErrorStr = result.Message;
return result.Data;
}
public Func<string, OperationResult<bool>> VerifyFunc { get; set; }
private void SwitchAllItems(bool selected)
{
if (_isInternalAction) return;
_isInternalAction = true;
foreach (var item in Items)
{
if (ItemContainerGenerator.ContainerFromItem(item) is CheckComboBoxItem checkComboBoxItem)
{
checkComboBoxItem.SetCurrentValue(ListBoxItem.IsSelectedProperty, selected);
}
}
_isInternalAction = false;
UpdateTags();
}
private void SelectAllItem_Selected(object sender, RoutedEventArgs e) => SwitchAllItems(true);
private void SelectAllItem_Unselected(object sender, RoutedEventArgs e) => SwitchAllItems(false);
protected override void OnSelectionChanged(SelectionChangedEventArgs e)
{
UpdateTags();
VerifyData();
base.OnSelectionChanged(e);
}
protected override bool IsItemItsOwnContainerOverride(object item) => item is CheckComboBoxItem;
protected override DependencyObject GetContainerForItemOverride() => new CheckComboBoxItem();
private void UpdateTags()
{
if (_panel == null || _isInternalAction) return;
if (_selectAllItem != null)
{
_isInternalAction = true;
_selectAllItem.SetCurrentValue(IsSelectedProperty, SelectedItems.Count == Items.Count);
_isInternalAction = false;
}
_panel.Children.Clear();
foreach (var item in SelectedItems)
{
if (ItemContainerGenerator.ContainerFromItem(item) is CheckComboBoxItem checkComboBoxItem)
{
var tag = new Tag
{
Style = TagStyle,
Content = checkComboBoxItem.Content,
Tag = checkComboBoxItem
};
_panel.Children.Add(tag);
}
}
}
}
}
@@ -0,0 +1,9 @@
using System.Windows.Controls;
namespace HandyControl.Controls
{
public class CheckComboBoxItem : ListBoxItem
{
}
}
@@ -5,7 +5,7 @@ using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Input;
#if netle40
#if NET40
using System.Windows.Threading;
#endif
using HandyControl.Data;
@@ -18,7 +18,7 @@ namespace HandyControl.Controls
[TemplatePart(Name = AutoPopupAutoComplete, Type = typeof(Popup))]
public class ComboBox : System.Windows.Controls.ComboBox, IDataInput
{
#if netle40
#if NET40
private string _searchText;
@@ -71,7 +71,7 @@ namespace HandyControl.Controls
if (AutoComplete)
{
#if netle40
#if NET40
_autoCompleteTimer = new DispatcherTimer
{
Interval = TimeSpan.FromMilliseconds(500)
@@ -84,7 +84,7 @@ namespace HandyControl.Controls
{
UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,
Mode = BindingMode.OneWayToSource,
#if !netle40
#if !NET40
Delay = 500,
#endif
Source = this
@@ -96,7 +96,7 @@ namespace HandyControl.Controls
}
}
#if netle40
#if NET40
private void AutoCompleteTimer_Tick(object sender, EventArgs e)
{
@@ -119,7 +119,7 @@ namespace HandyControl.Controls
}
}
#if !netle40
#if !NET40
protected override void OnDropDownClosed(EventArgs e)
{
base.OnDropDownClosed(e);
@@ -142,7 +142,7 @@ namespace HandyControl.Controls
_isAutoCompleteAction = false;
base.OnSelectionChanged(e);
VerifyData();
#if netle40
#if NET40
_isAutoCompleteAction = true;
#endif
}
@@ -169,7 +169,7 @@ namespace HandyControl.Controls
public bool IsError
{
get => (bool)GetValue(IsErrorProperty);
set => SetValue(IsErrorProperty, value);
set => SetValue(IsErrorProperty, ValueBoxes.BooleanBox(value));
}
/// <summary>
@@ -220,7 +220,7 @@ namespace HandyControl.Controls
public bool ShowClearButton
{
get => (bool)GetValue(ShowClearButtonProperty);
set => SetValue(ShowClearButtonProperty, value);
set => SetValue(ShowClearButtonProperty, ValueBoxes.BooleanBox(value));
}
/// <summary>
@@ -312,7 +312,7 @@ namespace HandyControl.Controls
var ctl = (ComboBox)d;
if (ctl._isAutoCompleteAction)
{
#if netle40
#if NET40
ctl._searchText = e.NewValue as string;
ctl._autoCompleteTimer.Stop();
ctl._autoCompleteTimer.Start();
@@ -339,7 +339,7 @@ namespace HandyControl.Controls
public bool AutoComplete
{
get => (bool)GetValue(AutoCompleteProperty);
set => SetValue(AutoCompleteProperty, value);
set => SetValue(AutoCompleteProperty, ValueBoxes.BooleanBox(value));
}
/// <summary>
@@ -8,7 +8,6 @@ using HandyControl.Interactivity;
namespace HandyControl.Controls
{
/// <inheritdoc cref="IDataInput" />
[TemplatePart(Name = ElementTextBox, Type = typeof(DatePickerTextBox))]
public class DatePicker : System.Windows.Controls.DatePicker, IDataInput
{
@@ -51,7 +50,7 @@ namespace HandyControl.Controls
public bool IsError
{
get => (bool) GetValue(IsErrorProperty);
set => SetValue(IsErrorProperty, value);
set => SetValue(IsErrorProperty, ValueBoxes.BooleanBox(value));
}
public static readonly DependencyProperty ErrorStrProperty = DependencyProperty.Register(
@@ -78,7 +77,7 @@ namespace HandyControl.Controls
public bool ShowClearButton
{
get => (bool) GetValue(ShowClearButtonProperty);
set => SetValue(ShowClearButtonProperty, value);
set => SetValue(ShowClearButtonProperty, ValueBoxes.BooleanBox(value));
}
public virtual bool VerifyData()
@@ -153,7 +153,7 @@ namespace HandyControl.Controls
public bool IsDropDownOpen
{
get => (bool) GetValue(IsDropDownOpenProperty);
set => SetValue(IsDropDownOpenProperty, value);
set => SetValue(IsDropDownOpenProperty, ValueBoxes.BooleanBox(value));
}
public static readonly DependencyProperty SelectedDateTimeProperty = DependencyProperty.Register(
@@ -238,7 +238,7 @@ namespace HandyControl.Controls
public bool IsError
{
get => (bool) GetValue(IsErrorProperty);
set => SetValue(IsErrorProperty, value);
set => SetValue(IsErrorProperty, ValueBoxes.BooleanBox(value));
}
public static readonly DependencyProperty ErrorStrProperty = DependencyProperty.Register(
@@ -265,7 +265,7 @@ namespace HandyControl.Controls
public bool ShowClearButton
{
get => (bool) GetValue(ShowClearButtonProperty);
set => SetValue(ShowClearButtonProperty, value);
set => SetValue(ShowClearButtonProperty, ValueBoxes.BooleanBox(value));
}
#endregion
@@ -0,0 +1,126 @@
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using HandyControl.Data;
using HandyControl.Interactivity;
using Microsoft.Win32;
namespace HandyControl.Controls
{
public class ImageSelector : Control
{
public ImageSelector() => CommandBindings.Add(new CommandBinding(ControlCommands.Switch, SwitchImage));
private void SwitchImage(object sender, ExecutedRoutedEventArgs e)
{
if (!HasValue)
{
var dialog = new OpenFileDialog
{
RestoreDirectory = true,
Filter = Filter,
DefaultExt = DefaultExt
};
if (dialog.ShowDialog() == true)
{
SetValue(UriPropertyKey, new Uri(dialog.FileName, UriKind.RelativeOrAbsolute));
SetValue(PreviewBrushPropertyKey, new ImageBrush(BitmapFrame.Create(Uri, BitmapCreateOptions.IgnoreImageCache, BitmapCacheOption.None))
{
Stretch = Stretch
});
SetValue(HasValuePropertyKey, ValueBoxes.TrueBox);
SetCurrentValue(ToolTipProperty, dialog.FileName);
}
}
else
{
SetValue(UriPropertyKey, default(Uri));
SetValue(PreviewBrushPropertyKey, default(Brush));
SetValue(HasValuePropertyKey, ValueBoxes.FalseBox);
SetCurrentValue(ToolTipProperty, default);
}
}
public static readonly DependencyProperty StretchProperty = DependencyProperty.Register(
"Stretch", typeof(Stretch), typeof(ImageSelector), new PropertyMetadata(default(Stretch)));
public Stretch Stretch
{
get => (Stretch) GetValue(StretchProperty);
set => SetValue(StretchProperty, value);
}
public static readonly DependencyPropertyKey UriPropertyKey = DependencyProperty.RegisterReadOnly(
"Uri", typeof(Uri), typeof(ImageSelector), new PropertyMetadata(default(Uri)));
public static readonly DependencyProperty UriProperty = UriPropertyKey.DependencyProperty;
public Uri Uri
{
get => (Uri) GetValue(UriProperty);
set => SetValue(UriProperty, value);
}
public static readonly DependencyPropertyKey PreviewBrushPropertyKey = DependencyProperty.RegisterReadOnly(
"PreviewBrush", typeof(Brush), typeof(ImageSelector), new PropertyMetadata(default(Brush)));
public static readonly DependencyProperty PreviewBrushProperty = PreviewBrushPropertyKey.DependencyProperty;
public Brush PreviewBrush
{
get => (Brush) GetValue(PreviewBrushProperty);
set => SetValue(PreviewBrushProperty, value);
}
public static readonly DependencyProperty StrokeThicknessProperty = DependencyProperty.Register(
"StrokeThickness", typeof(double), typeof(ImageSelector), new FrameworkPropertyMetadata(ValueBoxes.Double1Box, FrameworkPropertyMetadataOptions.AffectsRender));
public double StrokeThickness
{
get => (double) GetValue(StrokeThicknessProperty);
set => SetValue(StrokeThicknessProperty, value);
}
public static readonly DependencyProperty StrokeDashArrayProperty = DependencyProperty.Register(
"StrokeDashArray", typeof(DoubleCollection), typeof(ImageSelector), new FrameworkPropertyMetadata(default(DoubleCollection), FrameworkPropertyMetadataOptions.AffectsRender));
public DoubleCollection StrokeDashArray
{
get => (DoubleCollection) GetValue(StrokeDashArrayProperty);
set => SetValue(StrokeDashArrayProperty, value);
}
public static readonly DependencyProperty DefaultExtProperty = DependencyProperty.Register(
"DefaultExt", typeof(string), typeof(ImageSelector), new PropertyMetadata(".jpg"));
public string DefaultExt
{
get => (string) GetValue(DefaultExtProperty);
set => SetValue(DefaultExtProperty, value);
}
public static readonly DependencyProperty FilterProperty = DependencyProperty.Register(
"Filter", typeof(string), typeof(ImageSelector), new PropertyMetadata("(.jpg)|*.jpg|(.png)|*.png"));
public string Filter
{
get => (string) GetValue(FilterProperty);
set => SetValue(FilterProperty, value);
}
public static readonly DependencyPropertyKey HasValuePropertyKey = DependencyProperty.RegisterReadOnly(
"HasValue", typeof(bool), typeof(ImageSelector), new PropertyMetadata(ValueBoxes.FalseBox));
public static readonly DependencyProperty HasValueProperty = HasValuePropertyKey.DependencyProperty;
public bool HasValue
{
get => (bool) GetValue(HasValueProperty);
set => SetValue(HasValueProperty, ValueBoxes.BooleanBox(value));
}
}
}
@@ -1,4 +1,4 @@
using System;
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
@@ -8,7 +8,6 @@ using HandyControl.Tools;
namespace HandyControl.Controls
{
/// <inheritdoc cref="IDataInput" />
/// <summary>
/// 数值选择控件
/// </summary>
@@ -74,7 +73,7 @@ namespace HandyControl.Controls
if (_textBox != null)
{
TextCompositionManager.RemovePreviewTextInputHandler(_textBox, PreviewTextInputHandler);
_textBox.TextChanged -= _textBox_TextChanged;
_textBox.TextChanged -= TextBox_TextChanged;
_textBox.PreviewKeyDown -= TextBox_PreviewKeyDown;
_textBox.LostFocus -= TextBox_LostFocus;
}
@@ -87,18 +86,22 @@ namespace HandyControl.Controls
if (_textBox != null)
{
TextCompositionManager.AddPreviewTextInputHandler(_textBox, PreviewTextInputHandler);
_textBox.TextChanged += _textBox_TextChanged;
_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 TextBox_TextChanged(object sender, TextChangedEventArgs e) => UpdateData();
private void UpdateData()
{
if (!VerifyData()) return;
if (!VerifyData())
{
_updateText = true;
return;
}
if (double.TryParse(_textBox.Text, out var value))
{
_updateText = false;
@@ -172,13 +175,9 @@ namespace HandyControl.Controls
private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var ctl = (NumericUpDown) d;
var v = (double) e.NewValue;
if (ctl._updateText && ctl._textBox != null)
{
ctl._textBox.Text = ctl.CurrentText;
ctl._textBox.Select(ctl._textBox.Text.Length, 0);
}
var ctl = (NumericUpDown)d;
var v = (double)e.NewValue;
ctl.SetText();
ctl.OnValueChanged(new FunctionEventArgs<double>(ValueChangedEvent, ctl)
{
@@ -186,6 +185,15 @@ namespace HandyControl.Controls
});
}
private void SetText()
{
if (_updateText && _textBox != null)
{
_textBox.Text = CurrentText;
_textBox.Select(_textBox.Text.Length, 0);
}
}
private static object CoerceValue(DependencyObject d, object basevalue)
{
var ctl = (NumericUpDown)d;
@@ -201,7 +209,7 @@ namespace HandyControl.Controls
{
ctl.Value = maximum;
}
ctl.SetText();
return num > maximum ? maximum : num;
}
@@ -210,7 +218,7 @@ namespace HandyControl.Controls
/// </summary>
public double Value
{
get => (double) GetValue(ValueProperty);
get => (double)GetValue(ValueProperty);
set => SetValue(ValueProperty, value);
}
@@ -238,7 +246,7 @@ namespace HandyControl.Controls
/// </summary>
public double Maximum
{
get => (double) GetValue(MaximumProperty);
get => (double)GetValue(MaximumProperty);
set => SetValue(MaximumProperty, value);
}
@@ -266,7 +274,7 @@ namespace HandyControl.Controls
/// </summary>
public double Minimum
{
get => (double) GetValue(MinimumProperty);
get => (double)GetValue(MinimumProperty);
set => SetValue(MinimumProperty, value);
}
@@ -281,7 +289,7 @@ namespace HandyControl.Controls
/// </summary>
public double Increment
{
get => (double) GetValue(IncrementProperty);
get => (double)GetValue(IncrementProperty);
set => SetValue(IncrementProperty, value);
}
@@ -296,7 +304,7 @@ namespace HandyControl.Controls
/// </summary>
public int? DecimalPlaces
{
get => (int?) GetValue(DecimalPlacesProperty);
get => (int?)GetValue(DecimalPlacesProperty);
set => SetValue(DecimalPlacesProperty, value);
}
@@ -311,8 +319,8 @@ namespace HandyControl.Controls
/// </summary>
internal bool ShowUpDownButton
{
get => (bool) GetValue(ShowUpDownButtonProperty);
set => SetValue(ShowUpDownButtonProperty, value);
get => (bool)GetValue(ShowUpDownButtonProperty);
set => SetValue(ShowUpDownButtonProperty, ValueBoxes.BooleanBox(value));
}
/// <summary>
@@ -323,8 +331,8 @@ namespace HandyControl.Controls
public bool IsError
{
get => (bool) GetValue(IsErrorProperty);
set => SetValue(IsErrorProperty, value);
get => (bool)GetValue(IsErrorProperty);
set => SetValue(IsErrorProperty, ValueBoxes.BooleanBox(value));
}
/// <summary>
@@ -335,7 +343,7 @@ namespace HandyControl.Controls
public string ErrorStr
{
get => (string) GetValue(ErrorStrProperty);
get => (string)GetValue(ErrorStrProperty);
set => SetValue(ErrorStrProperty, value);
}
@@ -350,7 +358,7 @@ namespace HandyControl.Controls
public TextType TextType
{
get => (TextType) GetValue(TextTypeProperty);
get => (TextType)GetValue(TextTypeProperty);
set => SetValue(TextTypeProperty, value);
}
@@ -362,8 +370,8 @@ namespace HandyControl.Controls
public bool ShowClearButton
{
get => (bool) GetValue(ShowClearButtonProperty);
set => SetValue(ShowClearButtonProperty, value);
get => (bool)GetValue(ShowClearButtonProperty);
set => SetValue(ShowClearButtonProperty, ValueBoxes.BooleanBox(value));
}
/// <summary>
@@ -377,8 +385,8 @@ namespace HandyControl.Controls
/// </summary>
public bool IsReadOnly
{
get => (bool) GetValue(IsReadOnlyProperty);
set => SetValue(IsReadOnlyProperty, value);
get => (bool)GetValue(IsReadOnlyProperty);
set => SetValue(IsReadOnlyProperty, ValueBoxes.BooleanBox(value));
}
public Func<string, OperationResult<bool>> VerifyFunc { get; set; }
@@ -426,4 +434,4 @@ namespace HandyControl.Controls
return result.Data;
}
}
}
}
@@ -4,14 +4,16 @@ using System.Runtime.InteropServices;
using System.Security;
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.Interactivity;
using HandyControl.Properties.Langs;
namespace HandyControl.Controls
{
/// <inheritdoc cref="IDataInput" />
[TemplatePart(Name = ElementPasswordBox, Type = typeof(System.Windows.Controls.PasswordBox))]
[TemplatePart(Name = ElementTextBox, Type = typeof(System.Windows.Controls.TextBox))]
public class PasswordBox : Control, IDataInput
@@ -20,6 +22,11 @@ namespace HandyControl.Controls
private const string ElementTextBox = "PART_TextBox";
private SecureString _password;
private System.Windows.Controls.TextBox _textBox;
/// <summary>
/// 掩码字符
/// </summary>
@@ -27,46 +34,139 @@ namespace HandyControl.Controls
System.Windows.Controls.PasswordBox.PasswordCharProperty.AddOwner(typeof(PasswordBox),
new FrameworkPropertyMetadata('●'));
public char PasswordChar
{
get => (char)GetValue(PasswordCharProperty);
set => SetValue(PasswordCharProperty, value);
}
/// <summary>
/// 数据是否错误
/// </summary>
public static readonly DependencyProperty IsErrorProperty = DependencyProperty.Register(
"IsError", typeof(bool), typeof(PasswordBox), new PropertyMetadata(ValueBoxes.FalseBox));
public bool IsError
{
get => (bool)GetValue(IsErrorProperty);
set => SetValue(IsErrorProperty, ValueBoxes.BooleanBox(value));
}
/// <summary>
/// 错误提示
/// </summary>
public static readonly DependencyProperty ErrorStrProperty = DependencyProperty.Register(
"ErrorStr", typeof(string), typeof(PasswordBox), new PropertyMetadata(default(string)));
public string ErrorStr
{
get => (string)GetValue(ErrorStrProperty);
set => SetValue(ErrorStrProperty, value);
}
/// <summary>
/// 文本类型
/// </summary>
public static readonly DependencyProperty TextTypeProperty = DependencyProperty.Register(
"TextType", typeof(TextType), typeof(PasswordBox), new PropertyMetadata(default(TextType)));
public TextType TextType
{
get => (TextType)GetValue(TextTypeProperty);
set => SetValue(TextTypeProperty, value);
}
/// <summary>
/// 是否显示清除按钮
/// </summary>
public static readonly DependencyProperty ShowClearButtonProperty = DependencyProperty.Register(
"ShowClearButton", typeof(bool), typeof(PasswordBox), new PropertyMetadata(ValueBoxes.FalseBox));
public bool ShowClearButton
{
get => (bool)GetValue(ShowClearButtonProperty);
set => SetValue(ShowClearButtonProperty, ValueBoxes.BooleanBox(value));
}
public static readonly DependencyProperty ShowEyeButtonProperty = DependencyProperty.Register(
"ShowEyeButton", typeof(bool), typeof(PasswordBox), new PropertyMetadata(ValueBoxes.FalseBox));
public bool ShowEyeButton
{
get => (bool)GetValue(ShowEyeButtonProperty);
set => SetValue(ShowEyeButtonProperty, ValueBoxes.BooleanBox(value));
}
public static readonly DependencyProperty ShowPasswordProperty = DependencyProperty.Register(
"ShowPassword", typeof(bool), typeof(PasswordBox),
new PropertyMetadata(ValueBoxes.FalseBox, OnShowPasswordChanged));
private SecureString _password;
private System.Windows.Controls.TextBox _textBox;
public PasswordBox()
public bool ShowPassword
{
CommandBindings.Add(new CommandBinding(ControlCommands.Clear, (s, e) => Clear()));
get => (bool)GetValue(ShowPasswordProperty);
set => SetValue(ShowPasswordProperty, ValueBoxes.BooleanBox(value));
}
public static readonly DependencyProperty MaxLengthProperty =
System.Windows.Controls.TextBox.MaxLengthProperty.AddOwner(typeof(PasswordBox));
public int MaxLength
{
get => (int)GetValue(MaxLengthProperty);
set => SetValue(MaxLengthProperty, value);
}
public static readonly DependencyProperty SelectionBrushProperty =
TextBoxBase.SelectionBrushProperty.AddOwner(typeof(PasswordBox));
public Brush SelectionBrush
{
get => (Brush)GetValue(SelectionBrushProperty);
set => SetValue(SelectionBrushProperty, value);
}
#if !(NET40 || NET45 || NET451 || NET452 || NET46 || NET461 || NET462 || NET47 || NET471 || NET472)
public static readonly DependencyProperty SelectionTextBrushProperty =
TextBoxBase.SelectionTextBrushProperty.AddOwner(typeof(PasswordBox));
public Brush SelectionTextBrush
{
get => (Brush)GetValue(SelectionTextBrushProperty);
set => SetValue(SelectionTextBrushProperty, value);
}
#endif
public static readonly DependencyProperty SelectionOpacityProperty =
TextBoxBase.SelectionOpacityProperty.AddOwner(typeof(PasswordBox));
public double SelectionOpacity
{
get => (double)GetValue(SelectionOpacityProperty);
set => SetValue(SelectionOpacityProperty, value);
}
public static readonly DependencyProperty CaretBrushProperty =
TextBoxBase.CaretBrushProperty.AddOwner(typeof(PasswordBox));
public Brush CaretBrush
{
get => (Brush)GetValue(CaretBrushProperty);
set => SetValue(CaretBrushProperty, value);
}
#if !NET40
public static readonly DependencyProperty IsSelectionActiveProperty =
TextBoxBase.IsSelectionActiveProperty.AddOwner(typeof(PasswordBox));
public bool IsSelectionActive => ActualPasswordBox != null && (bool) ActualPasswordBox.GetValue(IsSelectionActiveProperty);
#endif
public PasswordBox() => CommandBindings.Add(new CommandBinding(ControlCommands.Clear, (s, e) => Clear()));
public System.Windows.Controls.PasswordBox ActualPasswordBox { get; set; }
[DefaultValue("")]
@@ -86,8 +186,7 @@ namespace HandyControl.Controls
if (ActualPasswordBox == null)
{
_password = new SecureString();
if (value == null)
value = string.Empty;
value ??= string.Empty;
foreach (var item in value)
_password.AppendChar(item);
@@ -101,50 +200,8 @@ namespace HandyControl.Controls
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public SecureString SecurePassword => ActualPasswordBox?.SecurePassword;
public char PasswordChar
{
get => (char) GetValue(PasswordCharProperty);
set => SetValue(PasswordCharProperty, value);
}
public bool ShowEyeButton
{
get => (bool) GetValue(ShowEyeButtonProperty);
set => SetValue(ShowEyeButtonProperty, value);
}
public bool ShowPassword
{
get => (bool) GetValue(ShowPasswordProperty);
set => SetValue(ShowPasswordProperty, value);
}
public Func<string, OperationResult<bool>> VerifyFunc { get; set; }
public bool IsError
{
get => (bool) GetValue(IsErrorProperty);
set => SetValue(IsErrorProperty, value);
}
public string ErrorStr
{
get => (string) GetValue(ErrorStrProperty);
set => SetValue(ErrorStrProperty, value);
}
public TextType TextType
{
get => (TextType) GetValue(TextTypeProperty);
set => SetValue(TextTypeProperty, value);
}
public bool ShowClearButton
{
get => (bool) GetValue(ShowClearButtonProperty);
set => SetValue(ShowClearButtonProperty, value);
}
public virtual bool VerifyData()
{
OperationResult<bool> result;
@@ -174,9 +231,9 @@ namespace HandyControl.Controls
private static void OnShowPasswordChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var ctl = (PasswordBox) d;
var ctl = (PasswordBox)d;
if (!ctl.ShowEyeButton) return;
if ((bool) e.NewValue)
if ((bool)e.NewValue)
{
ctl._textBox.Text = ctl.ActualPasswordBox.Password;
ctl._textBox.Select(string.IsNullOrEmpty(ctl._textBox.Text) ? 0 : ctl._textBox.Text.Length, 0);
@@ -203,6 +260,13 @@ namespace HandyControl.Controls
if (ActualPasswordBox != null)
{
ActualPasswordBox.PasswordChanged += PasswordBox_PasswordChanged;
ActualPasswordBox.SetBinding(System.Windows.Controls.PasswordBox.MaxLengthProperty, new Binding(MaxLengthProperty.Name) { Source = this });
ActualPasswordBox.SetBinding(System.Windows.Controls.PasswordBox.SelectionBrushProperty, new Binding(SelectionBrushProperty.Name) { Source = this });
#if !(NET40 || NET45 || NET451 || NET452 || NET46 || NET461 || NET462 || NET47 || NET471 || NET472)
ActualPasswordBox.SetBinding(System.Windows.Controls.PasswordBox.SelectionTextBrushProperty, new Binding(SelectionTextBrushProperty.Name) { Source = this });
#endif
ActualPasswordBox.SetBinding(System.Windows.Controls.PasswordBox.SelectionOpacityProperty, new Binding(SelectionOpacityProperty.Name) { Source = this });
ActualPasswordBox.SetBinding(System.Windows.Controls.PasswordBox.CaretBrushProperty, new Binding(CaretBrushProperty.Name) { Source = this });
if (_password != null)
{
@@ -77,7 +77,7 @@ namespace HandyControl.Controls
public bool IsRealTime
{
get => (bool)GetValue(IsRealTimeProperty);
set => SetValue(IsRealTimeProperty, value);
set => SetValue(IsRealTimeProperty, ValueBoxes.BooleanBox(value));
}
public static readonly DependencyProperty CommandProperty = DependencyProperty.Register(
@@ -8,7 +8,6 @@ using HandyControl.Tools;
namespace HandyControl.Controls
{
/// <inheritdoc cref="IDataInput" />
public class TextBox : System.Windows.Controls.TextBox, IDataInput
{
public TextBox()
@@ -35,8 +34,8 @@ namespace HandyControl.Controls
public bool IsError
{
get => (bool)GetValue(IsErrorProperty);
set => SetValue(IsErrorProperty, value);
get => (bool) GetValue(IsErrorProperty);
set => SetValue(IsErrorProperty, ValueBoxes.BooleanBox(value));
}
/// <summary>
@@ -71,8 +70,8 @@ namespace HandyControl.Controls
public bool ShowClearButton
{
get => (bool)GetValue(ShowClearButtonProperty);
set => SetValue(ShowClearButtonProperty, value);
get => (bool) GetValue(ShowClearButtonProperty);
set => SetValue(ShowClearButtonProperty, ValueBoxes.BooleanBox(value));
}
public virtual bool VerifyData()
@@ -130,7 +130,7 @@ namespace HandyControl.Controls
public bool IsDropDownOpen
{
get => (bool)GetValue(IsDropDownOpenProperty);
set => SetValue(IsDropDownOpenProperty, value);
set => SetValue(IsDropDownOpenProperty, ValueBoxes.BooleanBox(value));
}
public static readonly DependencyProperty IsDropDownOpenProperty =
@@ -262,7 +262,7 @@ namespace HandyControl.Controls
public bool IsError
{
get => (bool)GetValue(IsErrorProperty);
set => SetValue(IsErrorProperty, value);
set => SetValue(IsErrorProperty, ValueBoxes.BooleanBox(value));
}
public static readonly DependencyProperty ErrorStrProperty = DependencyProperty.Register(
@@ -289,7 +289,7 @@ namespace HandyControl.Controls
public bool ShowClearButton
{
get => (bool)GetValue(ShowClearButtonProperty);
set => SetValue(ShowClearButtonProperty, value);
set => SetValue(ShowClearButtonProperty, ValueBoxes.BooleanBox(value));
}
public static readonly DependencyProperty ClockProperty = DependencyProperty.Register(
@@ -2,7 +2,7 @@
namespace HandyControl.Controls
{
internal class WatermarkTextBox : TextBox
public class WatermarkTextBox : TextBox
{
#region Public Properties
@@ -31,7 +31,7 @@ namespace HandyControl.Controls
public bool IsRunning
{
get => (bool) GetValue(IsRunningProperty);
set => SetValue(IsRunningProperty, value);
set => SetValue(IsRunningProperty, ValueBoxes.BooleanBox(value));
}
public static readonly DependencyProperty DotCountProperty = DependencyProperty.Register(
@@ -4,6 +4,7 @@ using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Animation;
using HandyControl.Data;
namespace HandyControl.Controls
@@ -27,7 +28,7 @@ namespace HandyControl.Controls
public bool NeedHidden
{
get => (bool) GetValue(NeedHiddenProperty);
set => SetValue(NeedHiddenProperty, value);
set => SetValue(NeedHiddenProperty, ValueBoxes.BooleanBox(value));
}
static LoadingCircle()
@@ -100,7 +100,7 @@ namespace HandyControl.Controls
public bool IsPlaying
{
get => (bool)GetValue(IsPlayingProperty);
set => SetValue(IsPlayingProperty, value);
set => SetValue(IsPlayingProperty, ValueBoxes.BooleanBox(value));
}
public static readonly DependencyProperty RepeatBehaviorProperty = DependencyProperty.Register(
@@ -1,6 +1,7 @@
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using HandyControl.Data;
namespace HandyControl.Controls
@@ -85,7 +86,9 @@ namespace HandyControl.Controls
public bool ShowBadge
{
get => (bool) GetValue(ShowBadgeProperty);
set => SetValue(ShowBadgeProperty, value);
set => SetValue(ShowBadgeProperty, ValueBoxes.BooleanBox(value));
}
protected override Geometry GetLayoutClip(Size layoutSlotSize) => null;
}
}
@@ -30,7 +30,7 @@ namespace HandyControl.Controls
public bool IsRead
{
get => (bool) GetValue(IsReadProperty);
set => SetValue(IsReadProperty, value);
set => SetValue(IsReadProperty, ValueBoxes.BooleanBox(value));
}
public static void SetMaxWidth(DependencyObject element, double value)
@@ -0,0 +1,670 @@
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using HandyControl.Data;
using HandyControl.Expression.Drawing;
using HandyControl.Tools;
using HandyControl.Tools.Extension;
namespace HandyControl.Controls
{
public class DashedBorder : Decorator
{
private bool _useComplexRenderCodePath;
private Pen GeometryPenCache { get; set; }
private Pen LeftPenCache { get; set; }
private Pen RightPenCache { get; set; }
private Pen TopPenCache { get; set; }
private Pen BottomPenCache { get; set; }
private StreamGeometry BackgroundGeometryCache { get; set; }
private StreamGeometry BorderGeometryCache { get; set; }
private static void OnClearPenCache(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var border = (DashedBorder)d;
border.LeftPenCache = null;
border.RightPenCache = null;
border.TopPenCache = null;
border.BottomPenCache = null;
border.GeometryPenCache = null;
}
public static readonly DependencyProperty BorderThicknessProperty = DependencyProperty.Register(
"BorderThickness", typeof(Thickness), typeof(DashedBorder), new FrameworkPropertyMetadata(default(Thickness),
FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender,
OnClearPenCache));
public Thickness BorderThickness
{
get => (Thickness) GetValue(BorderThicknessProperty);
set => SetValue(BorderThicknessProperty, value);
}
public static readonly DependencyProperty BorderDashThicknessProperty = DependencyProperty.Register(
"BorderDashThickness", typeof(double), typeof(DashedBorder), new FrameworkPropertyMetadata(ValueBoxes.Double0Box,
FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender,
OnClearPenCache));
public double BorderDashThickness
{
get => (double) GetValue(BorderDashThicknessProperty);
set => SetValue(BorderDashThicknessProperty, value);
}
public static readonly DependencyProperty PaddingProperty = DependencyProperty.Register(
"Padding", typeof(Thickness), typeof(DashedBorder), new FrameworkPropertyMetadata(default(Thickness),
FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender));
public Thickness Padding
{
get => (Thickness) GetValue(PaddingProperty);
set => SetValue(PaddingProperty, value);
}
public static readonly DependencyProperty CornerRadiusProperty = DependencyProperty.Register(
"CornerRadius", typeof(CornerRadius), typeof(DashedBorder), new FrameworkPropertyMetadata(default(CornerRadius),
FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender));
public CornerRadius CornerRadius
{
get => (CornerRadius) GetValue(CornerRadiusProperty);
set => SetValue(CornerRadiusProperty, value);
}
public static readonly DependencyProperty BorderBrushProperty = DependencyProperty.Register(
"BorderBrush", typeof(Brush), typeof(DashedBorder), new FrameworkPropertyMetadata(default(Brush),
FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.SubPropertiesDoNotAffectRender,
OnClearPenCache));
public Brush BorderBrush
{
get => (Brush) GetValue(BorderBrushProperty);
set => SetValue(BorderBrushProperty, value);
}
public static readonly DependencyProperty BackgroundProperty = DependencyProperty.Register(
"Background", typeof(Brush), typeof(DashedBorder), new FrameworkPropertyMetadata(default(Brush),
FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.SubPropertiesDoNotAffectRender,
OnClearPenCache));
public Brush Background
{
get => (Brush) GetValue(BackgroundProperty);
set => SetValue(BackgroundProperty, value);
}
public static readonly DependencyProperty BorderDashArrayProperty = DependencyProperty.Register(
"BorderDashArray", typeof(DoubleCollection), typeof(DashedBorder), new FrameworkPropertyMetadata(default(DoubleCollection),
FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender,
OnClearPenCache));
public DoubleCollection BorderDashArray
{
get => (DoubleCollection) GetValue(BorderDashArrayProperty);
set => SetValue(BorderDashArrayProperty, value);
}
public static readonly DependencyProperty BorderDashCapProperty = DependencyProperty.Register(
"BorderDashCap", typeof(PenLineCap), typeof(DashedBorder), new FrameworkPropertyMetadata(default(PenLineCap),
FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender,
OnClearPenCache));
public PenLineCap BorderDashCap
{
get => (PenLineCap) GetValue(BorderDashCapProperty);
set => SetValue(BorderDashCapProperty, value);
}
public static readonly DependencyProperty BorderDashOffsetProperty = DependencyProperty.Register(
"BorderDashOffset", typeof(double), typeof(DashedBorder), new FrameworkPropertyMetadata(ValueBoxes.Double0Box,
FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender,
OnClearPenCache));
public double BorderDashOffset
{
get => (double) GetValue(BorderDashOffsetProperty);
set => SetValue(BorderDashOffsetProperty, value);
}
private static Size ConvertThickness2Size(Thickness th) => new Size(th.Left + th.Right, th.Top + th.Bottom);
private static Rect DeflateRect(Rect rt, Thickness thick) => new Rect(rt.Left + thick.Left,
rt.Top + thick.Top,
Math.Max(0.0, rt.Width - thick.Left - thick.Right),
Math.Max(0.0, rt.Height - thick.Top - thick.Bottom));
private static bool AreUniformCorners(CornerRadius borderRadii)
{
var topLeft = borderRadii.TopLeft;
return MathHelper.AreClose(topLeft, borderRadii.TopRight) &&
MathHelper.AreClose(topLeft, borderRadii.BottomLeft) &&
MathHelper.AreClose(topLeft, borderRadii.BottomRight);
}
private static void GenerateGeometry(StreamGeometryContext ctx, Rect rect, in Radii radii)
{
var topLeft = new Point(radii.LeftTop, 0);
var topRight = new Point(rect.Width - radii.RightTop, 0);
var rightTop = new Point(rect.Width, radii.TopRight);
var rightBottom = new Point(rect.Width, rect.Height - radii.BottomRight);
var bottomRight = new Point(rect.Width - radii.RightBottom, rect.Height);
var bottomLeft = new Point(radii.LeftBottom, rect.Height);
var leftBottom = new Point(0, rect.Height - radii.BottomLeft);
var leftTop = new Point(0, radii.TopLeft);
// top edge
if (topLeft.X > topRight.X)
{
var v = radii.LeftTop / (radii.LeftTop + radii.RightTop) * rect.Width;
topLeft.X = v;
topRight.X = v;
}
// right edge
if (rightTop.Y > rightBottom.Y)
{
var v = radii.TopRight / (radii.TopRight + radii.BottomRight) * rect.Height;
rightTop.Y = v;
rightBottom.Y = v;
}
// bottom edge
if (bottomRight.X < bottomLeft.X)
{
var v = radii.LeftBottom / (radii.LeftBottom + radii.RightBottom) * rect.Width;
bottomRight.X = v;
bottomLeft.X = v;
}
// left edge
if (leftBottom.Y < leftTop.Y)
{
var v = radii.TopLeft / (radii.TopLeft + radii.BottomLeft) * rect.Height;
leftBottom.Y = v;
leftTop.Y = v;
}
// add on offsets
var offset = new Vector(rect.TopLeft.X, rect.TopLeft.Y);
topLeft += offset;
topRight += offset;
rightTop += offset;
rightBottom += offset;
bottomRight += offset;
bottomLeft += offset;
leftBottom += offset;
leftTop += offset;
// create the border geometry
ctx.BeginFigure(topLeft, true, true);
// Top line
ctx.LineTo(topRight, true, false);
// Upper-right corner
var radiusX = rect.TopRight.X - topRight.X;
var radiusY = rightTop.Y - rect.TopRight.Y;
if (!MathHelper.IsZero(radiusX) || !MathHelper.IsZero(radiusY))
{
ctx.ArcTo(rightTop, new Size(radiusX, radiusY), 0, false, SweepDirection.Clockwise, true, false);
}
// Right line
ctx.LineTo(rightBottom, true, false);
// Lower-right corner
radiusX = rect.BottomRight.X - bottomRight.X;
radiusY = rect.BottomRight.Y - rightBottom.Y;
if (!MathHelper.IsZero(radiusX) || !MathHelper.IsZero(radiusY))
{
ctx.ArcTo(bottomRight, new Size(radiusX, radiusY), 0, false, SweepDirection.Clockwise, true, false);
}
// Bottom line
ctx.LineTo(bottomLeft, true, false);
// Lower-left corner
radiusX = bottomLeft.X - rect.BottomLeft.X;
radiusY = rect.BottomLeft.Y - leftBottom.Y;
if (!MathHelper.IsZero(radiusX) || !MathHelper.IsZero(radiusY))
{
ctx.ArcTo(leftBottom, new Size(radiusX, radiusY), 0, false, SweepDirection.Clockwise, true, false);
}
// Left line
ctx.LineTo(leftTop, true, false);
// Upper-left corner
radiusX = topLeft.X - rect.TopLeft.X;
radiusY = leftTop.Y - rect.TopLeft.Y;
if (!MathHelper.IsZero(radiusX) || !MathHelper.IsZero(radiusY))
{
ctx.ArcTo(topLeft, new Size(radiusX, radiusY), 0, false, SweepDirection.Clockwise, true, false);
}
}
protected override Size MeasureOverride(Size constraint)
{
var child = Child;
var borderThickness = BorderThickness;
var padding = Padding;
if (UseLayoutRounding)
{
var dpiScaleX = DpiHelper.DeviceDpiX;
var dpiScaleY = DpiHelper.DeviceDpiY;
borderThickness = new Thickness(
DpiHelper.RoundLayoutValue(borderThickness.Left, dpiScaleX),
DpiHelper.RoundLayoutValue(borderThickness.Top, dpiScaleY),
DpiHelper.RoundLayoutValue(borderThickness.Right, dpiScaleX),
DpiHelper.RoundLayoutValue(borderThickness.Bottom, dpiScaleY));
}
var borderSize = ConvertThickness2Size(borderThickness);
var paddingSize = ConvertThickness2Size(padding);
var mySize = new Size();
if (child != null)
{
var combined = new Size(borderSize.Width + paddingSize.Width, borderSize.Height + paddingSize.Height);
var childConstraint = new Size(Math.Max(0.0, constraint.Width - combined.Width), Math.Max(0.0, constraint.Height - combined.Height));
child.Measure(childConstraint);
var childSize = child.DesiredSize;
mySize.Width = childSize.Width + combined.Width;
mySize.Height = childSize.Height + combined.Height;
}
else
{
mySize = new Size(borderSize.Width + paddingSize.Width, borderSize.Height + paddingSize.Height);
}
return mySize;
}
protected override Size ArrangeOverride(Size arrangeSize)
{
var borderThickness = BorderThickness;
if (UseLayoutRounding)
{
var dpiScaleX = DpiHelper.DeviceDpiX;
var dpiScaleY = DpiHelper.DeviceDpiY;
borderThickness = new Thickness(
DpiHelper.RoundLayoutValue(borderThickness.Left, dpiScaleX),
DpiHelper.RoundLayoutValue(borderThickness.Top, dpiScaleY),
DpiHelper.RoundLayoutValue(borderThickness.Right, dpiScaleX),
DpiHelper.RoundLayoutValue(borderThickness.Bottom, dpiScaleY));
}
var boundRect = new Rect(arrangeSize);
var innerRect = DeflateRect(boundRect, borderThickness);
var child = Child;
if (child != null)
{
var padding = Padding;
var childRect = DeflateRect(innerRect, padding);
child.Arrange(childRect);
}
var radii = CornerRadius;
var borderBrush = BorderBrush;
var uniformCorners = AreUniformCorners(radii);
_useComplexRenderCodePath = !uniformCorners;
if (!_useComplexRenderCodePath && borderBrush != null)
{
_useComplexRenderCodePath = !MathHelper.IsZero(radii.TopLeft) && !borderThickness.IsUniform();
}
if (_useComplexRenderCodePath)
{
var innerRadii = new Radii(radii, borderThickness, false);
StreamGeometry backgroundGeometry = null;
if (!MathHelper.IsZero(innerRect.Width) && !MathHelper.IsZero(innerRect.Height))
{
backgroundGeometry = new StreamGeometry();
using (var ctx = backgroundGeometry.Open())
{
GenerateGeometry(ctx, innerRect, innerRadii);
}
backgroundGeometry.Freeze();
BackgroundGeometryCache = backgroundGeometry;
}
else
{
BackgroundGeometryCache = null;
}
if (!MathHelper.IsZero(boundRect.Width) && !MathHelper.IsZero(boundRect.Height))
{
var outerRadii = new Radii(radii, borderThickness, true);
var borderGeometry = new StreamGeometry();
using (var ctx = borderGeometry.Open())
{
GenerateGeometry(ctx, boundRect, outerRadii);
if (backgroundGeometry != null)
{
GenerateGeometry(ctx, innerRect, innerRadii);
}
}
borderGeometry.Freeze();
BorderGeometryCache = borderGeometry;
}
else
{
BorderGeometryCache = null;
}
}
else
{
BackgroundGeometryCache = null;
BorderGeometryCache = null;
}
return arrangeSize;
}
protected override void OnRender(DrawingContext drawingContext)
{
var background = Background;
var borderBrush = BorderBrush;
var useLayoutRounding = UseLayoutRounding;
if (_useComplexRenderCodePath)
{
var borderGeometry = BorderGeometryCache;
if (borderGeometry != null && borderBrush != null)
{
var pen = GeometryPenCache;
if (pen == null)
{
pen = new Pen
{
Brush = borderBrush,
Thickness = BorderDashThickness,
DashCap = BorderDashCap,
DashStyle = new DashStyle(BorderDashArray, BorderDashOffset)
};
if (borderBrush.IsFrozen)
{
pen.Freeze();
}
GeometryPenCache = pen;
}
drawingContext.DrawGeometry(null, pen, borderGeometry);
}
var backgroundGeometry = BackgroundGeometryCache;
if (backgroundGeometry != null && background != null)
{
drawingContext.DrawGeometry(background, null, backgroundGeometry);
}
}
else
{
var dpiScaleX = DpiHelper.DeviceDpiX;
var dpiScaleY = DpiHelper.DeviceDpiY;
var borderThickness = BorderThickness;
var cornerRadius = CornerRadius;
var outerCornerRadius = cornerRadius.TopLeft;
var roundedCorners = !MathHelper.IsZero(outerCornerRadius);
if (!borderThickness.IsZero() && borderBrush != null)
{
var pen = LeftPenCache;
if (pen == null)
{
pen = new Pen
{
Brush = borderBrush,
Thickness = useLayoutRounding
? DpiHelper.RoundLayoutValue(borderThickness.Left, dpiScaleX)
: borderThickness.Left,
DashCap = BorderDashCap,
DashStyle = new DashStyle(BorderDashArray, BorderDashOffset)
};
if (borderBrush.IsFrozen)
{
pen.Freeze();
}
LeftPenCache = pen;
}
double halfThickness;
var renderSize = RenderSize;
if (borderThickness.IsUniform())
{
halfThickness = pen.Thickness * 0.5;
var rect = new Rect(new Point(halfThickness, halfThickness), new Point(renderSize.Width - halfThickness, renderSize.Height - halfThickness));
if (roundedCorners)
{
drawingContext.DrawRoundedRectangle(null, pen, rect, outerCornerRadius, outerCornerRadius);
}
else
{
drawingContext.DrawRectangle(null, pen, rect);
}
}
else
{
if (MathHelper.GreaterThan(borderThickness.Left, 0))
{
halfThickness = pen.Thickness * 0.5;
drawingContext.DrawLine(pen, new Point(halfThickness, 0), new Point(halfThickness, renderSize.Height));
}
if (MathHelper.GreaterThan(borderThickness.Right, 0))
{
pen = RightPenCache;
if (pen == null)
{
pen = new Pen
{
Brush = borderBrush,
Thickness = useLayoutRounding
? DpiHelper.RoundLayoutValue(borderThickness.Right, dpiScaleX)
: borderThickness.Right,
DashCap = BorderDashCap,
DashStyle = new DashStyle(BorderDashArray, BorderDashOffset)
};
if (borderBrush.IsFrozen)
{
pen.Freeze();
}
RightPenCache = pen;
}
halfThickness = pen.Thickness * 0.5;
drawingContext.DrawLine(pen, new Point(renderSize.Width - halfThickness, 0), new Point(renderSize.Width - halfThickness, renderSize.Height));
}
if (MathHelper.GreaterThan(borderThickness.Top, 0))
{
pen = TopPenCache;
if (pen == null)
{
pen = new Pen
{
Brush = borderBrush,
Thickness = useLayoutRounding
? DpiHelper.RoundLayoutValue(borderThickness.Top, dpiScaleY)
: borderThickness.Top,
DashCap = BorderDashCap,
DashStyle = new DashStyle(BorderDashArray, BorderDashOffset)
};
if (borderBrush.IsFrozen)
{
pen.Freeze();
}
TopPenCache = pen;
}
halfThickness = pen.Thickness * 0.5;
drawingContext.DrawLine(pen, new Point(0, halfThickness), new Point(renderSize.Width, halfThickness));
}
if (MathHelper.GreaterThan(borderThickness.Bottom, 0))
{
pen = BottomPenCache;
if (pen == null)
{
pen = new Pen
{
Brush = borderBrush,
Thickness = useLayoutRounding
? DpiHelper.RoundLayoutValue(borderThickness.Bottom, dpiScaleY)
: borderThickness.Bottom,
DashCap = BorderDashCap,
DashStyle = new DashStyle(BorderDashArray, BorderDashOffset)
};
if (borderBrush.IsFrozen)
{
pen.Freeze();
}
BottomPenCache = pen;
}
halfThickness = pen.Thickness * 0.5;
drawingContext.DrawLine(pen, new Point(0, renderSize.Height - halfThickness), new Point(renderSize.Width, renderSize.Height - halfThickness));
}
}
}
if (background != null)
{
Point ptTL, ptBR;
if (useLayoutRounding)
{
ptTL = new Point(DpiHelper.RoundLayoutValue(borderThickness.Left, dpiScaleX), DpiHelper.RoundLayoutValue(borderThickness.Top, dpiScaleY));
ptBR = new Point(RenderSize.Width - DpiHelper.RoundLayoutValue(borderThickness.Right, dpiScaleX),
RenderSize.Height - DpiHelper.RoundLayoutValue(borderThickness.Bottom, dpiScaleY));
}
else
{
ptTL = new Point(borderThickness.Left, borderThickness.Top);
ptBR = new Point(RenderSize.Width - borderThickness.Right, RenderSize.Height - borderThickness.Bottom);
}
if (ptBR.X > ptTL.X && ptBR.Y > ptTL.Y)
{
if (roundedCorners)
{
var innerRadii = new Radii(cornerRadius, borderThickness, false);
var innerCornerRadius = innerRadii.TopLeft;
drawingContext.DrawRoundedRectangle(background, null, new Rect(ptTL, ptBR), innerCornerRadius, innerCornerRadius);
}
else
{
drawingContext.DrawRectangle(background, null, new Rect(ptTL, ptBR));
}
}
}
}
}
private readonly struct Radii
{
internal Radii(CornerRadius radii, Thickness borders, bool outer)
{
var left = 0.5 * borders.Left;
var top = 0.5 * borders.Top;
var right = 0.5 * borders.Right;
var bottom = 0.5 * borders.Bottom;
if (outer)
{
if (MathHelper.IsZero(radii.TopLeft))
{
LeftTop = TopLeft = 0.0;
}
else
{
LeftTop = radii.TopLeft + left;
TopLeft = radii.TopLeft + top;
}
if (MathHelper.IsZero(radii.TopRight))
{
TopRight = RightTop = 0.0;
}
else
{
TopRight = radii.TopRight + top;
RightTop = radii.TopRight + right;
}
if (MathHelper.IsZero(radii.BottomRight))
{
RightBottom = BottomRight = 0.0;
}
else
{
RightBottom = radii.BottomRight + right;
BottomRight = radii.BottomRight + bottom;
}
if (MathHelper.IsZero(radii.BottomLeft))
{
BottomLeft = LeftBottom = 0.0;
}
else
{
BottomLeft = radii.BottomLeft + bottom;
LeftBottom = radii.BottomLeft + left;
}
}
else
{
LeftTop = Math.Max(0.0, radii.TopLeft - left);
TopLeft = Math.Max(0.0, radii.TopLeft - top);
TopRight = Math.Max(0.0, radii.TopRight - top);
RightTop = Math.Max(0.0, radii.TopRight - right);
RightBottom = Math.Max(0.0, radii.BottomRight - right);
BottomRight = Math.Max(0.0, radii.BottomRight - bottom);
BottomLeft = Math.Max(0.0, radii.BottomLeft - bottom);
LeftBottom = Math.Max(0.0, radii.BottomLeft - left);
}
}
internal readonly double LeftTop;
internal readonly double TopLeft;
internal readonly double TopRight;
internal readonly double RightTop;
internal readonly double RightBottom;
internal readonly double BottomRight;
internal readonly double BottomLeft;
internal readonly double LeftBottom;
}
}
}
@@ -1,6 +1,7 @@
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Markup;
@@ -37,12 +38,15 @@ namespace HandyControl.Controls
private Point _contentRenderTransformOrigin;
static Drawer()
{
DataContextProperty.OverrideMetadata(typeof(Drawer), new FrameworkPropertyMetadata(DataContextPropertyChanged));
}
public Drawer()
{
Loaded += Drawer_Loaded;
Unloaded += Drawer_Unloaded;
CommandBindings.Add(new CommandBinding(ControlCommands.Close, (s, e) => SetCurrentValue(IsOpenProperty, ValueBoxes.FalseBox)));
}
private void Drawer_Loaded(object sender, RoutedEventArgs e)
@@ -68,6 +72,11 @@ namespace HandyControl.Controls
}
}
private static void DataContextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) =>
((Drawer)d).OnDataContextPropertyChanged(e);
private void OnDataContextPropertyChanged(DependencyPropertyChangedEventArgs e) => UpdateDataContext(_animationControl, e.OldValue, e.NewValue);
public static readonly RoutedEvent OpenedEvent =
EventManager.RegisterRoutedEvent("Opened", RoutingStrategy.Bubble,
typeof(RoutedEventHandler), typeof(Drawer));
@@ -100,7 +109,7 @@ namespace HandyControl.Controls
public bool IsOpen
{
get => (bool) GetValue(IsOpenProperty);
set => SetValue(IsOpenProperty, value);
set => SetValue(IsOpenProperty, ValueBoxes.BooleanBox(value));
}
public static readonly DependencyProperty MaskCanCloseProperty = DependencyProperty.Register(
@@ -109,7 +118,7 @@ namespace HandyControl.Controls
public bool MaskCanClose
{
get => (bool) GetValue(MaskCanCloseProperty);
set => SetValue(MaskCanCloseProperty, value);
set => SetValue(MaskCanCloseProperty, ValueBoxes.BooleanBox(value));
}
public static readonly DependencyProperty ShowMaskProperty = DependencyProperty.Register(
@@ -118,7 +127,7 @@ namespace HandyControl.Controls
public bool ShowMask
{
get => (bool) GetValue(ShowMaskProperty);
set => SetValue(ShowMaskProperty, value);
set => SetValue(ShowMaskProperty, ValueBoxes.BooleanBox(value));
}
public static readonly DependencyProperty DockProperty = DependencyProperty.Register(
@@ -223,6 +232,9 @@ namespace HandyControl.Controls
throw new ArgumentOutOfRangeException();
}
_animationControl.DataContext = DataContext;
_animationControl.CommandBindings.Clear();
_animationControl.CommandBindings.Add(new CommandBinding(ControlCommands.Close, (s, e) => SetCurrentValue(IsOpenProperty, ValueBoxes.FalseBox)));
panel.Children.Add(_animationControl);
_container = new AdornerContainer(_layer)
{
@@ -381,5 +393,14 @@ namespace HandyControl.Controls
SetCurrentValue(IsOpenProperty, ValueBoxes.FalseBox);
}
}
private void UpdateDataContext(FrameworkElement target, object oldValue, object newValue)
{
if (target == null || BindingOperations.GetBindingExpression(target, DataContextProperty) != null) return;
if (ReferenceEquals(this, target.DataContext) || Equals(oldValue, target.DataContext))
{
target.DataContext = newValue ?? this;
}
}
}
}
@@ -60,7 +60,7 @@ namespace HandyControl.Controls
public bool Animated
{
get => (bool) GetValue(AnimatedProperty);
set => SetValue(AnimatedProperty, value);
set => SetValue(AnimatedProperty, ValueBoxes.BooleanBox(value));
}
public static readonly DependencyProperty AnimationTimeProperty = DependencyProperty.Register(
@@ -73,7 +73,7 @@ namespace HandyControl.Controls
}
public static readonly DependencyProperty HidingHeightProperty = DependencyProperty.Register(
"HidingHeight", typeof(double), typeof(GotoTop), new PropertyMetadata(default(double)));
"HidingHeight", typeof(double), typeof(GotoTop), new PropertyMetadata(ValueBoxes.Double0Box));
public double HidingHeight
{
@@ -87,7 +87,7 @@ namespace HandyControl.Controls
public bool AutoHiding
{
get => (bool) GetValue(AutoHidingProperty);
set => SetValue(AutoHidingProperty, value);
set => SetValue(AutoHidingProperty, ValueBoxes.BooleanBox(value));
}
protected override void OnClick()
@@ -32,14 +32,20 @@ namespace HandyControl.Controls
set => SetValue(IdProperty, value);
}
public static readonly DependencyProperty SourceProperty = DependencyProperty.Register(
"Source", typeof(ImageSource), typeof(Gravatar), new PropertyMetadata(default(ImageSource), OnSourceChanged));
private static void OnSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var ctl = (Gravatar)d;
ctl.Background = new ImageBrush((ImageSource)e.NewValue);
var v = (ImageSource) e.NewValue;
ctl.Background = v != null
? new ImageBrush(v)
{
Stretch = Stretch.UniformToFill
}
: ResourceHelper.GetResource<Brush>("SecondaryRegionBrush");
}
public ImageSource Source
@@ -122,7 +122,9 @@ namespace HandyControl.Controls
private void HideAdornerElement()
{
if (_adornerContainer == null) return;
var layer = AdornerLayer.GetAdornerLayer(Target);
if (layer != null)
{
layer.Remove(_adornerContainer);
@@ -335,7 +335,7 @@ namespace HandyControl.Controls
public bool IsBlink
{
get => (bool)GetValue(IsBlinkProperty);
set => SetValue(IsBlinkProperty, value);
set => SetValue(IsBlinkProperty, ValueBoxes.BooleanBox(value));
}
private void DispatcherTimerBlinkTick(object sender, EventArgs e)
@@ -574,6 +574,7 @@ namespace HandyControl.Controls
{
if (msg == _wmTaskbarCreated)
{
_added = false;
UpdateIcon(true);
}
else
@@ -19,6 +19,7 @@ namespace HandyControl.Controls
[TemplatePart(Name = ElementPanelMain, Type = typeof(Panel))]
[TemplatePart(Name = ElementMoreRight, Type = typeof(FrameworkElement))]
[TemplatePart(Name = ElementButtonLast, Type = typeof(RadioButton))]
[TemplatePart(Name = ElementButtonLast, Type = typeof(NumericUpDown))]
public class Pagination : Control
{
#region Constants
@@ -30,6 +31,7 @@ namespace HandyControl.Controls
private const string ElementPanelMain = "PART_PanelMain";
private const string ElementMoreRight = "PART_MoreRight";
private const string ElementButtonLast = "PART_ButtonLast";
private const string ElementJump = "PART_Jump";
#endregion Constants
@@ -42,6 +44,7 @@ namespace HandyControl.Controls
private Panel _panelMain;
private FrameworkElement _moreRight;
private RadioButton _buttonLast;
private NumericUpDown _jumpNumericUpDown;
private bool _appliedTemplate;
@@ -72,6 +75,7 @@ namespace HandyControl.Controls
CommandBindings.Add(new CommandBinding(ControlCommands.Prev, ButtonPrev_OnClick));
CommandBindings.Add(new CommandBinding(ControlCommands.Next, ButtonNext_OnClick));
CommandBindings.Add(new CommandBinding(ControlCommands.Selected, ToggleButton_OnChecked));
CommandBindings.Add(new CommandBinding(ControlCommands.Jump, (s, e) => PageIndex = (int) _jumpNumericUpDown.Value));
this.Show(MaxPageCount > 1);
}
@@ -219,6 +223,19 @@ namespace HandyControl.Controls
#endregion MaxPageInterval
#region IsJumpEnabled
public static readonly DependencyProperty IsJumpEnabledProperty = DependencyProperty.Register(
"IsJumpEnabled", typeof(bool), typeof(Pagination), new PropertyMetadata(ValueBoxes.FalseBox));
public bool IsJumpEnabled
{
get => (bool) GetValue(IsJumpEnabledProperty);
set => SetValue(IsJumpEnabledProperty, ValueBoxes.BooleanBox(value));
}
#endregion
#endregion
#region Public Methods
@@ -235,6 +252,7 @@ namespace HandyControl.Controls
_panelMain = GetTemplateChild(ElementPanelMain) as Panel;
_moreRight = GetTemplateChild(ElementMoreRight) as FrameworkElement;
_buttonLast = GetTemplateChild(ElementButtonLast) as RadioButton;
_jumpNumericUpDown = GetTemplateChild(ElementJump) as NumericUpDown;
CheckNull();
@@ -137,7 +137,7 @@ namespace HandyControl.Controls
}
public static void SetIsOpen(DependencyObject element, bool value)
=> element.SetValue(IsOpenProperty, value);
=> element.SetValue(IsOpenProperty, ValueBoxes.BooleanBox(value));
public static bool GetIsOpen(DependencyObject element)
=> (bool) element.GetValue(IsOpenProperty);
@@ -145,7 +145,7 @@ namespace HandyControl.Controls
public bool IsOpen
{
get => (bool) GetValue(IsOpenProperty);
set => SetValue(IsOpenProperty, value);
set => SetValue(IsOpenProperty, ValueBoxes.BooleanBox(value));
}
public static Poptip Default => new Poptip();
@@ -44,7 +44,7 @@ namespace HandyControl.Controls
public bool CanMouseWheel
{
get => (bool) GetValue(CanMouseWheelProperty);
set => SetValue(CanMouseWheelProperty, value);
set => SetValue(CanMouseWheelProperty, ValueBoxes.BooleanBox(value));
}
protected override void OnMouseWheel(MouseWheelEventArgs e)
@@ -145,15 +145,9 @@ namespace HandyControl.Controls
public static readonly DependencyProperty IsInertiaEnabledProperty = DependencyProperty.RegisterAttached(
"IsInertiaEnabled", typeof(bool), typeof(ScrollViewer), new PropertyMetadata(ValueBoxes.FalseBox));
public static void SetIsInertiaEnabled(DependencyObject element, bool value)
{
element.SetValue(IsInertiaEnabledProperty, value);
}
public static void SetIsInertiaEnabled(DependencyObject element, bool value) => element.SetValue(IsInertiaEnabledProperty, ValueBoxes.BooleanBox(value));
public static bool GetIsInertiaEnabled(DependencyObject element)
{
return (bool)element.GetValue(IsInertiaEnabledProperty);
}
public static bool GetIsInertiaEnabled(DependencyObject element) => (bool)element.GetValue(IsInertiaEnabledProperty);
/// <summary>
/// 是否支持惯性
@@ -161,7 +155,7 @@ namespace HandyControl.Controls
public bool IsInertiaEnabled
{
get => (bool) GetValue(IsInertiaEnabledProperty);
set => SetValue(IsInertiaEnabledProperty, value);
set => SetValue(IsInertiaEnabledProperty, ValueBoxes.BooleanBox(value));
}
/// <summary>
@@ -176,18 +170,12 @@ namespace HandyControl.Controls
public bool IsPenetrating
{
get => (bool) GetValue(IsPenetratingProperty);
set => SetValue(IsPenetratingProperty, value);
set => SetValue(IsPenetratingProperty, ValueBoxes.BooleanBox(value));
}
public static void SetIsPenetrating(DependencyObject element, bool value)
{
element.SetValue(IsPenetratingProperty, value);
}
public static void SetIsPenetrating(DependencyObject element, bool value) => element.SetValue(IsPenetratingProperty, ValueBoxes.BooleanBox(value));
public static bool GetIsPenetrating(DependencyObject element)
{
return (bool) element.GetValue(IsPenetratingProperty);
}
public static bool GetIsPenetrating(DependencyObject element) => (bool) element.GetValue(IsPenetratingProperty);
/// <summary>
/// 当前垂直滚动偏移
@@ -72,16 +72,16 @@ namespace HandyControl.Controls
}
public static readonly DependencyProperty AutoSizeEnabledProperty = DependencyProperty.Register(
"AutoSizeEnabled", typeof(bool), typeof(Watermark), new PropertyMetadata(ValueBoxes.TrueBox));
"AutoSizeEnabled", typeof(bool), typeof(Watermark), new FrameworkPropertyMetadata(ValueBoxes.TrueBox, FrameworkPropertyMetadataOptions.AffectsRender));
public bool AutoSizeEnabled
{
get => (bool) GetValue(AutoSizeEnabledProperty);
set => SetValue(AutoSizeEnabledProperty, value);
set => SetValue(AutoSizeEnabledProperty, ValueBoxes.BooleanBox(value));
}
public static readonly DependencyProperty MarkMarginProperty = DependencyProperty.Register(
"MarkMargin", typeof(Thickness), typeof(Watermark), new PropertyMetadata(default(Thickness)));
"MarkMargin", typeof(Thickness), typeof(Watermark), new FrameworkPropertyMetadata(default(Thickness), FrameworkPropertyMetadataOptions.AffectsRender));
public Thickness MarkMargin
{
@@ -111,7 +111,8 @@ namespace HandyControl.Controls
presenter.Content = new TextBlock
{
Text = str,
FontSize = FontSize
FontSize = FontSize,
Foreground = MarkBrush
};
}
else
@@ -23,7 +23,7 @@ namespace HandyControl.Controls
public bool KeepVertical
{
get => (bool) GetValue(KeepVerticalProperty);
set => SetValue(KeepVerticalProperty, value);
set => SetValue(KeepVerticalProperty, ValueBoxes.BooleanBox(value));
}
public static readonly DependencyProperty OffsetAngleProperty = DependencyProperty.Register(
@@ -47,7 +47,7 @@ namespace HandyControl.Controls
public bool IsFixed
{
get => (bool) GetValue(IsFixedProperty);
set => SetValue(IsFixedProperty, value);
set => SetValue(IsFixedProperty, ValueBoxes.BooleanBox(value));
}
internal int GetLayoutCellCount(ColLayoutStatus status)
@@ -8,6 +8,7 @@ using System.Windows;
using System.Windows.Controls;
using System.Windows.Markup;
using HandyControl.Data;
using HandyControl.Tools.Extension;
namespace HandyControl.Controls
{
@@ -17,13 +18,13 @@ namespace HandyControl.Controls
public RelativePanel() => _childGraph = new Graph();
#region 容器对齐方式
#region Panel alignment
public static readonly DependencyProperty AlignLeftWithPanelProperty = DependencyProperty.RegisterAttached(
"AlignLeftWithPanel", typeof(bool), typeof(RelativePanel), new FrameworkPropertyMetadata(ValueBoxes.FalseBox, FrameworkPropertyMetadataOptions.AffectsRender));
public static void SetAlignLeftWithPanel(DependencyObject element, bool value)
=> element.SetValue(AlignLeftWithPanelProperty, value);
=> element.SetValue(AlignLeftWithPanelProperty, ValueBoxes.BooleanBox(value));
public static bool GetAlignLeftWithPanel(DependencyObject element)
=> (bool) element.GetValue(AlignLeftWithPanelProperty);
@@ -32,7 +33,7 @@ namespace HandyControl.Controls
"AlignTopWithPanel", typeof(bool), typeof(RelativePanel), new FrameworkPropertyMetadata(ValueBoxes.FalseBox, FrameworkPropertyMetadataOptions.AffectsRender));
public static void SetAlignTopWithPanel(DependencyObject element, bool value)
=> element.SetValue(AlignTopWithPanelProperty, value);
=> element.SetValue(AlignTopWithPanelProperty, ValueBoxes.BooleanBox(value));
public static bool GetAlignTopWithPanel(DependencyObject element)
=> (bool) element.GetValue(AlignTopWithPanelProperty);
@@ -41,7 +42,7 @@ namespace HandyControl.Controls
"AlignRightWithPanel", typeof(bool), typeof(RelativePanel), new FrameworkPropertyMetadata(ValueBoxes.FalseBox, FrameworkPropertyMetadataOptions.AffectsRender));
public static void SetAlignRightWithPanel(DependencyObject element, bool value)
=> element.SetValue(AlignRightWithPanelProperty, value);
=> element.SetValue(AlignRightWithPanelProperty, ValueBoxes.BooleanBox(value));
public static bool GetAlignRightWithPanel(DependencyObject element)
=> (bool) element.GetValue(AlignRightWithPanelProperty);
@@ -50,14 +51,14 @@ namespace HandyControl.Controls
"AlignBottomWithPanel", typeof(bool), typeof(RelativePanel), new FrameworkPropertyMetadata(ValueBoxes.FalseBox, FrameworkPropertyMetadataOptions.AffectsRender));
public static void SetAlignBottomWithPanel(DependencyObject element, bool value)
=> element.SetValue(AlignBottomWithPanelProperty, value);
=> element.SetValue(AlignBottomWithPanelProperty, ValueBoxes.BooleanBox(value));
public static bool GetAlignBottomWithPanel(DependencyObject element)
=> (bool) element.GetValue(AlignBottomWithPanelProperty);
#endregion
#region 元素间对齐方式
#region Sibling alignment
public static readonly DependencyProperty AlignLeftWithProperty = DependencyProperty.RegisterAttached(
"AlignLeftWith", typeof(UIElement), typeof(RelativePanel), new FrameworkPropertyMetadata(default(UIElement), FrameworkPropertyMetadataOptions.AffectsRender));
@@ -101,7 +102,7 @@ namespace HandyControl.Controls
#endregion
#region 元素间位置关系
#region Sibling positional
public static readonly DependencyProperty LeftOfProperty = DependencyProperty.RegisterAttached(
"LeftOf", typeof(UIElement), typeof(RelativePanel), new FrameworkPropertyMetadata(default(UIElement), FrameworkPropertyMetadataOptions.AffectsRender));
@@ -145,13 +146,13 @@ namespace HandyControl.Controls
#endregion
#region 居中对齐方式
#region Center alignment
public static readonly DependencyProperty AlignHorizontalCenterWithPanelProperty = DependencyProperty.RegisterAttached(
"AlignHorizontalCenterWithPanel", typeof(bool), typeof(RelativePanel), new FrameworkPropertyMetadata(ValueBoxes.FalseBox, FrameworkPropertyMetadataOptions.AffectsRender));
public static void SetAlignHorizontalCenterWithPanel(DependencyObject element, bool value)
=> element.SetValue(AlignHorizontalCenterWithPanelProperty, value);
=> element.SetValue(AlignHorizontalCenterWithPanelProperty, ValueBoxes.BooleanBox(value));
public static bool GetAlignHorizontalCenterWithPanel(DependencyObject element)
=> (bool)element.GetValue(AlignHorizontalCenterWithPanelProperty);
@@ -160,7 +161,7 @@ namespace HandyControl.Controls
"AlignVerticalCenterWithPanel", typeof(bool), typeof(RelativePanel), new FrameworkPropertyMetadata(ValueBoxes.FalseBox, FrameworkPropertyMetadataOptions.AffectsRender));
public static void SetAlignVerticalCenterWithPanel(DependencyObject element, bool value)
=> element.SetValue(AlignVerticalCenterWithPanelProperty, value);
=> element.SetValue(AlignVerticalCenterWithPanelProperty, ValueBoxes.BooleanBox(value));
public static bool GetAlignVerticalCenterWithPanel(DependencyObject element)
=> (bool)element.GetValue(AlignVerticalCenterWithPanelProperty);
@@ -189,22 +190,12 @@ namespace HandyControl.Controls
protected override Size MeasureOverride(Size availableSize)
{
foreach (UIElement child in InternalChildren)
{
child?.Measure(availableSize);
}
return base.MeasureOverride(availableSize);
}
protected override Size ArrangeOverride(Size arrangeSize)
{
_childGraph.Reset(arrangeSize);
#region Calc DesiredSize
_childGraph.Clear();
foreach (UIElement child in InternalChildren)
{
if (child == null) continue;
var node = _childGraph.AddNode(child);
node.AlignLeftWithNode = _childGraph.AddLink(node, GetAlignLeftWith(child));
@@ -220,23 +211,49 @@ namespace HandyControl.Controls
node.AlignHorizontalCenterWith = _childGraph.AddLink(node, GetAlignHorizontalCenterWith(child));
node.AlignVerticalCenterWith = _childGraph.AddLink(node, GetAlignVerticalCenterWith(child));
}
_childGraph.Measure(availableSize);
if (_childGraph.CheckCyclic())
{
throw new Exception("RelativePanel error: Circular dependency detected. Layout could not complete.");
}
#endregion
#region Calc AvailableSize
_childGraph.Reset();
var boundingSize = _childGraph.GetBoundingSize(Width.IsNaN(), Height.IsNaN());
_childGraph.Reset();
_childGraph.Measure(boundingSize);
return boundingSize;
#endregion
}
protected override Size ArrangeOverride(Size arrangeSize)
{
_childGraph.GetNodes().Do(node => node.Arrange(arrangeSize));
return arrangeSize;
}
private class GraphNode
{
public Point Position { get; set; }
public bool Arranged { get; set; }
public bool Measured { get; set; }
public UIElement Element { get; }
private bool HorizontalOffsetFlag { get; set; }
private bool VerticalOffsetFlag { get; set; }
private Size BoundingSize { get; set; }
public Size OriginDesiredSize { get; set; }
public double Left { get; set; } = double.NaN;
public double Top { get; set; } = double.NaN;
public double Right { get; set; } = double.NaN;
public double Bottom { get; set; } = double.NaN;
public HashSet<GraphNode> OutgoingNodes { get; }
public GraphNode AlignLeftWithNode { get; set; }
@@ -264,19 +281,100 @@ namespace HandyControl.Controls
OutgoingNodes = new HashSet<GraphNode>();
Element = element;
}
public void Arrange(Size arrangeSize) => Element.Arrange(new Rect(Left, Top, Math.Max(arrangeSize.Width - Left - Right, 0), Math.Max(arrangeSize.Height - Top - Bottom, 0)));
public void Reset()
{
Left = double.NaN;
Top = double.NaN;
Right = double.NaN;
Bottom = double.NaN;
Measured = false;
}
public Size GetBoundingSize()
{
if (Measured) return BoundingSize;
if (!OutgoingNodes.Any())
{
BoundingSize = Element.DesiredSize;
Measured = true;
}
else
{
BoundingSize = GetBoundingSize(this, Element.DesiredSize, OutgoingNodes);
Measured = true;
}
return BoundingSize;
}
private static Size GetBoundingSize(GraphNode prevNode, Size prevSize, IEnumerable<GraphNode> nodes)
{
foreach (var node in nodes)
{
if (node.Measured || !node.OutgoingNodes.Any())
{
if (prevNode.LeftOfNode != null && prevNode.LeftOfNode == node ||
prevNode.RightOfNode != null && prevNode.RightOfNode == node)
{
prevSize.Width += node.BoundingSize.Width;
if (GetAlignHorizontalCenterWithPanel(node.Element) || node.HorizontalOffsetFlag)
{
prevSize.Width += prevNode.OriginDesiredSize.Width;
prevNode.HorizontalOffsetFlag = true;
}
if (node.VerticalOffsetFlag)
{
prevNode.VerticalOffsetFlag = true;
}
}
if (prevNode.AboveNode != null && prevNode.AboveNode == node ||
prevNode.BelowNode != null && prevNode.BelowNode == node)
{
prevSize.Height += node.BoundingSize.Height;
if (GetAlignVerticalCenterWithPanel(node.Element) || node.VerticalOffsetFlag)
{
prevSize.Height += prevNode.OriginDesiredSize.Height;
prevNode.VerticalOffsetFlag = true;
}
if (node.HorizontalOffsetFlag)
{
prevNode.HorizontalOffsetFlag = true;
}
}
}
else
{
return GetBoundingSize(node, prevSize, node.OutgoingNodes);
}
}
return prevSize;
}
}
private class Graph
{
private readonly Dictionary<DependencyObject, GraphNode> _nodeDic;
private Size _arrangeSize;
private Size AvailableSize { get; set; }
public Graph()
public Graph() => _nodeDic = new Dictionary<DependencyObject, GraphNode>();
public IEnumerable<GraphNode> GetNodes() => _nodeDic.Values;
public void Clear()
{
_nodeDic = new Dictionary<DependencyObject, GraphNode>();
AvailableSize = new Size();
_nodeDic.Clear();
}
public void Reset() => _nodeDic.Values.Do(node => node.Reset());
public GraphNode AddLink(GraphNode from, UIElement to)
{
if (to == null) return null;
@@ -308,20 +406,15 @@ namespace HandyControl.Controls
return _nodeDic[value];
}
public void Reset(Size arrangeSize)
public void Measure(Size availableSize)
{
_arrangeSize = arrangeSize;
_nodeDic.Clear();
AvailableSize = availableSize;
Measure(_nodeDic.Values, null);
}
public bool CheckCyclic() => CheckCyclic(_nodeDic.Values, null);
private bool CheckCyclic(IEnumerable<GraphNode> nodes, HashSet<DependencyObject> set)
private void Measure(IEnumerable<GraphNode> nodes, HashSet<DependencyObject> set)
{
if (set == null)
{
set = new HashSet<DependencyObject>();
}
set ??= new HashSet<DependencyObject>();
foreach (var node in nodes)
{
@@ -329,185 +422,259 @@ namespace HandyControl.Controls
* 该节点无任何依赖,所以从这里开始计算元素位置。
* 因为无任何依赖,所以忽略同级元素
*/
if (!node.Arranged && node.OutgoingNodes.Count == 0)
if (!node.Measured && !node.OutgoingNodes.Any())
{
ArrangeChild(node, true);
MeasureChild(node);
continue;
}
// 判断依赖元素是否全部排列完毕
if (node.OutgoingNodes.All(item => item.Arranged))
if (node.OutgoingNodes.All(item => item.Measured))
{
ArrangeChild(node);
MeasureChild(node);
continue;
}
// 判断是否有循环
if (!set.Add(node.Element)) return true;
if (!set.Add(node.Element)) throw new Exception("RelativePanel error: Circular dependency detected. Layout could not complete.");
// 没有循环,且有依赖,则继续往下
return CheckCyclic(node.OutgoingNodes, set);
}
Measure(node.OutgoingNodes, set);
return false;
if (!node.Measured)
{
MeasureChild(node);
}
}
}
private void ArrangeChild(GraphNode node, bool ignoneSibling = false)
private void MeasureChild(GraphNode node)
{
var child = node.Element;
var childSize = child.DesiredSize;
var childPos = new Point();
#region 容器居中对齐
if (GetAlignHorizontalCenterWithPanel(child))
{
childPos.X = (_arrangeSize.Width - childSize.Width) / 2;
}
if (GetAlignVerticalCenterWithPanel(child))
{
childPos.Y = (_arrangeSize.Height - childSize.Height) / 2;
}
#endregion
child.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
node.OriginDesiredSize = child.DesiredSize;
var alignLeftWithPanel = GetAlignLeftWithPanel(child);
var alignTopWithPanel = GetAlignTopWithPanel(child);
var alignRightWithPanel = GetAlignRightWithPanel(child);
var alignBottomWithPanel = GetAlignBottomWithPanel(child);
if (!ignoneSibling)
#region Panel alignment
if (alignLeftWithPanel) node.Left = 0;
if (alignTopWithPanel) node.Top = 0;
if (alignRightWithPanel) node.Right = 0;
if (alignBottomWithPanel) node.Bottom = 0;
#endregion
#region Sibling alignment
if (node.AlignLeftWithNode != null)
{
#region 元素间位置
if (node.LeftOfNode != null)
{
childPos.X = node.LeftOfNode.Position.X - childSize.Width;
}
if (node.AboveNode != null)
{
childPos.Y = node.AboveNode.Position.Y - childSize.Height;
}
if (node.RightOfNode != null)
{
childPos.X = node.RightOfNode.Position.X + node.RightOfNode.Element.DesiredSize.Width;
}
if (node.BelowNode != null)
{
childPos.Y = node.BelowNode.Position.Y + node.BelowNode.Element.DesiredSize.Height;
}
#endregion
#region 元素居中对齐
if (node.AlignHorizontalCenterWith != null)
{
childPos.X = node.AlignHorizontalCenterWith.Position.X +
(node.AlignHorizontalCenterWith.Element.DesiredSize.Width - childSize.Width) / 2;
}
if (node.AlignVerticalCenterWith != null)
{
childPos.Y = node.AlignVerticalCenterWith.Position.Y +
(node.AlignVerticalCenterWith.Element.DesiredSize.Height - childSize.Height) / 2;
}
#endregion
#region 元素间对齐
if (node.AlignLeftWithNode != null)
{
childPos.X = node.AlignLeftWithNode.Position.X;
}
if (node.AlignTopWithNode != null)
{
childPos.Y = node.AlignTopWithNode.Position.Y;
}
if (node.AlignRightWithNode != null)
{
childPos.X = node.AlignRightWithNode.Element.DesiredSize.Width + node.AlignRightWithNode.Position.X - childSize.Width;
}
if (node.AlignBottomWithNode != null)
{
childPos.Y = node.AlignBottomWithNode.Element.DesiredSize.Height + node.AlignBottomWithNode.Position.Y - childSize.Height;
}
#endregion
node.Left = node.Left.IsNaN() ? node.AlignLeftWithNode.Left : node.AlignLeftWithNode.Left * 0.5;
}
#region 容器对齐
if (alignLeftWithPanel)
if (node.AlignTopWithNode != null)
{
if (node.AlignRightWithNode != null)
node.Top = node.Top.IsNaN() ? node.AlignTopWithNode.Top : node.AlignTopWithNode.Top * 0.5;
}
if (node.AlignRightWithNode != null)
{
node.Right = node.Right.IsNaN()
? node.AlignRightWithNode.Right
: node.AlignRightWithNode.Right * 0.5;
}
if (node.AlignBottomWithNode != null)
{
node.Bottom = node.Bottom.IsNaN()
? node.AlignBottomWithNode.Bottom
: node.AlignBottomWithNode.Bottom * 0.5;
}
#endregion
#region Measure
var availableHeight = AvailableSize.Height - node.Top - node.Bottom;
if (availableHeight.IsNaN())
{
availableHeight = AvailableSize.Height;
if (!node.Top.IsNaN() && node.Bottom.IsNaN())
{
childPos.X = (node.AlignRightWithNode.Element.DesiredSize.Width + node.AlignRightWithNode.Position.X - childSize.Width) / 2;
availableHeight -= node.Top;
}
else
else if (node.Top.IsNaN() && !node.Bottom.IsNaN())
{
childPos.X = 0;
availableHeight -= node.Bottom;
}
}
if (alignTopWithPanel)
var availableWidth = AvailableSize.Width - node.Left - node.Right;
if (availableWidth.IsNaN())
{
if (node.AlignBottomWithNode != null)
availableWidth = AvailableSize.Width;
if (!node.Left.IsNaN() && node.Right.IsNaN())
{
childPos.Y = (node.AlignBottomWithNode.Element.DesiredSize.Height + node.AlignBottomWithNode.Position.Y - childSize.Height) / 2;
availableWidth -= node.Left;
}
else
else if (node.Left.IsNaN() && !node.Right.IsNaN())
{
childPos.Y = 0;
availableWidth -= node.Right;
}
}
if (alignRightWithPanel)
child.Measure(new Size(Math.Max(availableWidth, 0), Math.Max(availableHeight, 0)));
var childSize = child.DesiredSize;
#endregion
#region Sibling positional
if (node.LeftOfNode != null && node.Left.IsNaN())
{
if (alignLeftWithPanel)
node.Left = node.LeftOfNode.Left - childSize.Width;
}
if (node.AboveNode != null && node.Top.IsNaN())
{
node.Top = node.AboveNode.Top - childSize.Height;
}
if (node.RightOfNode != null)
{
if (node.Right.IsNaN())
{
childPos.X = (_arrangeSize.Width - childSize.Width) / 2;
node.Right = node.RightOfNode.Right - childSize.Width;
}
else if(node.AlignLeftWithNode == null)
if (node.Left.IsNaN())
{
childPos.X = _arrangeSize.Width - childSize.Width;
}
else
{
childPos.X = (_arrangeSize.Width + node.AlignLeftWithNode.Position.X - childSize.Width) / 2;
node.Left = AvailableSize.Width - node.RightOfNode.Right;
}
}
if (alignBottomWithPanel)
if (node.BelowNode != null)
{
if (alignTopWithPanel)
if (node.Bottom.IsNaN())
{
childPos.Y = (_arrangeSize.Height - childSize.Height) / 2;
node.Bottom = node.BelowNode.Bottom - childSize.Height;
}
else if (node.AlignTopWithNode == null)
if (node.Top.IsNaN())
{
childPos.Y = _arrangeSize.Height - childSize.Height;
}
else
{
childPos.Y = (_arrangeSize.Height + node.AlignLeftWithNode.Position.Y - childSize.Height) / 2;
node.Top = AvailableSize.Height - node.BelowNode.Bottom;
}
}
#endregion
child.Arrange(new Rect(childPos.X, childPos.Y, childSize.Width, childSize.Height));
node.Position = childPos;
node.Arranged = true;
#region Sibling-center alignment
if (node.AlignHorizontalCenterWith != null)
{
var halfWidthLeft = (AvailableSize.Width + node.AlignHorizontalCenterWith.Left - node.AlignHorizontalCenterWith.Right - childSize.Width) * 0.5;
var halfWidthRight = (AvailableSize.Width - node.AlignHorizontalCenterWith.Left + node.AlignHorizontalCenterWith.Right - childSize.Width) * 0.5;
if (node.Left.IsNaN()) node.Left = halfWidthLeft;
else node.Left = (node.Left + halfWidthLeft) * 0.5;
if (node.Right.IsNaN()) node.Right = halfWidthRight;
else node.Right = (node.Right + halfWidthRight) * 0.5;
}
if (node.AlignVerticalCenterWith != null)
{
var halfHeightTop = (AvailableSize.Height + node.AlignVerticalCenterWith.Top - node.AlignVerticalCenterWith.Bottom - childSize.Height) * 0.5;
var halfHeightBottom = (AvailableSize.Height - node.AlignVerticalCenterWith.Top + node.AlignVerticalCenterWith.Bottom - childSize.Height) * 0.5;
if (node.Top.IsNaN()) node.Top = halfHeightTop;
else node.Top = (node.Top + halfHeightTop) * 0.5;
if (node.Bottom.IsNaN()) node.Bottom = halfHeightBottom;
else node.Bottom = (node.Bottom + halfHeightBottom) * 0.5;
}
#endregion
#region Panel-center alignment
if (GetAlignHorizontalCenterWithPanel(child))
{
var halfSubWidth = (AvailableSize.Width - childSize.Width) * 0.5;
if (node.Left.IsNaN()) node.Left = halfSubWidth;
else node.Left = (node.Left + halfSubWidth) * 0.5;
if (node.Right.IsNaN()) node.Right = halfSubWidth;
else node.Right = (node.Right + halfSubWidth) * 0.5;
}
if (GetAlignVerticalCenterWithPanel(child))
{
var halfSubHeight = (AvailableSize.Height - childSize.Height) * 0.5;
if (node.Top.IsNaN()) node.Top = halfSubHeight;
else node.Top = (node.Top + halfSubHeight) * 0.5;
if (node.Bottom.IsNaN()) node.Bottom = halfSubHeight;
else node.Bottom = (node.Bottom + halfSubHeight) * 0.5;
}
#endregion
if (node.Left.IsNaN())
{
if (!node.Right.IsNaN())
node.Left = AvailableSize.Width - node.Right - childSize.Width;
else
{
node.Left = 0;
node.Right = AvailableSize.Width - childSize.Width;
}
}
else if (!node.Left.IsNaN() && node.Right.IsNaN())
{
node.Right = AvailableSize.Width - node.Left - childSize.Width;
}
if (node.Top.IsNaN())
{
if (!node.Bottom.IsNaN())
node.Top = AvailableSize.Height - node.Bottom - childSize.Height;
else
{
node.Top = 0;
node.Bottom = AvailableSize.Height - childSize.Height;
}
}
else if (!node.Top.IsNaN() && node.Bottom.IsNaN())
{
node.Bottom = AvailableSize.Height - node.Top - childSize.Height;
}
node.Measured = true;
}
public Size GetBoundingSize(bool calcWidth, bool calcHeight)
{
var boundingSize = new Size();
foreach (var node in _nodeDic.Values)
{
var size = node.GetBoundingSize();
boundingSize.Width = Math.Max(boundingSize.Width, size.Width);
boundingSize.Height = Math.Max(boundingSize.Height, size.Height);
}
boundingSize.Width = calcWidth ? boundingSize.Width : AvailableSize.Width;
boundingSize.Height = calcHeight ? boundingSize.Height : AvailableSize.Height;
return boundingSize;
}
}
}
}
}
@@ -12,7 +12,7 @@ namespace HandyControl.Controls
/// </remarks>
public class SimplePanel : Panel
{
protected override Size MeasureOverride(Size availableSize)
protected override Size MeasureOverride(Size constraint)
{
var maxSize = new Size();
@@ -20,7 +20,7 @@ namespace HandyControl.Controls
{
if (child != null)
{
child.Measure(availableSize);
child.Measure(constraint);
maxSize.Width = Math.Max(maxSize.Width, child.DesiredSize.Width);
maxSize.Height = Math.Max(maxSize.Height, child.DesiredSize.Height);
}
@@ -38,7 +38,7 @@ namespace HandyControl.Controls
public bool ShowText
{
get => (bool) GetValue(ShowTextProperty);
set => SetValue(ShowTextProperty, value);
set => SetValue(ShowTextProperty, ValueBoxes.BooleanBox(value));
}
public double ArcThickness
@@ -86,7 +86,7 @@ namespace HandyControl.Controls
public bool ShowText
{
get => (bool)GetValue(ShowTextProperty);
set => SetValue(ShowTextProperty, value);
set => SetValue(ShowTextProperty, ValueBoxes.BooleanBox(value));
}
public static readonly DependencyProperty WaveFillProperty = DependencyProperty.Register(
@@ -0,0 +1,14 @@
using System.Windows;
namespace HandyControl.Controls
{
public class DatePropertyEditor : PropertyEditorBase
{
public override FrameworkElement CreateElement(PropertyItem propertyItem) => new DateTimePicker
{
IsEnabled = !propertyItem.IsReadOnly
};
public override DependencyProperty GetDependencyProperty() => System.Windows.Controls.DatePicker.SelectedDateProperty;
}
}
@@ -0,0 +1,14 @@
using System.Windows;
namespace HandyControl.Controls
{
public class DateTimePropertyEditor : PropertyEditorBase
{
public override FrameworkElement CreateElement(PropertyItem propertyItem) => new DateTimePicker
{
IsEnabled = !propertyItem.IsReadOnly
};
public override DependencyProperty GetDependencyProperty() => DateTimePicker.SelectedDateTimeProperty;
}
}
@@ -0,0 +1,17 @@
using System;
using System.Windows;
using System.Windows.Controls.Primitives;
namespace HandyControl.Controls
{
public class EnumPropertyEditor : PropertyEditorBase
{
public override FrameworkElement CreateElement(PropertyItem propertyItem) => new System.Windows.Controls.ComboBox
{
IsEnabled = !propertyItem.IsReadOnly,
ItemsSource = Enum.GetValues(propertyItem.PropertyType)
};
public override DependencyProperty GetDependencyProperty() => Selector.SelectedValueProperty;
}
}
@@ -0,0 +1,71 @@
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Shapes;
using HandyControl.Data;
using HandyControl.Tools;
namespace HandyControl.Controls
{
public class HorizontalAlignmentPropertyEditor : PropertyEditorBase
{
public override FrameworkElement CreateElement(PropertyItem propertyItem) => new System.Windows.Controls.ComboBox
{
Style = ResourceHelper.GetResource<Style>("ComboBoxCapsule"),
ItemsSource = Enum.GetValues(propertyItem.PropertyType),
ItemTemplateSelector = ResourceHelper.GetResource<DataTemplateSelector>("HorizontalAlignmentPathTemplateSelector"),
HorizontalAlignment = HorizontalAlignment.Left
};
public override DependencyProperty GetDependencyProperty() => Selector.SelectedValueProperty;
}
public class HorizontalAlignmentPathTemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if (item is HorizontalAlignment horizontalAlignment)
{
var dataTemplate = new DataTemplate
{
DataType = typeof(System.Windows.Controls.ComboBox)
};
var factory = new FrameworkElementFactory(typeof(Path));
factory.SetValue(FrameworkElement.WidthProperty, 12.0);
factory.SetValue(FrameworkElement.HeightProperty, ValueBoxes.Double10Box);
factory.SetBinding(Shape.FillProperty, new Binding(Control.ForegroundProperty.Name)
{
RelativeSource = new RelativeSource
{
AncestorType = typeof(ComboBoxItem)
}
});
switch (horizontalAlignment)
{
case HorizontalAlignment.Left:
factory.SetValue(Path.DataProperty, ResourceHelper.GetResource<Geometry>("AlignLeftGeometry"));
break;
case HorizontalAlignment.Center:
factory.SetValue(Path.DataProperty, ResourceHelper.GetResource<Geometry>("AlignHCenterGeometry"));
break;
case HorizontalAlignment.Right:
factory.SetValue(Path.DataProperty, ResourceHelper.GetResource<Geometry>("AlignRightGeometry"));
break;
case HorizontalAlignment.Stretch:
factory.SetValue(Path.DataProperty, ResourceHelper.GetResource<Geometry>("AlignHStretchGeometry"));
break;
}
dataTemplate.VisualTree = factory;
return dataTemplate;
}
return null;
}
}
}
@@ -0,0 +1,63 @@
using System;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace HandyControl.Controls
{
public class ImagePropertyEditor : PropertyEditorBase
{
public override FrameworkElement CreateElement(PropertyItem propertyItem)
{
var imageSelector = new ImageSelector
{
IsEnabled = !propertyItem.IsReadOnly,
Width = 50,
Height = 50,
HorizontalAlignment = HorizontalAlignment.Left
};
BindingOperations.SetBinding(this, UriProperty, new Binding(ImageSelector.UriProperty.Name)
{
Source = imageSelector,
Mode = BindingMode.OneWay
});
return imageSelector;
}
internal static readonly DependencyProperty UriProperty = DependencyProperty.Register(
"Uri", typeof(Uri), typeof(ImagePropertyEditor), new PropertyMetadata(default(Uri), OnUriChangedCallback));
private static void OnUriChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) =>
((ImagePropertyEditor)d).Source = e.NewValue is Uri uri ? BitmapFrame.Create(uri) : null;
internal Uri Uri
{
get => (Uri) GetValue(UriProperty);
set => SetValue(UriProperty, value);
}
public static readonly DependencyProperty SourceProperty = DependencyProperty.Register(
"Source", typeof(ImageSource), typeof(ImagePropertyEditor), new PropertyMetadata(default(ImageSource)));
public ImageSource Source
{
get => (ImageSource) GetValue(SourceProperty);
set => SetValue(SourceProperty, value);
}
public override void CreateBinding(PropertyItem propertyItem, DependencyObject element)
=> BindingOperations.SetBinding(this, GetDependencyProperty(),
new Binding($"({propertyItem.PropertyName})")
{
Source = propertyItem.Value,
Mode = GetBindingMode(propertyItem),
UpdateSourceTrigger = GetUpdateSourceTrigger(propertyItem),
Converter = GetConverter(propertyItem)
});
public override DependencyProperty GetDependencyProperty() => SourceProperty;
}
}
@@ -0,0 +1,31 @@
using System.Windows;
namespace HandyControl.Controls
{
public class NumberPropertyEditor : PropertyEditorBase
{
public NumberPropertyEditor(double minimum, double maximum)
{
Minimum = minimum;
Maximum = maximum;
}
public double Minimum { get; set; }
public double Maximum { get; set; }
public override FrameworkElement CreateElement(PropertyItem propertyItem)
{
var numericUpDown = new NumericUpDown
{
IsReadOnly = propertyItem.IsReadOnly,
Minimum = Minimum,
Maximum = Maximum
};
numericUpDown.SetBinding(NumericUpDown.ValueProperty, CreateBinding(propertyItem));
return numericUpDown;
}
}
}
@@ -0,0 +1,31 @@
using System.Windows;
namespace HandyControl.Controls
{
public class NumberPropertyEditor : PropertyEditorBase
{
public NumberPropertyEditor()
{
}
public NumberPropertyEditor(double minimum, double maximum)
{
Minimum = minimum;
Maximum = maximum;
}
public double Minimum { get; set; }
public double Maximum { get; set; }
public override FrameworkElement CreateElement(PropertyItem propertyItem) => new NumericUpDown
{
IsReadOnly = propertyItem.IsReadOnly,
Minimum = Minimum,
Maximum = Maximum
};
public override DependencyProperty GetDependencyProperty() => NumericUpDown.ValueProperty;
}
}
@@ -0,0 +1,14 @@
using System.Windows;
namespace HandyControl.Controls
{
public class PlainTextPropertyEditor : PropertyEditorBase
{
public override FrameworkElement CreateElement(PropertyItem propertyItem) => new System.Windows.Controls.TextBox
{
IsReadOnly = propertyItem.IsReadOnly
};
public override DependencyProperty GetDependencyProperty() => System.Windows.Controls.TextBox.TextProperty;
}
}
@@ -0,0 +1,28 @@
using System.Windows;
using System.Windows.Data;
namespace HandyControl.Controls
{
public abstract class PropertyEditorBase : DependencyObject
{
public abstract FrameworkElement CreateElement(PropertyItem propertyItem);
public virtual void CreateBinding(PropertyItem propertyItem, DependencyObject element) =>
BindingOperations.SetBinding(element, GetDependencyProperty(),
new Binding($"({propertyItem.PropertyName})")
{
Source = propertyItem.Value,
Mode = GetBindingMode(propertyItem),
UpdateSourceTrigger = GetUpdateSourceTrigger(propertyItem),
Converter = GetConverter(propertyItem)
});
public abstract DependencyProperty GetDependencyProperty();
public virtual BindingMode GetBindingMode(PropertyItem propertyItem) => propertyItem.IsReadOnly ? BindingMode.OneWay : BindingMode.TwoWay;
public virtual UpdateSourceTrigger GetUpdateSourceTrigger(PropertyItem propertyItem) => UpdateSourceTrigger.PropertyChanged;
protected virtual IValueConverter GetConverter(PropertyItem propertyItem) => null;
}
}
@@ -0,0 +1,20 @@
using System.Windows;
using System.Windows.Data;
using HandyControl.Tools;
namespace HandyControl.Controls
{
public class ReadOnlyTextPropertyEditor : PropertyEditorBase
{
public override FrameworkElement CreateElement(PropertyItem propertyItem) => new System.Windows.Controls.TextBox
{
IsReadOnly = true
};
public override DependencyProperty GetDependencyProperty() => System.Windows.Controls.TextBox.TextProperty;
public override BindingMode GetBindingMode(PropertyItem propertyItem) => BindingMode.OneWay;
protected override IValueConverter GetConverter(PropertyItem propertyItem) => ResourceHelper.GetResource<IValueConverter>("Object2StringConverter");
}
}
@@ -0,0 +1,19 @@
using System.Windows;
namespace HandyControl.Controls
{
public class PlainTextPropertyEditor : PropertyEditorBase
{
public override FrameworkElement CreateElement(PropertyItem propertyItem)
{
var textbox = new System.Windows.Controls.TextBox
{
IsReadOnly = propertyItem.IsReadOnly
};
textbox.SetBinding(System.Windows.Controls.TextBox.TextProperty, CreateBinding(propertyItem));
return textbox;
}
}
}
@@ -0,0 +1,18 @@
using System.Windows;
using System.Windows.Controls.Primitives;
using HandyControl.Tools;
namespace HandyControl.Controls
{
public class SwitchPropertyEditor : PropertyEditorBase
{
public override FrameworkElement CreateElement(PropertyItem propertyItem) => new ToggleButton
{
Style = ResourceHelper.GetResource<Style>("ToggleButtonSwitch"),
HorizontalAlignment = HorizontalAlignment.Left,
IsEnabled = !propertyItem.IsReadOnly
};
public override DependencyProperty GetDependencyProperty() => ToggleButton.IsCheckedProperty;
}
}
@@ -0,0 +1,14 @@
using System.Windows;
namespace HandyControl.Controls
{
public class TimePropertyEditor : PropertyEditorBase
{
public override FrameworkElement CreateElement(PropertyItem propertyItem) => new DateTimePicker
{
IsEnabled = !propertyItem.IsReadOnly
};
public override DependencyProperty GetDependencyProperty() => TimePicker.SelectedTimeProperty;
}
}
@@ -0,0 +1,71 @@
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Shapes;
using HandyControl.Data;
using HandyControl.Tools;
namespace HandyControl.Controls
{
public class VerticalAlignmentPropertyEditor : PropertyEditorBase
{
public override FrameworkElement CreateElement(PropertyItem propertyItem) => new System.Windows.Controls.ComboBox
{
Style = ResourceHelper.GetResource<Style>("ComboBoxCapsule"),
ItemsSource = Enum.GetValues(propertyItem.PropertyType),
ItemTemplateSelector = ResourceHelper.GetResource<DataTemplateSelector>("VerticalAlignmentPathTemplateSelector"),
HorizontalAlignment = HorizontalAlignment.Left
};
public override DependencyProperty GetDependencyProperty() => Selector.SelectedValueProperty;
}
public class VerticalAlignmentPathTemplateSelector : DataTemplateSelector
{
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if (item is VerticalAlignment verticalAlignment)
{
var dataTemplate = new DataTemplate
{
DataType = typeof(System.Windows.Controls.ComboBox)
};
var factory = new FrameworkElementFactory(typeof(Path));
factory.SetValue(FrameworkElement.WidthProperty, ValueBoxes.Double10Box);
factory.SetValue(FrameworkElement.HeightProperty, 12.0);
factory.SetBinding(Shape.FillProperty, new Binding(Control.ForegroundProperty.Name)
{
RelativeSource = new RelativeSource
{
AncestorType = typeof(ComboBoxItem)
}
});
switch (verticalAlignment)
{
case VerticalAlignment.Top:
factory.SetValue(Path.DataProperty, ResourceHelper.GetResource<Geometry>("AlignTopGeometry"));
break;
case VerticalAlignment.Center:
factory.SetValue(Path.DataProperty, ResourceHelper.GetResource<Geometry>("AlignVCenterGeometry"));
break;
case VerticalAlignment.Bottom:
factory.SetValue(Path.DataProperty, ResourceHelper.GetResource<Geometry>("AlignBottomGeometry"));
break;
case VerticalAlignment.Stretch:
factory.SetValue(Path.DataProperty, ResourceHelper.GetResource<Geometry>("AlignVStretchGeometry"));
break;
}
dataTemplate.VisualTree = factory;
return dataTemplate;
}
return null;
}
}
}
@@ -0,0 +1,189 @@
using System;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using HandyControl.Data;
using HandyControl.Interactivity;
using HandyControl.Tools.Extension;
namespace HandyControl.Controls
{
[TemplatePart(Name = ElementItemsControl, Type = typeof(ItemsControl))]
[TemplatePart(Name = ElementSearchBar, Type = typeof(SearchBar))]
public class PropertyGrid : Control
{
private const string ElementItemsControl = "PART_ItemsControl";
private const string ElementSearchBar = "PART_SearchBar";
private ItemsControl _itemsControl;
private ICollectionView _dataView;
private SearchBar _searchBar;
private string _searchKey;
public PropertyGrid()
{
CommandBindings.Add(new CommandBinding(ControlCommands.SortByCategory, SortByCategory));
CommandBindings.Add(new CommandBinding(ControlCommands.SortByName, SortByName));
}
public virtual PropertyResolver PropertyResolver { get; } = new PropertyResolver();
public static readonly RoutedEvent SelectedObjectChangedEvent =
EventManager.RegisterRoutedEvent("SelectedObjectChanged", RoutingStrategy.Bubble,
typeof(RoutedPropertyChangedEventHandler<object>), typeof(PropertyGrid));
public event RoutedPropertyChangedEventHandler<object> SelectedObjectChanged
{
add => AddHandler(SelectedObjectChangedEvent, value);
remove => RemoveHandler(SelectedObjectChangedEvent, value);
}
public static readonly DependencyProperty SelectedObjectProperty = DependencyProperty.Register(
"SelectedObject", typeof(object), typeof(PropertyGrid), new PropertyMetadata(default, OnSelectedObjectChanged));
private static void OnSelectedObjectChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var ctl = (PropertyGrid)d;
ctl.OnSelectedObjectChanged(e.OldValue, e.NewValue);
}
public object SelectedObject
{
get => GetValue(SelectedObjectProperty);
set => SetValue(SelectedObjectProperty, value);
}
protected virtual void OnSelectedObjectChanged(object oldValue, object newValue)
{
UpdateItems(newValue);
RaiseEvent(new RoutedPropertyChangedEventArgs<object>(oldValue, newValue, SelectedObjectChangedEvent));
}
public static readonly DependencyProperty DescriptionProperty = DependencyProperty.Register(
"Description", typeof(string), typeof(PropertyGrid), new PropertyMetadata(default(string)));
public string Description
{
get => (string)GetValue(DescriptionProperty);
set => SetValue(DescriptionProperty, value);
}
public static readonly DependencyProperty MaxTitleWidthProperty = DependencyProperty.Register(
"MaxTitleWidth", typeof(double), typeof(PropertyGrid), new PropertyMetadata(ValueBoxes.Double0Box));
public double MaxTitleWidth
{
get => (double) GetValue(MaxTitleWidthProperty);
set => SetValue(MaxTitleWidthProperty, value);
}
public static readonly DependencyProperty MinTitleWidthProperty = DependencyProperty.Register(
"MinTitleWidth", typeof(double), typeof(PropertyGrid), new PropertyMetadata(ValueBoxes.Double0Box));
public double MinTitleWidth
{
get => (double) GetValue(MinTitleWidthProperty);
set => SetValue(MinTitleWidthProperty, value);
}
public override void OnApplyTemplate()
{
if (_searchBar != null)
{
_searchBar.SearchStarted -= SearchBar_SearchStarted;
}
base.OnApplyTemplate();
_itemsControl = GetTemplateChild(ElementItemsControl) as ItemsControl;
_searchBar = GetTemplateChild(ElementSearchBar) as SearchBar;
if (_searchBar != null)
{
_searchBar.SearchStarted += SearchBar_SearchStarted;
}
UpdateItems(SelectedObject);
}
private void UpdateItems(object obj)
{
if (obj == null || _itemsControl == null) return;
_dataView = CollectionViewSource.GetDefaultView(TypeDescriptor.GetProperties(obj).OfType<PropertyDescriptor>()
.Where(item => PropertyResolver.ResolveIsBrowsable(item)).Select(CreatePropertyItem)
.Do(item => item.InitElement()));
SortByCategory(null, null);
_itemsControl.ItemsSource = _dataView;
}
private void SortByCategory(object sender, ExecutedRoutedEventArgs e)
{
using (_dataView.DeferRefresh())
{
_dataView.GroupDescriptions.Clear();
_dataView.SortDescriptions.Clear();
_dataView.SortDescriptions.Add(new SortDescription(PropertyItem.CategoryProperty.Name, ListSortDirection.Ascending));
_dataView.SortDescriptions.Add(new SortDescription(PropertyItem.PropertyNameProperty.Name, ListSortDirection.Ascending));
_dataView.GroupDescriptions.Add(new PropertyGroupDescription(PropertyItem.CategoryProperty.Name));
}
}
private void SortByName(object sender, ExecutedRoutedEventArgs e)
{
using (_dataView.DeferRefresh())
{
_dataView.GroupDescriptions.Clear();
_dataView.SortDescriptions.Clear();
_dataView.SortDescriptions.Add(new SortDescription(PropertyItem.PropertyNameProperty.Name, ListSortDirection.Ascending));
}
}
private void SearchBar_SearchStarted(object sender, FunctionEventArgs<string> e)
{
_searchKey = e.Info;
if (string.IsNullOrEmpty(_searchKey))
{
foreach (UIElement item in _dataView)
{
item.Show();
}
}
else
{
foreach (PropertyItem item in _dataView)
{
item.Show(item.PropertyName.ToLower().Contains(_searchKey) || item.DisplayName.ToLower().Contains(_searchKey));
}
}
}
protected virtual PropertyItem CreatePropertyItem(PropertyDescriptor propertyDescriptor) => new PropertyItem
{
Category = PropertyResolver.ResolveCategory(propertyDescriptor),
DisplayName = PropertyResolver.ResolveDisplayName(propertyDescriptor),
Description = PropertyResolver.ResolveDescription(propertyDescriptor),
IsReadOnly = PropertyResolver.ResolveIsReadOnly(propertyDescriptor),
DefaultValue = PropertyResolver.ResolveDefaultValue(propertyDescriptor),
Editor = PropertyResolver.ResolveEditor(propertyDescriptor),
Value = SelectedObject,
PropertyName = propertyDescriptor.Name,
PropertyType = propertyDescriptor.PropertyType,
PropertyTypeName = $"{propertyDescriptor.PropertyType.Namespace}.{propertyDescriptor.PropertyType.Name}"
};
protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
{
base.OnRenderSizeChanged(sizeInfo);
TitleElement.SetTitleWidth(this, new GridLength(Math.Max(MinTitleWidth, Math.Min(MaxTitleWidth, ActualWidth / 3))));
}
}
}
@@ -0,0 +1,137 @@
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using HandyControl.Data;
namespace HandyControl.Controls
{
public class PropertyItem : Control
{
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
"Value", typeof(object), typeof(PropertyItem), new PropertyMetadata(default(object)));
public object Value
{
get => GetValue(ValueProperty);
set => SetValue(ValueProperty, value);
}
public static readonly DependencyProperty DisplayNameProperty = DependencyProperty.Register(
"DisplayName", typeof(string), typeof(PropertyItem), new PropertyMetadata(default(string)));
public string DisplayName
{
get => (string)GetValue(DisplayNameProperty);
set => SetValue(DisplayNameProperty, value);
}
public static readonly DependencyProperty PropertyNameProperty = DependencyProperty.Register(
"PropertyName", typeof(string), typeof(PropertyItem), new PropertyMetadata(default(string)));
public string PropertyName
{
get => (string)GetValue(PropertyNameProperty);
set => SetValue(PropertyNameProperty, value);
}
public static readonly DependencyProperty PropertyTypeProperty = DependencyProperty.Register(
"PropertyType", typeof(Type), typeof(PropertyItem), new PropertyMetadata(default(Type)));
public Type PropertyType
{
get => (Type) GetValue(PropertyTypeProperty);
set => SetValue(PropertyTypeProperty, value);
}
public static readonly DependencyProperty PropertyTypeNameProperty = DependencyProperty.Register(
"PropertyTypeName", typeof(string), typeof(PropertyItem), new PropertyMetadata(default(string)));
public string PropertyTypeName
{
get => (string)GetValue(PropertyTypeNameProperty);
set => SetValue(PropertyTypeNameProperty, value);
}
public static readonly DependencyProperty DescriptionProperty = DependencyProperty.Register(
"Description", typeof(string), typeof(PropertyItem), new PropertyMetadata(default(string)));
public string Description
{
get => (string)GetValue(DescriptionProperty);
set => SetValue(DescriptionProperty, value);
}
public static readonly DependencyProperty IsReadOnlyProperty = DependencyProperty.Register(
"IsReadOnly", typeof(bool), typeof(PropertyItem), new PropertyMetadata(ValueBoxes.FalseBox));
public bool IsReadOnly
{
get => (bool)GetValue(IsReadOnlyProperty);
set => SetValue(IsReadOnlyProperty, ValueBoxes.BooleanBox(value));
}
public static readonly DependencyProperty DefaultValueProperty = DependencyProperty.Register(
"DefaultValue", typeof(object), typeof(PropertyItem), new PropertyMetadata(default(object)));
public object DefaultValue
{
get => GetValue(DefaultValueProperty);
set => SetValue(DefaultValueProperty, value);
}
public static readonly DependencyProperty CategoryProperty = DependencyProperty.Register(
"Category", typeof(string), typeof(PropertyItem), new PropertyMetadata(default(string)));
public string Category
{
get => (string)GetValue(CategoryProperty);
set => SetValue(CategoryProperty, value);
}
public static readonly DependencyProperty EditorProperty = DependencyProperty.Register(
"Editor", typeof(PropertyEditorBase), typeof(PropertyItem), new PropertyMetadata(default(PropertyEditorBase)));
public PropertyEditorBase Editor
{
get => (PropertyEditorBase)GetValue(EditorProperty);
set => SetValue(EditorProperty, value);
}
public static readonly DependencyProperty EditorElementProperty = DependencyProperty.Register(
"EditorElement", typeof(FrameworkElement), typeof(PropertyItem), new PropertyMetadata(default(FrameworkElement)));
public FrameworkElement EditorElement
{
get => (FrameworkElement)GetValue(EditorElementProperty);
set => SetValue(EditorElementProperty, value);
}
public static readonly DependencyProperty IsSelectedProperty = DependencyProperty.Register(
"IsSelected", typeof(bool), typeof(PropertyItem), new PropertyMetadata(ValueBoxes.FalseBox));
public bool IsSelected
{
get => (bool)GetValue(IsSelectedProperty);
set => SetValue(IsSelectedProperty, ValueBoxes.BooleanBox(value));
}
public static readonly DependencyProperty IsExpandedEnabledProperty = DependencyProperty.Register(
"IsExpandedEnabled", typeof(bool), typeof(PropertyItem), new PropertyMetadata(ValueBoxes.FalseBox));
public bool IsExpandedEnabled
{
get => (bool)GetValue(IsExpandedEnabledProperty);
set => SetValue(IsExpandedEnabledProperty, ValueBoxes.BooleanBox(value));
}
public PropertyDescriptor PropertyDescriptor { get; set; }
public virtual void InitElement()
{
if (Editor == null) return;
EditorElement = Editor.CreateElement(this);
Editor.CreateBinding(this, EditorElement);
}
}
}
@@ -0,0 +1,9 @@
using System.Windows.Controls;
namespace HandyControl.Controls
{
public class PropertyItemsControl : ItemsControl
{
protected override bool IsItemItsOwnContainerOverride(object item) => item is PropertyItem;
}
}
@@ -0,0 +1,127 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Media;
using HandyControl.Properties.Langs;
namespace HandyControl.Controls
{
public class PropertyResolver
{
private static readonly Dictionary<Type, EditorTypeCode> TypeCodeDic = new Dictionary<Type, EditorTypeCode>
{
[typeof(string)] = EditorTypeCode.PlainText,
[typeof(sbyte)] = EditorTypeCode.SByteNumber,
[typeof(byte)] = EditorTypeCode.ByteNumber,
[typeof(short)] = EditorTypeCode.Int16Number,
[typeof(ushort)] = EditorTypeCode.UInt16Number,
[typeof(int)] = EditorTypeCode.Int32Number,
[typeof(uint)] = EditorTypeCode.UInt32Number,
[typeof(long)] = EditorTypeCode.Int64Number,
[typeof(ulong)] = EditorTypeCode.UInt64Number,
[typeof(float)] = EditorTypeCode.SingleNumber,
[typeof(double)] = EditorTypeCode.DoubleNumber,
[typeof(bool)] = EditorTypeCode.Switch,
[typeof(DateTime)] = EditorTypeCode.DateTime,
[typeof(HorizontalAlignment)] = EditorTypeCode.HorizontalAlignment,
[typeof(VerticalAlignment)] = EditorTypeCode.VerticalAlignment,
[typeof(ImageSource)] = EditorTypeCode.ImageSource
};
public string ResolveCategory(PropertyDescriptor propertyDescriptor)
{
var categoryAttribute = propertyDescriptor.Attributes.OfType<CategoryAttribute>().FirstOrDefault();
return categoryAttribute == null ?
Lang.Miscellaneous :
string.IsNullOrEmpty(categoryAttribute.Category) ?
Lang.Miscellaneous :
categoryAttribute.Category;
}
public string ResolveDisplayName(PropertyDescriptor propertyDescriptor)
{
var displayName = propertyDescriptor.DisplayName;
if (string.IsNullOrEmpty(displayName))
{
displayName = propertyDescriptor.Name;
}
return displayName;
}
public string ResolveDescription(PropertyDescriptor propertyDescriptor) => propertyDescriptor.Description;
public bool ResolveIsBrowsable(PropertyDescriptor propertyDescriptor) => propertyDescriptor.IsBrowsable;
public bool ResolveIsDisplay(PropertyDescriptor propertyDescriptor) => propertyDescriptor.IsLocalizable;
public bool ResolveIsReadOnly(PropertyDescriptor propertyDescriptor) => propertyDescriptor.IsReadOnly;
public object ResolveDefaultValue(PropertyDescriptor propertyDescriptor)
{
var defaultValueAttribute = propertyDescriptor.Attributes.OfType<DefaultValueAttribute>().FirstOrDefault();
return defaultValueAttribute?.Value;
}
public PropertyEditorBase ResolveEditor(PropertyDescriptor propertyDescriptor)
{
var editorAttribute = propertyDescriptor.Attributes.OfType<EditorAttribute>().FirstOrDefault();
var editor = editorAttribute == null || string.IsNullOrEmpty(editorAttribute.EditorTypeName)
? CreateDefaultEditor(propertyDescriptor.PropertyType)
: CreateEditor(Type.GetType(editorAttribute.EditorTypeName));
return editor;
}
public virtual PropertyEditorBase CreateDefaultEditor(Type type) =>
TypeCodeDic.TryGetValue(type, out var editorType)
? editorType switch
{
EditorTypeCode.PlainText => new PlainTextPropertyEditor(),
EditorTypeCode.SByteNumber => new NumberPropertyEditor(sbyte.MinValue, sbyte.MaxValue),
EditorTypeCode.ByteNumber => new NumberPropertyEditor(byte.MinValue, byte.MaxValue),
EditorTypeCode.Int16Number => new NumberPropertyEditor(short.MinValue, short.MaxValue),
EditorTypeCode.UInt16Number => new NumberPropertyEditor(ushort.MinValue, ushort.MaxValue),
EditorTypeCode.Int32Number => new NumberPropertyEditor(int.MinValue, int.MaxValue),
EditorTypeCode.UInt32Number => new NumberPropertyEditor(uint.MinValue, uint.MaxValue),
EditorTypeCode.Int64Number => new NumberPropertyEditor(long.MinValue, long.MaxValue),
EditorTypeCode.UInt64Number => new NumberPropertyEditor(ulong.MinValue, ulong.MaxValue),
EditorTypeCode.SingleNumber => new NumberPropertyEditor(float.MinValue, float.MaxValue),
EditorTypeCode.DoubleNumber => new NumberPropertyEditor(double.MinValue, double.MaxValue),
EditorTypeCode.Switch => new SwitchPropertyEditor(),
EditorTypeCode.DateTime => new DateTimePropertyEditor(),
EditorTypeCode.HorizontalAlignment => new HorizontalAlignmentPropertyEditor(),
EditorTypeCode.VerticalAlignment => new VerticalAlignmentPropertyEditor(),
EditorTypeCode.ImageSource => new ImagePropertyEditor(),
_ => new ReadOnlyTextPropertyEditor()
}
: type.IsSubclassOf(typeof(Enum))
? (PropertyEditorBase) new EnumPropertyEditor()
: new ReadOnlyTextPropertyEditor();
public virtual PropertyEditorBase CreateEditor(Type type) => new ReadOnlyTextPropertyEditor();
private enum EditorTypeCode
{
PlainText,
SByteNumber,
ByteNumber,
Int16Number,
UInt16Number,
Int32Number,
UInt32Number,
Int64Number,
UInt64Number,
SingleNumber,
DoubleNumber,
Switch,
DateTime,
HorizontalAlignment,
VerticalAlignment,
ImageSource
}
}
}
@@ -95,7 +95,6 @@ namespace HandyControl.Controls
if (DefaultValue > 0)
{
Value = DefaultValue;
UpdateItems();
}
}
else
@@ -108,13 +107,13 @@ namespace HandyControl.Controls
public bool AllowHalf
{
get => (bool) GetValue(AllowHalfProperty);
set => SetValue(AllowHalfProperty, value);
set => SetValue(AllowHalfProperty, ValueBoxes.BooleanBox(value));
}
public bool AllowClear
{
get => (bool) GetValue(AllowClearProperty);
set => SetValue(AllowClearProperty, value);
set => SetValue(AllowClearProperty, ValueBoxes.BooleanBox(value));
}
public Geometry Icon
@@ -150,13 +149,13 @@ namespace HandyControl.Controls
public bool ShowText
{
get => (bool) GetValue(ShowTextProperty);
set => SetValue(ShowTextProperty, value);
set => SetValue(ShowTextProperty, ValueBoxes.BooleanBox(value));
}
public bool IsReadOnly
{
get => (bool)GetValue(IsReadOnlyProperty);
set => SetValue(IsReadOnlyProperty, value);
set => SetValue(IsReadOnlyProperty, ValueBoxes.BooleanBox(value));
}
private void RateItemValueChanged(object sender, RoutedEventArgs e) =>
@@ -221,7 +220,6 @@ namespace HandyControl.Controls
protected override void OnMouseLeave(MouseEventArgs e)
{
base.OnMouseLeave(e);
UpdateItems();
}
@@ -58,13 +58,13 @@ namespace HandyControl.Controls
public bool AllowClear
{
get => (bool) GetValue(AllowClearProperty);
set => SetValue(AllowClearProperty, value);
set => SetValue(AllowClearProperty, ValueBoxes.BooleanBox(value));
}
public bool AllowHalf
{
get => (bool) GetValue(AllowHalfProperty);
set => SetValue(AllowHalfProperty, value);
set => SetValue(AllowHalfProperty, ValueBoxes.BooleanBox(value));
}
public Geometry Icon
@@ -76,13 +76,13 @@ namespace HandyControl.Controls
internal bool IsSelected
{
get => (bool) GetValue(IsSelectedProperty);
set => SetValue(IsSelectedProperty, value);
set => SetValue(IsSelectedProperty, ValueBoxes.BooleanBox(value));
}
public bool IsReadOnly
{
get => (bool)GetValue(IsReadOnlyProperty);
set => SetValue(IsReadOnlyProperty, value);
set => SetValue(IsReadOnlyProperty, ValueBoxes.BooleanBox(value));
}
internal bool IsHalf
@@ -125,7 +125,7 @@ namespace HandyControl.Controls
public bool IsDrawing
{
get => (bool)GetValue(IsDrawingProperty);
internal set => SetValue(IsDrawingProperty, value);
internal set => SetValue(IsDrawingProperty, ValueBoxes.BooleanBox(value));
}
public static readonly DependencyProperty IsSelectingProperty = DependencyProperty.Register(
@@ -134,7 +134,7 @@ namespace HandyControl.Controls
public bool IsSelecting
{
get => (bool)GetValue(IsSelectingProperty);
internal set => SetValue(IsSelectingProperty, value);
internal set => SetValue(IsSelectingProperty, ValueBoxes.BooleanBox(value));
}
public static readonly DependencyProperty SizeProperty = DependencyProperty.Register(
@@ -127,7 +127,7 @@ namespace HandyControl.Controls
public bool AutoSelect
{
get => (bool) GetValue(AutoSelectProperty);
set => SetValue(AutoSelectProperty, value);
set => SetValue(AutoSelectProperty, ValueBoxes.BooleanBox(value));
}
public static readonly DependencyProperty ExpandModeProperty = DependencyProperty.Register(
@@ -170,6 +170,16 @@ namespace HandyControl.Controls
}
else if (sideMenuItem.IsSelected)
{
switch (sideMenuItem.Role)
{
case SideMenuItemRole.Header:
_selectedHeader = sideMenuItem;
break;
case SideMenuItemRole.Item:
_selectedItem = sideMenuItem;
break;
}
ShowSelectedOne(sideMenuItem);
sideMenuItemSelected = sideMenuItem;
@@ -102,7 +102,7 @@ namespace HandyControl.Controls
public bool IsSelected
{
get => (bool) GetValue(IsSelectedProperty);
set => SetValue(IsSelectedProperty, value);
set => SetValue(IsSelectedProperty, ValueBoxes.BooleanBox(value));
}
public static readonly DependencyProperty RoleProperty = DependencyProperty.Register(
@@ -146,7 +146,7 @@ namespace HandyControl.Controls
public bool IsDirectionReversed
{
get => (bool)GetValue(IsDirectionReversedProperty);
set => SetValue(IsDirectionReversedProperty, value);
set => SetValue(IsDirectionReversedProperty, ValueBoxes.BooleanBox(value));
}
public static readonly DependencyProperty DelayProperty = RepeatButton.DelayProperty.AddOwner(typeof(RangeSlider), new FrameworkPropertyMetadata(GetKeyboardDelay()));
@@ -206,7 +206,7 @@ namespace HandyControl.Controls
public bool IsSnapToTickEnabled
{
get => (bool)GetValue(IsSnapToTickEnabledProperty);
set => SetValue(IsSnapToTickEnabledProperty, value);
set => SetValue(IsSnapToTickEnabledProperty, ValueBoxes.BooleanBox(value));
}
public static readonly DependencyProperty TickPlacementProperty = DependencyProperty.Register(
@@ -243,7 +243,7 @@ namespace HandyControl.Controls
public bool IsMoveToPointEnabled
{
get => (bool)GetValue(IsMoveToPointEnabledProperty);
set => SetValue(IsMoveToPointEnabledProperty, value);
set => SetValue(IsMoveToPointEnabledProperty, ValueBoxes.BooleanBox(value));
}
protected override void OnPreviewMouseLeftButtonDown(MouseButtonEventArgs e)
@@ -170,7 +170,7 @@ namespace HandyControl.Controls
public bool IsDirectionReversed
{
get => (bool) GetValue(IsDirectionReversedProperty);
set => SetValue(IsDirectionReversedProperty, value);
set => SetValue(IsDirectionReversedProperty, ValueBoxes.BooleanBox(value));
}
protected override Visual GetVisualChild(int index)
@@ -59,7 +59,7 @@ namespace HandyControl.Controls
public bool IsAnimationEnabled
{
get => (bool)GetValue(IsAnimationEnabledProperty);
set => SetValue(IsAnimationEnabledProperty, value);
set => SetValue(IsAnimationEnabledProperty, ValueBoxes.BooleanBox(value));
}
/// <summary>
@@ -74,7 +74,7 @@ namespace HandyControl.Controls
public bool IsDraggable
{
get => (bool)GetValue(IsDraggableProperty);
set => SetValue(IsDraggableProperty, value);
set => SetValue(IsDraggableProperty, ValueBoxes.BooleanBox(value));
}
/// <summary>
@@ -84,7 +84,7 @@ namespace HandyControl.Controls
"ShowCloseButton", typeof(bool), typeof(TabControl), new FrameworkPropertyMetadata(ValueBoxes.FalseBox, FrameworkPropertyMetadataOptions.Inherits));
public static void SetShowCloseButton(DependencyObject element, bool value)
=> element.SetValue(ShowCloseButtonProperty, value);
=> element.SetValue(ShowCloseButtonProperty, ValueBoxes.BooleanBox(value));
public static bool GetShowCloseButton(DependencyObject element)
=> (bool) element.GetValue(ShowCloseButtonProperty);
@@ -105,7 +105,7 @@ namespace HandyControl.Controls
"ShowContextMenu", typeof(bool), typeof(TabControl), new FrameworkPropertyMetadata(ValueBoxes.TrueBox, FrameworkPropertyMetadataOptions.Inherits));
public static void SetShowContextMenu(DependencyObject element, bool value)
=> element.SetValue(ShowContextMenuProperty, value);
=> element.SetValue(ShowContextMenuProperty, ValueBoxes.BooleanBox(value));
public static bool GetShowContextMenu(DependencyObject element)
=> (bool) element.GetValue(ShowContextMenuProperty);
@@ -131,7 +131,7 @@ namespace HandyControl.Controls
public bool IsTabFillEnabled
{
get => (bool)GetValue(IsTabFillEnabledProperty);
set => SetValue(IsTabFillEnabledProperty, value);
set => SetValue(IsTabFillEnabledProperty, ValueBoxes.BooleanBox(value));
}
/// <summary>
@@ -176,7 +176,7 @@ namespace HandyControl.Controls
public bool IsScrollable
{
get => (bool) GetValue(IsScrollableProperty);
set => SetValue(IsScrollableProperty, value);
set => SetValue(IsScrollableProperty, ValueBoxes.BooleanBox(value));
}
/// <summary>
@@ -191,7 +191,7 @@ namespace HandyControl.Controls
public bool ShowOverflowButton
{
get => (bool) GetValue(ShowOverflowButtonProperty);
set => SetValue(ShowOverflowButtonProperty, value);
set => SetValue(ShowOverflowButtonProperty, ValueBoxes.BooleanBox(value));
}
/// <summary>
@@ -206,7 +206,7 @@ namespace HandyControl.Controls
public bool ShowScrollButton
{
get => (bool) GetValue(ShowScrollButtonProperty);
set => SetValue(ShowScrollButtonProperty, value);
set => SetValue(ShowScrollButtonProperty, ValueBoxes.BooleanBox(value));
}
/// <summary>
@@ -145,7 +145,7 @@ namespace HandyControl.Controls
}
public static void SetShowCloseButton(DependencyObject element, bool value)
=> element.SetValue(ShowCloseButtonProperty, value);
=> element.SetValue(ShowCloseButtonProperty, ValueBoxes.BooleanBox(value));
public static bool GetShowCloseButton(DependencyObject element)
=> (bool)element.GetValue(ShowCloseButtonProperty);
@@ -173,11 +173,11 @@ namespace HandyControl.Controls
public bool ShowContextMenu
{
get => (bool) GetValue(ShowContextMenuProperty);
set => SetValue(ShowContextMenuProperty, value);
set => SetValue(ShowContextMenuProperty, ValueBoxes.BooleanBox(value));
}
public static void SetShowContextMenu(DependencyObject element, bool value)
=> element.SetValue(ShowContextMenuProperty, value);
=> element.SetValue(ShowContextMenuProperty, ValueBoxes.BooleanBox(value));
public static bool GetShowContextMenu(DependencyObject element)
=> (bool)element.GetValue(ShowContextMenuProperty);
@@ -53,7 +53,7 @@ namespace HandyControl.Controls
public bool IsTabFillEnabled
{
get => (bool)GetValue(IsTabFillEnabledProperty);
set => SetValue(IsTabFillEnabledProperty, value);
set => SetValue(IsTabFillEnabledProperty, ValueBoxes.BooleanBox(value));
}
/// <summary>
@@ -27,7 +27,7 @@ namespace HandyControl.Controls
public bool ShowCloseButton
{
get => (bool) GetValue(ShowCloseButtonProperty);
set => SetValue(ShowCloseButtonProperty, value);
set => SetValue(ShowCloseButtonProperty, ValueBoxes.BooleanBox(value));
}
public static readonly DependencyProperty SelectableProperty = DependencyProperty.Register(
@@ -36,7 +36,7 @@ namespace HandyControl.Controls
public bool Selectable
{
get => (bool) GetValue(SelectableProperty);
set => SetValue(SelectableProperty, value);
set => SetValue(SelectableProperty, ValueBoxes.BooleanBox(value));
}
public static readonly DependencyProperty IsSelectedProperty = DependencyProperty.Register(
@@ -49,7 +49,7 @@ namespace HandyControl.Controls
public bool IsSelected
{
get => (bool) GetValue(IsSelectedProperty);
set => SetValue(IsSelectedProperty, value);
set => SetValue(IsSelectedProperty, ValueBoxes.BooleanBox(value));
}
public static readonly RoutedEvent SelectedEvent = EventManager.RegisterRoutedEvent("Selected", RoutingStrategy.Bubble, typeof(EventHandler), typeof(Tag));
@@ -45,7 +45,7 @@ namespace HandyControl.Controls
public bool ShowAddButton
{
get => (bool) GetValue(ShowAddButtonProperty);
set => SetValue(ShowAddButtonProperty, value);
set => SetValue(ShowAddButtonProperty, ValueBoxes.BooleanBox(value));
}
public static readonly DependencyProperty TagMarginProperty = DependencyProperty.Register(
@@ -201,7 +201,7 @@ namespace HandyControl.Controls
return;
}
#if netle45
#if NET40 || NET45
_formattedText = new FormattedText(
Text,
CultureInfo.CurrentUICulture,
@@ -129,7 +129,7 @@ namespace HandyControl.Controls
return;
}
#if netle45
#if NET40 || NET45
_formattedText = new FormattedText(
Text,
CultureInfo.CurrentUICulture,
@@ -170,6 +170,7 @@ namespace HandyControl.Controls
_formattedText.SetFontWeight(FontWeight);
_formattedText.SetFontFamily(FontFamily);
_formattedText.SetFontStretch(FontStretch);
_formattedText.SetForegroundBrush(Foreground);
}
private static void OnFormattedTextUpdated(DependencyObject d, DependencyPropertyChangedEventArgs e)
@@ -87,7 +87,7 @@ namespace HandyControl.Controls
public bool ShowConfirmButton
{
get => (bool)GetValue(ShowConfirmButtonProperty);
set => SetValue(ShowConfirmButtonProperty, value);
set => SetValue(ShowConfirmButtonProperty, ValueBoxes.BooleanBox(value));
}
public static readonly DependencyProperty SelectedDateTimeProperty = DependencyProperty.Register(
@@ -82,7 +82,7 @@ namespace HandyControl.Controls
internal bool ShowConfirmButton
{
get => (bool) GetValue(ShowConfirmButtonProperty);
set => SetValue(ShowConfirmButtonProperty, value);
set => SetValue(ShowConfirmButtonProperty, ValueBoxes.BooleanBox(value));
}
protected virtual void OnSelectedTimeChanged(FunctionEventArgs<DateTime?> e) => RaiseEvent(e);
@@ -216,7 +216,7 @@ namespace HandyControl.Controls
public bool ShowSpeStr
{
get => (bool)GetValue(ShowSpeStrProperty);
set => SetValue(ShowSpeStrProperty, value);
set => SetValue(ShowSpeStrProperty, ValueBoxes.BooleanBox(value));
}
/// <summary>
@@ -11,7 +11,7 @@ namespace HandyControl.Controls
public bool IsTransferred
{
get => (bool) GetValue(IsTransferredProperty);
set => SetValue(IsTransferredProperty, value);
set => SetValue(IsTransferredProperty, ValueBoxes.BooleanBox(value));
}
public static readonly DependencyProperty IsOriginProperty = DependencyProperty.Register(
@@ -20,7 +20,7 @@ namespace HandyControl.Controls
public bool IsOrigin
{
get => (bool) GetValue(IsOriginProperty);
internal set => SetValue(IsOriginProperty, value);
internal set => SetValue(IsOriginProperty, ValueBoxes.BooleanBox(value));
}
}
}
@@ -1,5 +1,4 @@
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Media;
using HandyControl.Data;
using HandyControl.Tools;
@@ -9,23 +8,18 @@ namespace HandyControl.Controls
{
public class BlurWindow : Window
{
static BlurWindow()
{
StyleProperty.OverrideMetadata(typeof(BlurWindow), new FrameworkPropertyMetadata(Application.Current.FindResource(ResourceToken.WindowBlur)));
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
EnableBlur(this);
}
public static SystemVersionInfo SystemVersionInfo { get; set; }
internal static void EnableBlur(Window window)
{
if (SystemVersionInfo < SystemVersionInfo.Windows10 ||
SystemVersionInfo >= SystemVersionInfo.Windows10_1903)
var versionInfo = ConfigHelper.Instance.SystemVersionInfo;
if (versionInfo < SystemVersionInfo.Windows10 ||
versionInfo >= SystemVersionInfo.Windows10_1903)
{
var colorValue = ResourceHelper.GetResource<uint>(ResourceToken.BlurGradientValue);
var color = ColorHelper.ToColor(colorValue);
@@ -37,7 +31,7 @@ namespace HandyControl.Controls
var accentPolicy = new InteropValues.ACCENTPOLICY();
var accentPolicySize = Marshal.SizeOf(accentPolicy);
accentPolicy.AccentState = SystemVersionInfo < SystemVersionInfo.Windows10_1809
accentPolicy.AccentState = versionInfo < SystemVersionInfo.Windows10_1809
? InteropValues.ACCENTSTATE.ACCENT_ENABLE_BLURBEHIND
: InteropValues.ACCENTSTATE.ACCENT_ENABLE_ACRYLICBLURBEHIND;
Loaded 100 of 608 files, more files were not shown because too many files have changed in this diff. Show more