Merge branch 'master' into master
This commit is contained in:
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
-11
@@ -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(
|
||||
|
||||
+161
-22
@@ -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);
|
||||
|
||||
|
||||
+21
-20
@@ -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;
|
||||
}
|
||||
}
|
||||
+14
@@ -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;
|
||||
}
|
||||
}
|
||||
+71
@@ -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;
|
||||
}
|
||||
}
|
||||
+14
@@ -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;
|
||||
}
|
||||
}
|
||||
+20
@@ -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;
|
||||
}
|
||||
}
|
||||
+71
@@ -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
Reference in new issue
Block a user