chore: use file-scoped namespace
This commit is contained in:
1 parent
99d2fafb72
commit
bbf1b7d4c6
748 files changed
+57929
-58678
No files matched your search
@@ -8,164 +8,163 @@ using HandyControl.Data;
|
||||
using HandyControl.Expression.Drawing;
|
||||
using HandyControl.Tools.Extension;
|
||||
|
||||
namespace HandyControl.Controls
|
||||
namespace HandyControl.Controls;
|
||||
|
||||
public class AnimationPath : Shape
|
||||
{
|
||||
public class AnimationPath : Shape
|
||||
private Storyboard _storyboard;
|
||||
|
||||
private double _pathLength;
|
||||
|
||||
public static readonly DependencyProperty DataProperty = DependencyProperty.Register(nameof(Data),
|
||||
typeof(Geometry), typeof(AnimationPath), new FrameworkPropertyMetadata(null,
|
||||
OnPropertiesChanged));
|
||||
|
||||
private static void OnPropertiesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
private Storyboard _storyboard;
|
||||
|
||||
private double _pathLength;
|
||||
|
||||
public static readonly DependencyProperty DataProperty = DependencyProperty.Register(nameof(Data),
|
||||
typeof(Geometry), typeof(AnimationPath), new FrameworkPropertyMetadata(null,
|
||||
OnPropertiesChanged));
|
||||
|
||||
private static void OnPropertiesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
if (d is AnimationPath path)
|
||||
{
|
||||
if (d is AnimationPath path)
|
||||
{
|
||||
path.UpdatePath();
|
||||
}
|
||||
path.UpdatePath();
|
||||
}
|
||||
|
||||
public Geometry Data
|
||||
{
|
||||
get => (Geometry) GetValue(DataProperty);
|
||||
set => SetValue(DataProperty, value);
|
||||
}
|
||||
|
||||
protected override Geometry DefiningGeometry => Data ?? Geometry.Empty;
|
||||
|
||||
public static readonly DependencyProperty PathLengthProperty = DependencyProperty.Register(
|
||||
"PathLength", typeof(double), typeof(AnimationPath), new FrameworkPropertyMetadata(ValueBoxes.Double0Box, OnPropertiesChanged));
|
||||
|
||||
public double PathLength
|
||||
{
|
||||
get => (double) GetValue(PathLengthProperty);
|
||||
set => SetValue(PathLengthProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty DurationProperty = DependencyProperty.Register(
|
||||
"Duration", typeof(Duration), typeof(AnimationPath), new FrameworkPropertyMetadata(new Duration(TimeSpan.FromSeconds(2)),
|
||||
OnPropertiesChanged));
|
||||
|
||||
public Duration Duration
|
||||
{
|
||||
get => (Duration) GetValue(DurationProperty);
|
||||
set => SetValue(DurationProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty IsPlayingProperty = DependencyProperty.Register(
|
||||
"IsPlaying", typeof(bool), typeof(AnimationPath), new FrameworkPropertyMetadata(ValueBoxes.TrueBox, (o, args) =>
|
||||
{
|
||||
var ctl = (AnimationPath) o;
|
||||
var v = (bool) args.NewValue;
|
||||
if (v)
|
||||
{
|
||||
ctl.UpdatePath();
|
||||
}
|
||||
else
|
||||
{
|
||||
ctl._storyboard?.Pause();
|
||||
}
|
||||
}));
|
||||
|
||||
public bool IsPlaying
|
||||
{
|
||||
get => (bool) GetValue(IsPlayingProperty);
|
||||
set => SetValue(IsPlayingProperty, ValueBoxes.BooleanBox(value));
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty RepeatBehaviorProperty =
|
||||
Timeline.RepeatBehaviorProperty.AddOwner(typeof(AnimationPath),
|
||||
new PropertyMetadata(RepeatBehavior.Forever));
|
||||
|
||||
public RepeatBehavior RepeatBehavior
|
||||
{
|
||||
get => (RepeatBehavior) GetValue(RepeatBehaviorProperty);
|
||||
set => SetValue(RepeatBehaviorProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty FillBehaviorProperty =
|
||||
Timeline.FillBehaviorProperty.AddOwner(typeof(AnimationPath), new PropertyMetadata(FillBehavior.Stop));
|
||||
|
||||
public FillBehavior FillBehavior
|
||||
{
|
||||
get { return (FillBehavior) GetValue(FillBehaviorProperty); }
|
||||
set { SetValue(FillBehaviorProperty, value); }
|
||||
}
|
||||
|
||||
static AnimationPath()
|
||||
{
|
||||
StretchProperty.AddOwner(typeof(AnimationPath), new FrameworkPropertyMetadata(Stretch.Uniform,
|
||||
OnPropertiesChanged));
|
||||
|
||||
StrokeThicknessProperty.AddOwner(typeof(AnimationPath), new FrameworkPropertyMetadata(ValueBoxes.Double1Box,
|
||||
OnPropertiesChanged));
|
||||
}
|
||||
|
||||
public AnimationPath() => Loaded += (s, e) => UpdatePath();
|
||||
|
||||
public static readonly RoutedEvent CompletedEvent =
|
||||
EventManager.RegisterRoutedEvent("Completed", RoutingStrategy.Bubble,
|
||||
typeof(EventHandler), typeof(AnimationPath));
|
||||
|
||||
public event EventHandler Completed
|
||||
{
|
||||
add => AddHandler(CompletedEvent, value);
|
||||
remove => RemoveHandler(CompletedEvent, value);
|
||||
}
|
||||
|
||||
private void UpdatePath()
|
||||
{
|
||||
if (!Duration.HasTimeSpan || !IsPlaying) return;
|
||||
|
||||
_pathLength = PathLength > 0 ? PathLength : Data.GetTotalLength(new Size(ActualWidth, ActualHeight), StrokeThickness);
|
||||
|
||||
if (MathHelper.IsVerySmall(_pathLength)) return;
|
||||
|
||||
StrokeDashOffset = _pathLength;
|
||||
StrokeDashArray = new DoubleCollection(new List<double>
|
||||
{
|
||||
_pathLength,
|
||||
_pathLength
|
||||
});
|
||||
|
||||
if (_storyboard != null)
|
||||
{
|
||||
_storyboard.Stop();
|
||||
_storyboard.Completed -= Storyboard_Completed;
|
||||
}
|
||||
_storyboard = new Storyboard
|
||||
{
|
||||
RepeatBehavior = RepeatBehavior,
|
||||
FillBehavior = FillBehavior
|
||||
};
|
||||
_storyboard.Completed += Storyboard_Completed;
|
||||
|
||||
var frames = new DoubleAnimationUsingKeyFrames();
|
||||
|
||||
var frameIn = new LinearDoubleKeyFrame
|
||||
{
|
||||
Value = _pathLength,
|
||||
KeyTime = KeyTime.FromTimeSpan(TimeSpan.Zero)
|
||||
};
|
||||
frames.KeyFrames.Add(frameIn);
|
||||
|
||||
var frameOut = new LinearDoubleKeyFrame
|
||||
{
|
||||
Value = FillBehavior == FillBehavior.Stop ? -_pathLength : 0,
|
||||
KeyTime = KeyTime.FromTimeSpan(Duration.TimeSpan)
|
||||
};
|
||||
frames.KeyFrames.Add(frameOut);
|
||||
|
||||
Storyboard.SetTarget(frames, this);
|
||||
Storyboard.SetTargetProperty(frames, new PropertyPath(StrokeDashOffsetProperty));
|
||||
_storyboard.Children.Add(frames);
|
||||
|
||||
_storyboard.Begin();
|
||||
}
|
||||
|
||||
private void Storyboard_Completed(object sender, EventArgs e) => RaiseEvent(new RoutedEventArgs(CompletedEvent));
|
||||
}
|
||||
}
|
||||
|
||||
public Geometry Data
|
||||
{
|
||||
get => (Geometry) GetValue(DataProperty);
|
||||
set => SetValue(DataProperty, value);
|
||||
}
|
||||
|
||||
protected override Geometry DefiningGeometry => Data ?? Geometry.Empty;
|
||||
|
||||
public static readonly DependencyProperty PathLengthProperty = DependencyProperty.Register(
|
||||
"PathLength", typeof(double), typeof(AnimationPath), new FrameworkPropertyMetadata(ValueBoxes.Double0Box, OnPropertiesChanged));
|
||||
|
||||
public double PathLength
|
||||
{
|
||||
get => (double) GetValue(PathLengthProperty);
|
||||
set => SetValue(PathLengthProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty DurationProperty = DependencyProperty.Register(
|
||||
"Duration", typeof(Duration), typeof(AnimationPath), new FrameworkPropertyMetadata(new Duration(TimeSpan.FromSeconds(2)),
|
||||
OnPropertiesChanged));
|
||||
|
||||
public Duration Duration
|
||||
{
|
||||
get => (Duration) GetValue(DurationProperty);
|
||||
set => SetValue(DurationProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty IsPlayingProperty = DependencyProperty.Register(
|
||||
"IsPlaying", typeof(bool), typeof(AnimationPath), new FrameworkPropertyMetadata(ValueBoxes.TrueBox, (o, args) =>
|
||||
{
|
||||
var ctl = (AnimationPath) o;
|
||||
var v = (bool) args.NewValue;
|
||||
if (v)
|
||||
{
|
||||
ctl.UpdatePath();
|
||||
}
|
||||
else
|
||||
{
|
||||
ctl._storyboard?.Pause();
|
||||
}
|
||||
}));
|
||||
|
||||
public bool IsPlaying
|
||||
{
|
||||
get => (bool) GetValue(IsPlayingProperty);
|
||||
set => SetValue(IsPlayingProperty, ValueBoxes.BooleanBox(value));
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty RepeatBehaviorProperty =
|
||||
Timeline.RepeatBehaviorProperty.AddOwner(typeof(AnimationPath),
|
||||
new PropertyMetadata(RepeatBehavior.Forever));
|
||||
|
||||
public RepeatBehavior RepeatBehavior
|
||||
{
|
||||
get => (RepeatBehavior) GetValue(RepeatBehaviorProperty);
|
||||
set => SetValue(RepeatBehaviorProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty FillBehaviorProperty =
|
||||
Timeline.FillBehaviorProperty.AddOwner(typeof(AnimationPath), new PropertyMetadata(FillBehavior.Stop));
|
||||
|
||||
public FillBehavior FillBehavior
|
||||
{
|
||||
get { return (FillBehavior) GetValue(FillBehaviorProperty); }
|
||||
set { SetValue(FillBehaviorProperty, value); }
|
||||
}
|
||||
|
||||
static AnimationPath()
|
||||
{
|
||||
StretchProperty.AddOwner(typeof(AnimationPath), new FrameworkPropertyMetadata(Stretch.Uniform,
|
||||
OnPropertiesChanged));
|
||||
|
||||
StrokeThicknessProperty.AddOwner(typeof(AnimationPath), new FrameworkPropertyMetadata(ValueBoxes.Double1Box,
|
||||
OnPropertiesChanged));
|
||||
}
|
||||
|
||||
public AnimationPath() => Loaded += (s, e) => UpdatePath();
|
||||
|
||||
public static readonly RoutedEvent CompletedEvent =
|
||||
EventManager.RegisterRoutedEvent("Completed", RoutingStrategy.Bubble,
|
||||
typeof(EventHandler), typeof(AnimationPath));
|
||||
|
||||
public event EventHandler Completed
|
||||
{
|
||||
add => AddHandler(CompletedEvent, value);
|
||||
remove => RemoveHandler(CompletedEvent, value);
|
||||
}
|
||||
|
||||
private void UpdatePath()
|
||||
{
|
||||
if (!Duration.HasTimeSpan || !IsPlaying) return;
|
||||
|
||||
_pathLength = PathLength > 0 ? PathLength : Data.GetTotalLength(new Size(ActualWidth, ActualHeight), StrokeThickness);
|
||||
|
||||
if (MathHelper.IsVerySmall(_pathLength)) return;
|
||||
|
||||
StrokeDashOffset = _pathLength;
|
||||
StrokeDashArray = new DoubleCollection(new List<double>
|
||||
{
|
||||
_pathLength,
|
||||
_pathLength
|
||||
});
|
||||
|
||||
if (_storyboard != null)
|
||||
{
|
||||
_storyboard.Stop();
|
||||
_storyboard.Completed -= Storyboard_Completed;
|
||||
}
|
||||
_storyboard = new Storyboard
|
||||
{
|
||||
RepeatBehavior = RepeatBehavior,
|
||||
FillBehavior = FillBehavior
|
||||
};
|
||||
_storyboard.Completed += Storyboard_Completed;
|
||||
|
||||
var frames = new DoubleAnimationUsingKeyFrames();
|
||||
|
||||
var frameIn = new LinearDoubleKeyFrame
|
||||
{
|
||||
Value = _pathLength,
|
||||
KeyTime = KeyTime.FromTimeSpan(TimeSpan.Zero)
|
||||
};
|
||||
frames.KeyFrames.Add(frameIn);
|
||||
|
||||
var frameOut = new LinearDoubleKeyFrame
|
||||
{
|
||||
Value = FillBehavior == FillBehavior.Stop ? -_pathLength : 0,
|
||||
KeyTime = KeyTime.FromTimeSpan(Duration.TimeSpan)
|
||||
};
|
||||
frames.KeyFrames.Add(frameOut);
|
||||
|
||||
Storyboard.SetTarget(frames, this);
|
||||
Storyboard.SetTargetProperty(frames, new PropertyPath(StrokeDashOffsetProperty));
|
||||
_storyboard.Children.Add(frames);
|
||||
|
||||
_storyboard.Begin();
|
||||
}
|
||||
|
||||
private void Storyboard_Completed(object sender, EventArgs e) => RaiseEvent(new RoutedEventArgs(CompletedEvent));
|
||||
}
|
||||
@@ -4,98 +4,97 @@ using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using HandyControl.Data;
|
||||
|
||||
namespace HandyControl.Controls
|
||||
namespace HandyControl.Controls;
|
||||
|
||||
/// <summary>
|
||||
/// 标记
|
||||
/// </summary>
|
||||
public class Badge : ContentControl
|
||||
{
|
||||
/// <summary>
|
||||
/// 标记
|
||||
/// </summary>
|
||||
public class Badge : ContentControl
|
||||
public static readonly RoutedEvent ValueChangedEvent =
|
||||
EventManager.RegisterRoutedEvent("ValueChanged", RoutingStrategy.Bubble,
|
||||
typeof(EventHandler<FunctionEventArgs<int>>), typeof(Badge));
|
||||
|
||||
public event EventHandler<FunctionEventArgs<int>> ValueChanged
|
||||
{
|
||||
public static readonly RoutedEvent ValueChangedEvent =
|
||||
EventManager.RegisterRoutedEvent("ValueChanged", RoutingStrategy.Bubble,
|
||||
typeof(EventHandler<FunctionEventArgs<int>>), typeof(Badge));
|
||||
|
||||
public event EventHandler<FunctionEventArgs<int>> ValueChanged
|
||||
{
|
||||
add => AddHandler(ValueChangedEvent, value);
|
||||
remove => RemoveHandler(ValueChangedEvent, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
|
||||
"Text", typeof(string), typeof(Badge), new PropertyMetadata("0"));
|
||||
|
||||
public string Text
|
||||
{
|
||||
get => (string) GetValue(TextProperty);
|
||||
set => SetValue(TextProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
|
||||
"Value", typeof(int), typeof(Badge), new PropertyMetadata(ValueBoxes.Int0Box, OnValueChanged));
|
||||
|
||||
private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
var ctl = (Badge) d;
|
||||
var v = (int) e.NewValue;
|
||||
ctl.SetCurrentValue(TextProperty, v <= ctl.Maximum ? v.ToString() : $"{ctl.Maximum}+");
|
||||
if (ctl.IsInitialized)
|
||||
{
|
||||
ctl.RaiseEvent(new FunctionEventArgs<int>(ValueChangedEvent, ctl)
|
||||
{
|
||||
Info = v
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public int Value
|
||||
{
|
||||
get => (int) GetValue(ValueProperty);
|
||||
set => SetValue(ValueProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty StatusProperty = DependencyProperty.Register(
|
||||
"Status", typeof(BadgeStatus), typeof(Badge), new PropertyMetadata(default(BadgeStatus)));
|
||||
|
||||
public BadgeStatus Status
|
||||
{
|
||||
get => (BadgeStatus) GetValue(StatusProperty);
|
||||
set => SetValue(StatusProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty MaximumProperty = DependencyProperty.Register(
|
||||
"Maximum", typeof(int), typeof(Badge), new PropertyMetadata(ValueBoxes.Int99Box, OnMaximumChanged));
|
||||
|
||||
private static void OnMaximumChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
var ctl = (Badge) d;
|
||||
var v = ctl.Value;
|
||||
ctl.SetCurrentValue(TextProperty, v <= ctl.Maximum ? v.ToString() : $"{ctl.Maximum}+");
|
||||
}
|
||||
|
||||
public int Maximum
|
||||
{
|
||||
get => (int) GetValue(MaximumProperty);
|
||||
set => SetValue(MaximumProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty BadgeMarginProperty = DependencyProperty.Register(
|
||||
"BadgeMargin", typeof(Thickness), typeof(Badge), new PropertyMetadata(default(Thickness)));
|
||||
|
||||
public Thickness BadgeMargin
|
||||
{
|
||||
get => (Thickness) GetValue(BadgeMarginProperty);
|
||||
set => SetValue(BadgeMarginProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ShowBadgeProperty = DependencyProperty.Register(
|
||||
"ShowBadge", typeof(bool), typeof(Badge), new PropertyMetadata(ValueBoxes.TrueBox));
|
||||
|
||||
public bool ShowBadge
|
||||
{
|
||||
get => (bool) GetValue(ShowBadgeProperty);
|
||||
set => SetValue(ShowBadgeProperty, ValueBoxes.BooleanBox(value));
|
||||
}
|
||||
|
||||
protected override Geometry GetLayoutClip(Size layoutSlotSize) => null;
|
||||
add => AddHandler(ValueChangedEvent, value);
|
||||
remove => RemoveHandler(ValueChangedEvent, value);
|
||||
}
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
|
||||
"Text", typeof(string), typeof(Badge), new PropertyMetadata("0"));
|
||||
|
||||
public string Text
|
||||
{
|
||||
get => (string) GetValue(TextProperty);
|
||||
set => SetValue(TextProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
|
||||
"Value", typeof(int), typeof(Badge), new PropertyMetadata(ValueBoxes.Int0Box, OnValueChanged));
|
||||
|
||||
private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
var ctl = (Badge) d;
|
||||
var v = (int) e.NewValue;
|
||||
ctl.SetCurrentValue(TextProperty, v <= ctl.Maximum ? v.ToString() : $"{ctl.Maximum}+");
|
||||
if (ctl.IsInitialized)
|
||||
{
|
||||
ctl.RaiseEvent(new FunctionEventArgs<int>(ValueChangedEvent, ctl)
|
||||
{
|
||||
Info = v
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public int Value
|
||||
{
|
||||
get => (int) GetValue(ValueProperty);
|
||||
set => SetValue(ValueProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty StatusProperty = DependencyProperty.Register(
|
||||
"Status", typeof(BadgeStatus), typeof(Badge), new PropertyMetadata(default(BadgeStatus)));
|
||||
|
||||
public BadgeStatus Status
|
||||
{
|
||||
get => (BadgeStatus) GetValue(StatusProperty);
|
||||
set => SetValue(StatusProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty MaximumProperty = DependencyProperty.Register(
|
||||
"Maximum", typeof(int), typeof(Badge), new PropertyMetadata(ValueBoxes.Int99Box, OnMaximumChanged));
|
||||
|
||||
private static void OnMaximumChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
var ctl = (Badge) d;
|
||||
var v = ctl.Value;
|
||||
ctl.SetCurrentValue(TextProperty, v <= ctl.Maximum ? v.ToString() : $"{ctl.Maximum}+");
|
||||
}
|
||||
|
||||
public int Maximum
|
||||
{
|
||||
get => (int) GetValue(MaximumProperty);
|
||||
set => SetValue(MaximumProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty BadgeMarginProperty = DependencyProperty.Register(
|
||||
"BadgeMargin", typeof(Thickness), typeof(Badge), new PropertyMetadata(default(Thickness)));
|
||||
|
||||
public Thickness BadgeMargin
|
||||
{
|
||||
get => (Thickness) GetValue(BadgeMarginProperty);
|
||||
set => SetValue(BadgeMarginProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ShowBadgeProperty = DependencyProperty.Register(
|
||||
"ShowBadge", typeof(bool), typeof(Badge), new PropertyMetadata(ValueBoxes.TrueBox));
|
||||
|
||||
public bool ShowBadge
|
||||
{
|
||||
get => (bool) GetValue(ShowBadgeProperty);
|
||||
set => SetValue(ShowBadgeProperty, ValueBoxes.BooleanBox(value));
|
||||
}
|
||||
|
||||
protected override Geometry GetLayoutClip(Size layoutSlotSize) => null;
|
||||
}
|
||||
@@ -7,110 +7,109 @@ using System.Windows.Data;
|
||||
using System.Windows.Markup;
|
||||
using System.Windows.Media.Effects;
|
||||
|
||||
namespace HandyControl.Controls
|
||||
namespace HandyControl.Controls;
|
||||
|
||||
[DefaultProperty("Content")]
|
||||
[ContentProperty("Content")]
|
||||
public class BlendEffectBox : Control
|
||||
{
|
||||
[DefaultProperty("Content")]
|
||||
[ContentProperty("Content")]
|
||||
public class BlendEffectBox : Control
|
||||
private readonly ContentPresenter _effectBottomPresenter;
|
||||
|
||||
private readonly ContentPresenter _effectTopPresenter;
|
||||
|
||||
private bool _isInternalAction;
|
||||
|
||||
public BlendEffectBox()
|
||||
{
|
||||
private readonly ContentPresenter _effectBottomPresenter;
|
||||
_effectTopPresenter = new ContentPresenter();
|
||||
ActualContent = _effectTopPresenter;
|
||||
|
||||
private readonly ContentPresenter _effectTopPresenter;
|
||||
|
||||
private bool _isInternalAction;
|
||||
|
||||
public BlendEffectBox()
|
||||
_effectBottomPresenter = new ContentPresenter();
|
||||
_effectBottomPresenter.SetBinding(ContentPresenter.ContentProperty, new Binding(ContentProperty.Name)
|
||||
{
|
||||
_effectTopPresenter = new ContentPresenter();
|
||||
ActualContent = _effectTopPresenter;
|
||||
Source = this
|
||||
});
|
||||
|
||||
_effectBottomPresenter = new ContentPresenter();
|
||||
_effectBottomPresenter.SetBinding(ContentPresenter.ContentProperty, new Binding(ContentProperty.Name)
|
||||
{
|
||||
Source = this
|
||||
});
|
||||
var effects = new ObservableCollection<Effect>();
|
||||
effects.CollectionChanged += OnEffectsChanged;
|
||||
Effects = effects;
|
||||
}
|
||||
|
||||
var effects = new ObservableCollection<Effect>();
|
||||
effects.CollectionChanged += OnEffectsChanged;
|
||||
Effects = effects;
|
||||
private void OnEffectsChanged(object sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
if (Effects == null || Effects.Count == 0)
|
||||
{
|
||||
ClearEffect(_effectTopPresenter);
|
||||
return;
|
||||
}
|
||||
|
||||
private void OnEffectsChanged(object sender, NotifyCollectionChangedEventArgs e)
|
||||
if (_isInternalAction) return;
|
||||
|
||||
_isInternalAction = true;
|
||||
AddEffect(_effectTopPresenter, Effects.Count);
|
||||
_isInternalAction = false;
|
||||
}
|
||||
|
||||
private void ClearEffect(ContentPresenter presenter)
|
||||
{
|
||||
if (presenter == null) return;
|
||||
|
||||
if (ReferenceEquals(_effectBottomPresenter, presenter))
|
||||
{
|
||||
if (Effects == null || Effects.Count == 0)
|
||||
_effectBottomPresenter.SetCurrentValue(EffectProperty, null);
|
||||
return;
|
||||
}
|
||||
|
||||
presenter.SetCurrentValue(EffectProperty, null);
|
||||
ClearEffect(presenter.Content as ContentPresenter);
|
||||
}
|
||||
|
||||
private void AddEffect(ContentPresenter presenter, int count)
|
||||
{
|
||||
var newCount = --count;
|
||||
|
||||
if (newCount >= 0)
|
||||
{
|
||||
presenter.Effect = Effects[newCount];
|
||||
|
||||
var nextCount = --count;
|
||||
if (nextCount >= 1)
|
||||
{
|
||||
ClearEffect(_effectTopPresenter);
|
||||
return;
|
||||
var content = new ContentPresenter();
|
||||
presenter.Content = content;
|
||||
AddEffect(content, newCount);
|
||||
}
|
||||
|
||||
if (_isInternalAction) return;
|
||||
|
||||
_isInternalAction = true;
|
||||
AddEffect(_effectTopPresenter, Effects.Count);
|
||||
_isInternalAction = false;
|
||||
}
|
||||
|
||||
private void ClearEffect(ContentPresenter presenter)
|
||||
{
|
||||
if (presenter == null) return;
|
||||
|
||||
if (ReferenceEquals(_effectBottomPresenter, presenter))
|
||||
else if (nextCount >= 0)
|
||||
{
|
||||
_effectBottomPresenter.SetCurrentValue(EffectProperty, null);
|
||||
return;
|
||||
_effectBottomPresenter.Effect = Effects[0];
|
||||
presenter.Content = _effectBottomPresenter;
|
||||
}
|
||||
|
||||
presenter.SetCurrentValue(EffectProperty, null);
|
||||
ClearEffect(presenter.Content as ContentPresenter);
|
||||
}
|
||||
|
||||
private void AddEffect(ContentPresenter presenter, int count)
|
||||
{
|
||||
var newCount = --count;
|
||||
|
||||
if (newCount >= 0)
|
||||
else
|
||||
{
|
||||
presenter.Effect = Effects[newCount];
|
||||
|
||||
var nextCount = --count;
|
||||
if (nextCount >= 1)
|
||||
{
|
||||
var content = new ContentPresenter();
|
||||
presenter.Content = content;
|
||||
AddEffect(content, newCount);
|
||||
}
|
||||
else if (nextCount >= 0)
|
||||
{
|
||||
_effectBottomPresenter.Effect = Effects[0];
|
||||
presenter.Content = _effectBottomPresenter;
|
||||
}
|
||||
else
|
||||
{
|
||||
presenter.Content = _effectBottomPresenter;
|
||||
}
|
||||
presenter.Content = _effectBottomPresenter;
|
||||
}
|
||||
}
|
||||
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
|
||||
[Bindable(true)]
|
||||
public Collection<Effect> Effects { get; }
|
||||
|
||||
public static readonly DependencyProperty ContentProperty = DependencyProperty.Register(
|
||||
"Content", typeof(FrameworkElement), typeof(BlendEffectBox), new PropertyMetadata(default(FrameworkElement)));
|
||||
|
||||
public FrameworkElement Content
|
||||
{
|
||||
get => (FrameworkElement) GetValue(ContentProperty);
|
||||
set => SetValue(ContentProperty, value);
|
||||
}
|
||||
|
||||
internal static readonly DependencyProperty ActualContentProperty = DependencyProperty.Register(
|
||||
"ActualContent", typeof(FrameworkElement), typeof(BlendEffectBox), new PropertyMetadata(default(FrameworkElement)));
|
||||
|
||||
internal FrameworkElement ActualContent
|
||||
{
|
||||
get => (FrameworkElement) GetValue(ActualContentProperty);
|
||||
set => SetValue(ActualContentProperty, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
|
||||
[Bindable(true)]
|
||||
public Collection<Effect> Effects { get; }
|
||||
|
||||
public static readonly DependencyProperty ContentProperty = DependencyProperty.Register(
|
||||
"Content", typeof(FrameworkElement), typeof(BlendEffectBox), new PropertyMetadata(default(FrameworkElement)));
|
||||
|
||||
public FrameworkElement Content
|
||||
{
|
||||
get => (FrameworkElement) GetValue(ContentProperty);
|
||||
set => SetValue(ContentProperty, value);
|
||||
}
|
||||
|
||||
internal static readonly DependencyProperty ActualContentProperty = DependencyProperty.Register(
|
||||
"ActualContent", typeof(FrameworkElement), typeof(BlendEffectBox), new PropertyMetadata(default(FrameworkElement)));
|
||||
|
||||
internal FrameworkElement ActualContent
|
||||
{
|
||||
get => (FrameworkElement) GetValue(ActualContentProperty);
|
||||
set => SetValue(ActualContentProperty, value);
|
||||
}
|
||||
}
|
||||
@@ -2,86 +2,85 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace HandyControl.Controls
|
||||
namespace HandyControl.Controls;
|
||||
|
||||
public class Card : ContentControl
|
||||
{
|
||||
public class Card : ContentControl
|
||||
public static readonly DependencyProperty HeaderProperty = DependencyProperty.Register(
|
||||
"Header", typeof(object), typeof(Card), new PropertyMetadata(default(object)));
|
||||
|
||||
public object Header
|
||||
{
|
||||
public static readonly DependencyProperty HeaderProperty = DependencyProperty.Register(
|
||||
"Header", typeof(object), typeof(Card), new PropertyMetadata(default(object)));
|
||||
|
||||
public object Header
|
||||
{
|
||||
get => GetValue(HeaderProperty);
|
||||
set => SetValue(HeaderProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty HeaderTemplateProperty = DependencyProperty.Register(
|
||||
"HeaderTemplate", typeof(DataTemplate), typeof(Card), new PropertyMetadata(default(DataTemplate)));
|
||||
|
||||
[Bindable(true), Category("Content")]
|
||||
public DataTemplate HeaderTemplate
|
||||
{
|
||||
get => (DataTemplate) GetValue(HeaderTemplateProperty);
|
||||
set => SetValue(HeaderTemplateProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty HeaderTemplateSelectorProperty = DependencyProperty.Register(
|
||||
"HeaderTemplateSelector", typeof(DataTemplateSelector), typeof(Card), new PropertyMetadata(default(DataTemplateSelector)));
|
||||
|
||||
[Bindable(true), Category("Content")]
|
||||
public DataTemplateSelector HeaderTemplateSelector
|
||||
{
|
||||
get => (DataTemplateSelector) GetValue(HeaderTemplateSelectorProperty);
|
||||
set => SetValue(HeaderTemplateSelectorProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty HeaderStringFormatProperty = DependencyProperty.Register(
|
||||
"HeaderStringFormat", typeof(string), typeof(Card), new PropertyMetadata(default(string)));
|
||||
|
||||
[Bindable(true), Category("Content")]
|
||||
public string HeaderStringFormat
|
||||
{
|
||||
get => (string) GetValue(HeaderStringFormatProperty);
|
||||
set => SetValue(HeaderStringFormatProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty FooterProperty = DependencyProperty.Register(
|
||||
"Footer", typeof(object), typeof(Card), new PropertyMetadata(default(object)));
|
||||
|
||||
public object Footer
|
||||
{
|
||||
get => GetValue(FooterProperty);
|
||||
set => SetValue(FooterProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty FooterTemplateProperty = DependencyProperty.Register(
|
||||
"FooterTemplate", typeof(DataTemplate), typeof(Card), new PropertyMetadata(default(DataTemplate)));
|
||||
|
||||
[Bindable(true), Category("Content")]
|
||||
public DataTemplate FooterTemplate
|
||||
{
|
||||
get => (DataTemplate) GetValue(FooterTemplateProperty);
|
||||
set => SetValue(FooterTemplateProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty FooterTemplateSelectorProperty = DependencyProperty.Register(
|
||||
"FooterTemplateSelector", typeof(DataTemplateSelector), typeof(Card), new PropertyMetadata(default(DataTemplateSelector)));
|
||||
|
||||
[Bindable(true), Category("Content")]
|
||||
public DataTemplateSelector FooterTemplateSelector
|
||||
{
|
||||
get => (DataTemplateSelector) GetValue(FooterTemplateSelectorProperty);
|
||||
set => SetValue(FooterTemplateSelectorProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty FooterStringFormatProperty = DependencyProperty.Register(
|
||||
"FooterStringFormat", typeof(string), typeof(Card), new PropertyMetadata(default(string)));
|
||||
|
||||
[Bindable(true), Category("Content")]
|
||||
public string FooterStringFormat
|
||||
{
|
||||
get => (string) GetValue(FooterStringFormatProperty);
|
||||
set => SetValue(FooterStringFormatProperty, value);
|
||||
}
|
||||
get => GetValue(HeaderProperty);
|
||||
set => SetValue(HeaderProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty HeaderTemplateProperty = DependencyProperty.Register(
|
||||
"HeaderTemplate", typeof(DataTemplate), typeof(Card), new PropertyMetadata(default(DataTemplate)));
|
||||
|
||||
[Bindable(true), Category("Content")]
|
||||
public DataTemplate HeaderTemplate
|
||||
{
|
||||
get => (DataTemplate) GetValue(HeaderTemplateProperty);
|
||||
set => SetValue(HeaderTemplateProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty HeaderTemplateSelectorProperty = DependencyProperty.Register(
|
||||
"HeaderTemplateSelector", typeof(DataTemplateSelector), typeof(Card), new PropertyMetadata(default(DataTemplateSelector)));
|
||||
|
||||
[Bindable(true), Category("Content")]
|
||||
public DataTemplateSelector HeaderTemplateSelector
|
||||
{
|
||||
get => (DataTemplateSelector) GetValue(HeaderTemplateSelectorProperty);
|
||||
set => SetValue(HeaderTemplateSelectorProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty HeaderStringFormatProperty = DependencyProperty.Register(
|
||||
"HeaderStringFormat", typeof(string), typeof(Card), new PropertyMetadata(default(string)));
|
||||
|
||||
[Bindable(true), Category("Content")]
|
||||
public string HeaderStringFormat
|
||||
{
|
||||
get => (string) GetValue(HeaderStringFormatProperty);
|
||||
set => SetValue(HeaderStringFormatProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty FooterProperty = DependencyProperty.Register(
|
||||
"Footer", typeof(object), typeof(Card), new PropertyMetadata(default(object)));
|
||||
|
||||
public object Footer
|
||||
{
|
||||
get => GetValue(FooterProperty);
|
||||
set => SetValue(FooterProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty FooterTemplateProperty = DependencyProperty.Register(
|
||||
"FooterTemplate", typeof(DataTemplate), typeof(Card), new PropertyMetadata(default(DataTemplate)));
|
||||
|
||||
[Bindable(true), Category("Content")]
|
||||
public DataTemplate FooterTemplate
|
||||
{
|
||||
get => (DataTemplate) GetValue(FooterTemplateProperty);
|
||||
set => SetValue(FooterTemplateProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty FooterTemplateSelectorProperty = DependencyProperty.Register(
|
||||
"FooterTemplateSelector", typeof(DataTemplateSelector), typeof(Card), new PropertyMetadata(default(DataTemplateSelector)));
|
||||
|
||||
[Bindable(true), Category("Content")]
|
||||
public DataTemplateSelector FooterTemplateSelector
|
||||
{
|
||||
get => (DataTemplateSelector) GetValue(FooterTemplateSelectorProperty);
|
||||
set => SetValue(FooterTemplateSelectorProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty FooterStringFormatProperty = DependencyProperty.Register(
|
||||
"FooterStringFormat", typeof(string), typeof(Card), new PropertyMetadata(default(string)));
|
||||
|
||||
[Bindable(true), Category("Content")]
|
||||
public string FooterStringFormat
|
||||
{
|
||||
get => (string) GetValue(FooterStringFormatProperty);
|
||||
set => SetValue(FooterStringFormatProperty, value);
|
||||
}
|
||||
}
|
||||
@@ -2,45 +2,44 @@
|
||||
using System.Windows;
|
||||
using HandyControl.Data;
|
||||
|
||||
namespace HandyControl.Controls
|
||||
namespace HandyControl.Controls;
|
||||
|
||||
public class ChatBubble : SelectableItem
|
||||
{
|
||||
public class ChatBubble : SelectableItem
|
||||
public static readonly DependencyProperty RoleProperty = DependencyProperty.Register(
|
||||
"Role", typeof(ChatRoleType), typeof(ChatBubble), new PropertyMetadata(default(ChatRoleType)));
|
||||
|
||||
public ChatRoleType Role
|
||||
{
|
||||
public static readonly DependencyProperty RoleProperty = DependencyProperty.Register(
|
||||
"Role", typeof(ChatRoleType), typeof(ChatBubble), new PropertyMetadata(default(ChatRoleType)));
|
||||
|
||||
public ChatRoleType Role
|
||||
{
|
||||
get => (ChatRoleType) GetValue(RoleProperty);
|
||||
set => SetValue(RoleProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty TypeProperty = DependencyProperty.Register(
|
||||
"Type", typeof(ChatMessageType), typeof(ChatBubble), new PropertyMetadata(default(ChatMessageType)));
|
||||
|
||||
public ChatMessageType Type
|
||||
{
|
||||
get => (ChatMessageType) GetValue(TypeProperty);
|
||||
set => SetValue(TypeProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty IsReadProperty = DependencyProperty.Register(
|
||||
"IsRead", typeof(bool), typeof(ChatBubble), new PropertyMetadata(ValueBoxes.FalseBox));
|
||||
|
||||
public bool IsRead
|
||||
{
|
||||
get => (bool) GetValue(IsReadProperty);
|
||||
set => SetValue(IsReadProperty, ValueBoxes.BooleanBox(value));
|
||||
}
|
||||
|
||||
public Action<object> ReadAction { get; set; }
|
||||
|
||||
protected override void OnSelected(RoutedEventArgs e)
|
||||
{
|
||||
base.OnSelected(e);
|
||||
|
||||
IsRead = true;
|
||||
ReadAction?.Invoke(Content);
|
||||
}
|
||||
get => (ChatRoleType) GetValue(RoleProperty);
|
||||
set => SetValue(RoleProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty TypeProperty = DependencyProperty.Register(
|
||||
"Type", typeof(ChatMessageType), typeof(ChatBubble), new PropertyMetadata(default(ChatMessageType)));
|
||||
|
||||
public ChatMessageType Type
|
||||
{
|
||||
get => (ChatMessageType) GetValue(TypeProperty);
|
||||
set => SetValue(TypeProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty IsReadProperty = DependencyProperty.Register(
|
||||
"IsRead", typeof(bool), typeof(ChatBubble), new PropertyMetadata(ValueBoxes.FalseBox));
|
||||
|
||||
public bool IsRead
|
||||
{
|
||||
get => (bool) GetValue(IsReadProperty);
|
||||
set => SetValue(IsReadProperty, ValueBoxes.BooleanBox(value));
|
||||
}
|
||||
|
||||
public Action<object> ReadAction { get; set; }
|
||||
|
||||
protected override void OnSelected(RoutedEventArgs e)
|
||||
{
|
||||
base.OnSelected(e);
|
||||
|
||||
IsRead = true;
|
||||
ReadAction?.Invoke(Content);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -3,80 +3,79 @@ using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using HandyControl.Data;
|
||||
|
||||
namespace HandyControl.Controls
|
||||
namespace HandyControl.Controls;
|
||||
|
||||
public class Divider : Control
|
||||
{
|
||||
public class Divider : Control
|
||||
public static readonly DependencyProperty ContentProperty = DependencyProperty.Register(
|
||||
"Content", typeof(object), typeof(Divider), new PropertyMetadata(default(object)));
|
||||
|
||||
public object Content
|
||||
{
|
||||
public static readonly DependencyProperty ContentProperty = DependencyProperty.Register(
|
||||
"Content", typeof(object), typeof(Divider), new PropertyMetadata(default(object)));
|
||||
|
||||
public object Content
|
||||
{
|
||||
get => GetValue(ContentProperty);
|
||||
set => SetValue(ContentProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty OrientationProperty = DependencyProperty.Register(
|
||||
"Orientation", typeof(Orientation), typeof(Divider), new PropertyMetadata(default(Orientation)));
|
||||
|
||||
public Orientation Orientation
|
||||
{
|
||||
get => (Orientation) GetValue(OrientationProperty);
|
||||
set => SetValue(OrientationProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ContentTemplateProperty = DependencyProperty.Register(
|
||||
"ContentTemplate", typeof(DataTemplate), typeof(Divider), new PropertyMetadata(default(DataTemplate)));
|
||||
|
||||
public DataTemplate ContentTemplate
|
||||
{
|
||||
get => (DataTemplate) GetValue(ContentTemplateProperty);
|
||||
set => SetValue(ContentTemplateProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ContentStringFormatProperty = DependencyProperty.Register(
|
||||
"ContentStringFormat", typeof(string), typeof(Divider), new PropertyMetadata(default(string)));
|
||||
|
||||
public string ContentStringFormat
|
||||
{
|
||||
get => (string) GetValue(ContentStringFormatProperty);
|
||||
set => SetValue(ContentStringFormatProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ContentTemplateSelectorProperty = DependencyProperty.Register(
|
||||
"ContentTemplateSelector", typeof(DataTemplateSelector), typeof(Divider), new PropertyMetadata(default(DataTemplateSelector)));
|
||||
|
||||
public DataTemplateSelector ContentTemplateSelector
|
||||
{
|
||||
get => (DataTemplateSelector) GetValue(ContentTemplateSelectorProperty);
|
||||
set => SetValue(ContentTemplateSelectorProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty LineStrokeProperty = DependencyProperty.Register(
|
||||
"LineStroke", typeof(Brush), typeof(Divider), new PropertyMetadata(default(Brush)));
|
||||
|
||||
public Brush LineStroke
|
||||
{
|
||||
get => (Brush) GetValue(LineStrokeProperty);
|
||||
set => SetValue(LineStrokeProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty LineStrokeThicknessProperty = DependencyProperty.Register(
|
||||
"LineStrokeThickness", typeof(double), typeof(Divider), new PropertyMetadata(ValueBoxes.Double1Box));
|
||||
|
||||
public double LineStrokeThickness
|
||||
{
|
||||
get => (double) GetValue(LineStrokeThicknessProperty);
|
||||
set => SetValue(LineStrokeThicknessProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty LineStrokeDashArrayProperty = DependencyProperty.Register(
|
||||
"LineStrokeDashArray", typeof(DoubleCollection), typeof(Divider), new PropertyMetadata(new DoubleCollection()));
|
||||
|
||||
public DoubleCollection LineStrokeDashArray
|
||||
{
|
||||
get => (DoubleCollection) GetValue(LineStrokeDashArrayProperty);
|
||||
set => SetValue(LineStrokeDashArrayProperty, value);
|
||||
}
|
||||
get => GetValue(ContentProperty);
|
||||
set => SetValue(ContentProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty OrientationProperty = DependencyProperty.Register(
|
||||
"Orientation", typeof(Orientation), typeof(Divider), new PropertyMetadata(default(Orientation)));
|
||||
|
||||
public Orientation Orientation
|
||||
{
|
||||
get => (Orientation) GetValue(OrientationProperty);
|
||||
set => SetValue(OrientationProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ContentTemplateProperty = DependencyProperty.Register(
|
||||
"ContentTemplate", typeof(DataTemplate), typeof(Divider), new PropertyMetadata(default(DataTemplate)));
|
||||
|
||||
public DataTemplate ContentTemplate
|
||||
{
|
||||
get => (DataTemplate) GetValue(ContentTemplateProperty);
|
||||
set => SetValue(ContentTemplateProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ContentStringFormatProperty = DependencyProperty.Register(
|
||||
"ContentStringFormat", typeof(string), typeof(Divider), new PropertyMetadata(default(string)));
|
||||
|
||||
public string ContentStringFormat
|
||||
{
|
||||
get => (string) GetValue(ContentStringFormatProperty);
|
||||
set => SetValue(ContentStringFormatProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ContentTemplateSelectorProperty = DependencyProperty.Register(
|
||||
"ContentTemplateSelector", typeof(DataTemplateSelector), typeof(Divider), new PropertyMetadata(default(DataTemplateSelector)));
|
||||
|
||||
public DataTemplateSelector ContentTemplateSelector
|
||||
{
|
||||
get => (DataTemplateSelector) GetValue(ContentTemplateSelectorProperty);
|
||||
set => SetValue(ContentTemplateSelectorProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty LineStrokeProperty = DependencyProperty.Register(
|
||||
"LineStroke", typeof(Brush), typeof(Divider), new PropertyMetadata(default(Brush)));
|
||||
|
||||
public Brush LineStroke
|
||||
{
|
||||
get => (Brush) GetValue(LineStrokeProperty);
|
||||
set => SetValue(LineStrokeProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty LineStrokeThicknessProperty = DependencyProperty.Register(
|
||||
"LineStrokeThickness", typeof(double), typeof(Divider), new PropertyMetadata(ValueBoxes.Double1Box));
|
||||
|
||||
public double LineStrokeThickness
|
||||
{
|
||||
get => (double) GetValue(LineStrokeThicknessProperty);
|
||||
set => SetValue(LineStrokeThicknessProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty LineStrokeDashArrayProperty = DependencyProperty.Register(
|
||||
"LineStrokeDashArray", typeof(DoubleCollection), typeof(Divider), new PropertyMetadata(new DoubleCollection()));
|
||||
|
||||
public DoubleCollection LineStrokeDashArray
|
||||
{
|
||||
get => (DoubleCollection) GetValue(LineStrokeDashArrayProperty);
|
||||
set => SetValue(LineStrokeDashArrayProperty, value);
|
||||
}
|
||||
}
|
||||
@@ -2,35 +2,34 @@
|
||||
using System.Windows.Controls;
|
||||
using HandyControl.Data;
|
||||
|
||||
namespace HandyControl.Controls
|
||||
namespace HandyControl.Controls;
|
||||
|
||||
public class Empty : ContentControl
|
||||
{
|
||||
public class Empty : ContentControl
|
||||
public static readonly DependencyProperty DescriptionProperty = DependencyProperty.Register(
|
||||
"Description", typeof(object), typeof(Empty), new PropertyMetadata(default(object)));
|
||||
|
||||
public object Description
|
||||
{
|
||||
public static readonly DependencyProperty DescriptionProperty = DependencyProperty.Register(
|
||||
"Description", typeof(object), typeof(Empty), new PropertyMetadata(default(object)));
|
||||
|
||||
public object Description
|
||||
{
|
||||
get => GetValue(DescriptionProperty);
|
||||
set => SetValue(DescriptionProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty LogoProperty = DependencyProperty.Register(
|
||||
"Logo", typeof(object), typeof(Empty), new PropertyMetadata(default(object)));
|
||||
|
||||
public object Logo
|
||||
{
|
||||
get => GetValue(LogoProperty);
|
||||
set => SetValue(LogoProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ShowEmptyProperty = DependencyProperty.RegisterAttached(
|
||||
"ShowEmpty", typeof(bool), typeof(Empty), new FrameworkPropertyMetadata(ValueBoxes.FalseBox, FrameworkPropertyMetadataOptions.Inherits));
|
||||
|
||||
public static void SetShowEmpty(DependencyObject element, bool value)
|
||||
=> element.SetValue(ShowEmptyProperty, ValueBoxes.BooleanBox(value));
|
||||
|
||||
public static bool GetShowEmpty(DependencyObject element)
|
||||
=> (bool) element.GetValue(ShowEmptyProperty);
|
||||
get => GetValue(DescriptionProperty);
|
||||
set => SetValue(DescriptionProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty LogoProperty = DependencyProperty.Register(
|
||||
"Logo", typeof(object), typeof(Empty), new PropertyMetadata(default(object)));
|
||||
|
||||
public object Logo
|
||||
{
|
||||
get => GetValue(LogoProperty);
|
||||
set => SetValue(LogoProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ShowEmptyProperty = DependencyProperty.RegisterAttached(
|
||||
"ShowEmpty", typeof(bool), typeof(Empty), new FrameworkPropertyMetadata(ValueBoxes.FalseBox, FrameworkPropertyMetadataOptions.Inherits));
|
||||
|
||||
public static void SetShowEmpty(DependencyObject element, bool value)
|
||||
=> element.SetValue(ShowEmptyProperty, ValueBoxes.BooleanBox(value));
|
||||
|
||||
public static bool GetShowEmpty(DependencyObject element)
|
||||
=> (bool) element.GetValue(ShowEmptyProperty);
|
||||
}
|
||||
@@ -5,96 +5,95 @@ using HandyControl.Data;
|
||||
using HandyControl.Tools;
|
||||
using HandyControl.Tools.Extension;
|
||||
|
||||
namespace HandyControl.Controls
|
||||
namespace HandyControl.Controls;
|
||||
|
||||
public class GotoTop : Button
|
||||
{
|
||||
public class GotoTop : Button
|
||||
private Action _gotoTopAction;
|
||||
|
||||
private System.Windows.Controls.ScrollViewer _scrollViewer;
|
||||
|
||||
public static readonly DependencyProperty TargetProperty = DependencyProperty.Register(
|
||||
"Target", typeof(DependencyObject), typeof(GotoTop), new PropertyMetadata(default(DependencyObject)));
|
||||
|
||||
public DependencyObject Target
|
||||
{
|
||||
private Action _gotoTopAction;
|
||||
get => (DependencyObject) GetValue(TargetProperty);
|
||||
set => SetValue(TargetProperty, value);
|
||||
}
|
||||
|
||||
private System.Windows.Controls.ScrollViewer _scrollViewer;
|
||||
public GotoTop() => Loaded += (s, e) => CreateGotoAction(Target);
|
||||
|
||||
public static readonly DependencyProperty TargetProperty = DependencyProperty.Register(
|
||||
"Target", typeof(DependencyObject), typeof(GotoTop), new PropertyMetadata(default(DependencyObject)));
|
||||
|
||||
public DependencyObject Target
|
||||
public virtual void CreateGotoAction(DependencyObject obj)
|
||||
{
|
||||
if (_scrollViewer != null)
|
||||
{
|
||||
get => (DependencyObject) GetValue(TargetProperty);
|
||||
set => SetValue(TargetProperty, value);
|
||||
_scrollViewer.ScrollChanged -= ScrollViewer_ScrollChanged;
|
||||
}
|
||||
|
||||
public GotoTop() => Loaded += (s, e) => CreateGotoAction(Target);
|
||||
|
||||
public virtual void CreateGotoAction(DependencyObject obj)
|
||||
_scrollViewer = VisualHelper.GetChild<System.Windows.Controls.ScrollViewer>(obj);
|
||||
if (_scrollViewer != null)
|
||||
{
|
||||
if (_scrollViewer != null)
|
||||
_scrollViewer.ScrollChanged += ScrollViewer_ScrollChanged;
|
||||
|
||||
if (_scrollViewer is ScrollViewer scrollViewerHandy && Animated && scrollViewerHandy.IsInertiaEnabled)
|
||||
{
|
||||
_scrollViewer.ScrollChanged -= ScrollViewer_ScrollChanged;
|
||||
_gotoTopAction = () => scrollViewerHandy.ScrollToTopInternal(AnimationTime);
|
||||
}
|
||||
_scrollViewer = VisualHelper.GetChild<System.Windows.Controls.ScrollViewer>(obj);
|
||||
if (_scrollViewer != null)
|
||||
else
|
||||
{
|
||||
_scrollViewer.ScrollChanged += ScrollViewer_ScrollChanged;
|
||||
|
||||
if (_scrollViewer is ScrollViewer scrollViewerHandy && Animated && scrollViewerHandy.IsInertiaEnabled)
|
||||
{
|
||||
_gotoTopAction = () => scrollViewerHandy.ScrollToTopInternal(AnimationTime);
|
||||
}
|
||||
else
|
||||
{
|
||||
_gotoTopAction = () => _scrollViewer.ScrollToTop();
|
||||
}
|
||||
_gotoTopAction = () => _scrollViewer.ScrollToTop();
|
||||
}
|
||||
}
|
||||
|
||||
private void ScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
|
||||
{
|
||||
if (AutoHiding)
|
||||
{
|
||||
this.Show(e.VerticalOffset >= HidingHeight);
|
||||
}
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty AnimatedProperty = DependencyProperty.Register(
|
||||
"Animated", typeof(bool), typeof(GotoTop), new PropertyMetadata(ValueBoxes.TrueBox));
|
||||
|
||||
public bool Animated
|
||||
{
|
||||
get => (bool) GetValue(AnimatedProperty);
|
||||
set => SetValue(AnimatedProperty, ValueBoxes.BooleanBox(value));
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty AnimationTimeProperty = DependencyProperty.Register(
|
||||
"AnimationTime", typeof(double), typeof(GotoTop), new PropertyMetadata(ValueBoxes.Double200Box));
|
||||
|
||||
public double AnimationTime
|
||||
{
|
||||
get => (double) GetValue(AnimationTimeProperty);
|
||||
set => SetValue(AnimationTimeProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty HidingHeightProperty = DependencyProperty.Register(
|
||||
"HidingHeight", typeof(double), typeof(GotoTop), new PropertyMetadata(ValueBoxes.Double0Box));
|
||||
|
||||
public double HidingHeight
|
||||
{
|
||||
get => (double) GetValue(HidingHeightProperty);
|
||||
set => SetValue(HidingHeightProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty AutoHidingProperty = DependencyProperty.Register(
|
||||
"AutoHiding", typeof(bool), typeof(GotoTop), new PropertyMetadata(ValueBoxes.TrueBox));
|
||||
|
||||
public bool AutoHiding
|
||||
{
|
||||
get => (bool) GetValue(AutoHidingProperty);
|
||||
set => SetValue(AutoHidingProperty, ValueBoxes.BooleanBox(value));
|
||||
}
|
||||
|
||||
protected override void OnClick()
|
||||
{
|
||||
base.OnClick();
|
||||
|
||||
_gotoTopAction?.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
|
||||
{
|
||||
if (AutoHiding)
|
||||
{
|
||||
this.Show(e.VerticalOffset >= HidingHeight);
|
||||
}
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty AnimatedProperty = DependencyProperty.Register(
|
||||
"Animated", typeof(bool), typeof(GotoTop), new PropertyMetadata(ValueBoxes.TrueBox));
|
||||
|
||||
public bool Animated
|
||||
{
|
||||
get => (bool) GetValue(AnimatedProperty);
|
||||
set => SetValue(AnimatedProperty, ValueBoxes.BooleanBox(value));
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty AnimationTimeProperty = DependencyProperty.Register(
|
||||
"AnimationTime", typeof(double), typeof(GotoTop), new PropertyMetadata(ValueBoxes.Double200Box));
|
||||
|
||||
public double AnimationTime
|
||||
{
|
||||
get => (double) GetValue(AnimationTimeProperty);
|
||||
set => SetValue(AnimationTimeProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty HidingHeightProperty = DependencyProperty.Register(
|
||||
"HidingHeight", typeof(double), typeof(GotoTop), new PropertyMetadata(ValueBoxes.Double0Box));
|
||||
|
||||
public double HidingHeight
|
||||
{
|
||||
get => (double) GetValue(HidingHeightProperty);
|
||||
set => SetValue(HidingHeightProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty AutoHidingProperty = DependencyProperty.Register(
|
||||
"AutoHiding", typeof(bool), typeof(GotoTop), new PropertyMetadata(ValueBoxes.TrueBox));
|
||||
|
||||
public bool AutoHiding
|
||||
{
|
||||
get => (bool) GetValue(AutoHidingProperty);
|
||||
set => SetValue(AutoHidingProperty, ValueBoxes.BooleanBox(value));
|
||||
}
|
||||
|
||||
protected override void OnClick()
|
||||
{
|
||||
base.OnClick();
|
||||
|
||||
_gotoTopAction?.Invoke();
|
||||
}
|
||||
}
|
||||
@@ -4,55 +4,54 @@ using System.Windows.Media;
|
||||
using HandyControl.Data;
|
||||
using HandyControl.Tools;
|
||||
|
||||
namespace HandyControl.Controls
|
||||
namespace HandyControl.Controls;
|
||||
|
||||
public class Gravatar : ContentControl
|
||||
{
|
||||
public class Gravatar : ContentControl
|
||||
public static readonly DependencyProperty GeneratorProperty = DependencyProperty.Register(
|
||||
"Generator", typeof(IGravatarGenerator), typeof(Gravatar), new PropertyMetadata(new GithubGravatarGenerator()));
|
||||
|
||||
public IGravatarGenerator Generator
|
||||
{
|
||||
public static readonly DependencyProperty GeneratorProperty = DependencyProperty.Register(
|
||||
"Generator", typeof(IGravatarGenerator), typeof(Gravatar), new PropertyMetadata(new GithubGravatarGenerator()));
|
||||
|
||||
public IGravatarGenerator Generator
|
||||
{
|
||||
get => (IGravatarGenerator) GetValue(GeneratorProperty);
|
||||
set => SetValue(GeneratorProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty IdProperty = DependencyProperty.Register(
|
||||
"Id", typeof(string), typeof(Gravatar), new PropertyMetadata(default(string), OnIdChanged));
|
||||
|
||||
private static void OnIdChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
var ctl = (Gravatar) d;
|
||||
if (ctl.Source != null) return;
|
||||
ctl.Content = ctl.Generator.GetGravatar((string) e.NewValue);
|
||||
}
|
||||
|
||||
public string Id
|
||||
{
|
||||
get => (string) GetValue(IdProperty);
|
||||
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;
|
||||
var v = (ImageSource) e.NewValue;
|
||||
|
||||
ctl.Background = v != null
|
||||
? new ImageBrush(v)
|
||||
{
|
||||
Stretch = Stretch.UniformToFill
|
||||
}
|
||||
: ResourceHelper.GetResourceInternal<Brush>(ResourceToken.SecondaryRegionBrush);
|
||||
}
|
||||
|
||||
public ImageSource Source
|
||||
{
|
||||
get => (ImageSource) GetValue(SourceProperty);
|
||||
set => SetValue(SourceProperty, value);
|
||||
}
|
||||
get => (IGravatarGenerator) GetValue(GeneratorProperty);
|
||||
set => SetValue(GeneratorProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty IdProperty = DependencyProperty.Register(
|
||||
"Id", typeof(string), typeof(Gravatar), new PropertyMetadata(default(string), OnIdChanged));
|
||||
|
||||
private static void OnIdChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
var ctl = (Gravatar) d;
|
||||
if (ctl.Source != null) return;
|
||||
ctl.Content = ctl.Generator.GetGravatar((string) e.NewValue);
|
||||
}
|
||||
|
||||
public string Id
|
||||
{
|
||||
get => (string) GetValue(IdProperty);
|
||||
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;
|
||||
var v = (ImageSource) e.NewValue;
|
||||
|
||||
ctl.Background = v != null
|
||||
? new ImageBrush(v)
|
||||
{
|
||||
Stretch = Stretch.UniformToFill
|
||||
}
|
||||
: ResourceHelper.GetResourceInternal<Brush>(ResourceToken.SecondaryRegionBrush);
|
||||
}
|
||||
|
||||
public ImageSource Source
|
||||
{
|
||||
get => (ImageSource) GetValue(SourceProperty);
|
||||
set => SetValue(SourceProperty, value);
|
||||
}
|
||||
}
|
||||
@@ -7,154 +7,153 @@ using HandyControl.Interactivity;
|
||||
using HandyControl.Tools;
|
||||
using HandyControl.Tools.Extension;
|
||||
|
||||
namespace HandyControl.Controls
|
||||
namespace HandyControl.Controls;
|
||||
|
||||
[TemplatePart(Name = ElementVisualBrush, Type = typeof(VisualBrush))]
|
||||
public class Magnifier : AdornerElement
|
||||
{
|
||||
[TemplatePart(Name = ElementVisualBrush, Type = typeof(VisualBrush))]
|
||||
public class Magnifier : AdornerElement
|
||||
private AdornerContainer _adornerContainer;
|
||||
|
||||
private Size _viewboxSize;
|
||||
|
||||
private const string ElementVisualBrush = "PART_VisualBrush";
|
||||
|
||||
private VisualBrush _visualBrush = new();
|
||||
|
||||
private readonly TranslateTransform _translateTransform;
|
||||
|
||||
public static readonly DependencyProperty HorizontalOffsetProperty = DependencyProperty.Register(
|
||||
"HorizontalOffset", typeof(double), typeof(Magnifier), new PropertyMetadata(ValueBoxes.Double0Box));
|
||||
|
||||
public double HorizontalOffset
|
||||
{
|
||||
private AdornerContainer _adornerContainer;
|
||||
get => (double) GetValue(HorizontalOffsetProperty);
|
||||
set => SetValue(HorizontalOffsetProperty, value);
|
||||
}
|
||||
|
||||
private Size _viewboxSize;
|
||||
public static readonly DependencyProperty VerticalOffsetProperty = DependencyProperty.Register(
|
||||
"VerticalOffset", typeof(double), typeof(Magnifier), new PropertyMetadata(ValueBoxes.Double0Box));
|
||||
|
||||
private const string ElementVisualBrush = "PART_VisualBrush";
|
||||
public double VerticalOffset
|
||||
{
|
||||
get => (double) GetValue(VerticalOffsetProperty);
|
||||
set => SetValue(VerticalOffsetProperty, value);
|
||||
}
|
||||
|
||||
private VisualBrush _visualBrush = new();
|
||||
public static Magnifier Default => new();
|
||||
|
||||
private readonly TranslateTransform _translateTransform;
|
||||
public static readonly DependencyProperty ScaleProperty = DependencyProperty.Register(
|
||||
"Scale", typeof(double), typeof(Magnifier), new PropertyMetadata(5.0, OnScaleChanged), ValidateHelper.IsInRangeOfPosDouble);
|
||||
|
||||
public static readonly DependencyProperty HorizontalOffsetProperty = DependencyProperty.Register(
|
||||
"HorizontalOffset", typeof(double), typeof(Magnifier), new PropertyMetadata(ValueBoxes.Double0Box));
|
||||
private static void OnScaleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((Magnifier) d).UpdateViewboxSize();
|
||||
|
||||
public double HorizontalOffset
|
||||
public double Scale
|
||||
{
|
||||
get => (double) GetValue(ScaleProperty);
|
||||
set => SetValue(ScaleProperty, value);
|
||||
}
|
||||
|
||||
public Magnifier()
|
||||
{
|
||||
_translateTransform = new TranslateTransform();
|
||||
RenderTransform = _translateTransform;
|
||||
}
|
||||
|
||||
public override void OnApplyTemplate()
|
||||
{
|
||||
base.OnApplyTemplate();
|
||||
|
||||
var visualBrush = GetTemplateChild(ElementVisualBrush) as VisualBrush ?? new VisualBrush();
|
||||
visualBrush.Viewbox = _visualBrush.Viewbox;
|
||||
_visualBrush = visualBrush;
|
||||
}
|
||||
|
||||
protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
|
||||
{
|
||||
base.OnRenderSizeChanged(sizeInfo);
|
||||
UpdateViewboxSize();
|
||||
}
|
||||
|
||||
private void UpdateViewboxSize() => _viewboxSize = new Size(ActualWidth / Scale, ActualHeight / Scale);
|
||||
|
||||
protected sealed override void OnTargetChanged(FrameworkElement element, bool isNew)
|
||||
{
|
||||
base.OnTargetChanged(element, isNew);
|
||||
|
||||
if (element == null) return;
|
||||
|
||||
if (!isNew)
|
||||
{
|
||||
get => (double) GetValue(HorizontalOffsetProperty);
|
||||
set => SetValue(HorizontalOffsetProperty, value);
|
||||
element.MouseEnter -= Element_MouseEnter;
|
||||
element.MouseLeave -= Element_MouseLeave;
|
||||
element.MouseMove -= Element_MouseMove;
|
||||
ElementTarget = null;
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty VerticalOffsetProperty = DependencyProperty.Register(
|
||||
"VerticalOffset", typeof(double), typeof(Magnifier), new PropertyMetadata(ValueBoxes.Double0Box));
|
||||
|
||||
public double VerticalOffset
|
||||
else
|
||||
{
|
||||
get => (double) GetValue(VerticalOffsetProperty);
|
||||
set => SetValue(VerticalOffsetProperty, value);
|
||||
}
|
||||
|
||||
public static Magnifier Default => new();
|
||||
|
||||
public static readonly DependencyProperty ScaleProperty = DependencyProperty.Register(
|
||||
"Scale", typeof(double), typeof(Magnifier), new PropertyMetadata(5.0, OnScaleChanged), ValidateHelper.IsInRangeOfPosDouble);
|
||||
|
||||
private static void OnScaleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((Magnifier) d).UpdateViewboxSize();
|
||||
|
||||
public double Scale
|
||||
{
|
||||
get => (double) GetValue(ScaleProperty);
|
||||
set => SetValue(ScaleProperty, value);
|
||||
}
|
||||
|
||||
public Magnifier()
|
||||
{
|
||||
_translateTransform = new TranslateTransform();
|
||||
RenderTransform = _translateTransform;
|
||||
}
|
||||
|
||||
public override void OnApplyTemplate()
|
||||
{
|
||||
base.OnApplyTemplate();
|
||||
|
||||
var visualBrush = GetTemplateChild(ElementVisualBrush) as VisualBrush ?? new VisualBrush();
|
||||
visualBrush.Viewbox = _visualBrush.Viewbox;
|
||||
_visualBrush = visualBrush;
|
||||
}
|
||||
|
||||
protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
|
||||
{
|
||||
base.OnRenderSizeChanged(sizeInfo);
|
||||
UpdateViewboxSize();
|
||||
}
|
||||
|
||||
private void UpdateViewboxSize() => _viewboxSize = new Size(ActualWidth / Scale, ActualHeight / Scale);
|
||||
|
||||
protected sealed override void OnTargetChanged(FrameworkElement element, bool isNew)
|
||||
{
|
||||
base.OnTargetChanged(element, isNew);
|
||||
|
||||
if (element == null) return;
|
||||
|
||||
if (!isNew)
|
||||
{
|
||||
element.MouseEnter -= Element_MouseEnter;
|
||||
element.MouseLeave -= Element_MouseLeave;
|
||||
element.MouseMove -= Element_MouseMove;
|
||||
ElementTarget = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
element.MouseEnter += Element_MouseEnter;
|
||||
element.MouseLeave += Element_MouseLeave;
|
||||
element.MouseMove += Element_MouseMove;
|
||||
ElementTarget = element;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Dispose() => HideAdornerElement();
|
||||
|
||||
private void UpdateLocation()
|
||||
{
|
||||
var targetPoint = Mouse.GetPosition(Target);
|
||||
var subX = targetPoint.X - _visualBrush.Viewbox.Width / 2;
|
||||
var subY = targetPoint.Y - _visualBrush.Viewbox.Height / 2;
|
||||
|
||||
var targetVector = VisualTreeHelper.GetOffset(Target);
|
||||
_visualBrush.Viewbox = new Rect(new Point(subX + targetVector.X, subY + targetVector.Y), _viewboxSize);
|
||||
|
||||
var adornerPoint = Mouse.GetPosition(_adornerContainer);
|
||||
_translateTransform.X = adornerPoint.X + HorizontalOffset;
|
||||
_translateTransform.Y = adornerPoint.Y + VerticalOffset;
|
||||
}
|
||||
|
||||
private void Element_MouseMove(object sender, MouseEventArgs e) => UpdateLocation();
|
||||
|
||||
private void Element_MouseLeave(object sender, MouseEventArgs e) => HideAdornerElement();
|
||||
|
||||
private void Element_MouseEnter(object sender, MouseEventArgs e) => ShowAdornerElement();
|
||||
|
||||
private void HideAdornerElement()
|
||||
{
|
||||
if (_adornerContainer == null) return;
|
||||
var layer = AdornerLayer.GetAdornerLayer(Target);
|
||||
|
||||
if (layer != null)
|
||||
{
|
||||
layer.Remove(_adornerContainer);
|
||||
}
|
||||
else if (_adornerContainer is { Parent: AdornerLayer parent })
|
||||
{
|
||||
parent.Remove(_adornerContainer);
|
||||
}
|
||||
|
||||
if (_adornerContainer != null)
|
||||
{
|
||||
_adornerContainer.Child = null;
|
||||
_adornerContainer = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void ShowAdornerElement()
|
||||
{
|
||||
if (_adornerContainer == null)
|
||||
{
|
||||
var layer = AdornerLayer.GetAdornerLayer(Target);
|
||||
if (layer == null) return;
|
||||
|
||||
_adornerContainer = new AdornerContainer(layer)
|
||||
{
|
||||
Child = this
|
||||
};
|
||||
layer.Add(_adornerContainer);
|
||||
}
|
||||
this.Show();
|
||||
element.MouseEnter += Element_MouseEnter;
|
||||
element.MouseLeave += Element_MouseLeave;
|
||||
element.MouseMove += Element_MouseMove;
|
||||
ElementTarget = element;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Dispose() => HideAdornerElement();
|
||||
|
||||
private void UpdateLocation()
|
||||
{
|
||||
var targetPoint = Mouse.GetPosition(Target);
|
||||
var subX = targetPoint.X - _visualBrush.Viewbox.Width / 2;
|
||||
var subY = targetPoint.Y - _visualBrush.Viewbox.Height / 2;
|
||||
|
||||
var targetVector = VisualTreeHelper.GetOffset(Target);
|
||||
_visualBrush.Viewbox = new Rect(new Point(subX + targetVector.X, subY + targetVector.Y), _viewboxSize);
|
||||
|
||||
var adornerPoint = Mouse.GetPosition(_adornerContainer);
|
||||
_translateTransform.X = adornerPoint.X + HorizontalOffset;
|
||||
_translateTransform.Y = adornerPoint.Y + VerticalOffset;
|
||||
}
|
||||
|
||||
private void Element_MouseMove(object sender, MouseEventArgs e) => UpdateLocation();
|
||||
|
||||
private void Element_MouseLeave(object sender, MouseEventArgs e) => HideAdornerElement();
|
||||
|
||||
private void Element_MouseEnter(object sender, MouseEventArgs e) => ShowAdornerElement();
|
||||
|
||||
private void HideAdornerElement()
|
||||
{
|
||||
if (_adornerContainer == null) return;
|
||||
var layer = AdornerLayer.GetAdornerLayer(Target);
|
||||
|
||||
if (layer != null)
|
||||
{
|
||||
layer.Remove(_adornerContainer);
|
||||
}
|
||||
else if (_adornerContainer is { Parent: AdornerLayer parent })
|
||||
{
|
||||
parent.Remove(_adornerContainer);
|
||||
}
|
||||
|
||||
if (_adornerContainer != null)
|
||||
{
|
||||
_adornerContainer.Child = null;
|
||||
_adornerContainer = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void ShowAdornerElement()
|
||||
{
|
||||
if (_adornerContainer == null)
|
||||
{
|
||||
var layer = AdornerLayer.GetAdornerLayer(Target);
|
||||
if (layer == null) return;
|
||||
|
||||
_adornerContainer = new AdornerContainer(layer)
|
||||
{
|
||||
Child = this
|
||||
};
|
||||
layer.Add(_adornerContainer);
|
||||
}
|
||||
this.Show();
|
||||
}
|
||||
}
|
||||
@@ -5,150 +5,149 @@ using System.Windows.Threading;
|
||||
using HandyControl.Data;
|
||||
using HandyControl.Tools;
|
||||
|
||||
namespace HandyControl.Controls
|
||||
namespace HandyControl.Controls;
|
||||
|
||||
public sealed class Notification : System.Windows.Window
|
||||
{
|
||||
public sealed class Notification : System.Windows.Window
|
||||
private const int WaitTime = 6;
|
||||
|
||||
/// <summary>
|
||||
/// 计数
|
||||
/// </summary>
|
||||
private int _tickCount;
|
||||
|
||||
/// <summary>
|
||||
/// 关闭计时器
|
||||
/// </summary>
|
||||
private DispatcherTimer _timerClose;
|
||||
|
||||
private ShowAnimation ShowAnimation { get; set; }
|
||||
|
||||
private bool _shouldBeClosed;
|
||||
|
||||
public Notification()
|
||||
{
|
||||
private const int WaitTime = 6;
|
||||
WindowStyle = WindowStyle.None;
|
||||
AllowsTransparency = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 计数
|
||||
/// </summary>
|
||||
private int _tickCount;
|
||||
|
||||
/// <summary>
|
||||
/// 关闭计时器
|
||||
/// </summary>
|
||||
private DispatcherTimer _timerClose;
|
||||
|
||||
private ShowAnimation ShowAnimation { get; set; }
|
||||
|
||||
private bool _shouldBeClosed;
|
||||
|
||||
public Notification()
|
||||
public static Notification Show(object content, ShowAnimation showAnimation = ShowAnimation.None, bool staysOpen = false)
|
||||
{
|
||||
var notification = new Notification
|
||||
{
|
||||
WindowStyle = WindowStyle.None;
|
||||
AllowsTransparency = true;
|
||||
Content = content,
|
||||
Opacity = 0,
|
||||
ShowAnimation = showAnimation
|
||||
};
|
||||
|
||||
notification.Show();
|
||||
|
||||
var desktopWorkingArea = SystemParameters.WorkArea;
|
||||
var leftMax = desktopWorkingArea.Width - notification.ActualWidth;
|
||||
var topMax = desktopWorkingArea.Height - notification.ActualHeight;
|
||||
|
||||
switch (showAnimation)
|
||||
{
|
||||
case ShowAnimation.None:
|
||||
notification.Opacity = 1;
|
||||
notification.Left = leftMax;
|
||||
notification.Top = topMax;
|
||||
break;
|
||||
case ShowAnimation.HorizontalMove:
|
||||
notification.Opacity = 1;
|
||||
notification.Left = desktopWorkingArea.Width;
|
||||
notification.Top = topMax;
|
||||
notification.BeginAnimation(LeftProperty, AnimationHelper.CreateAnimation(leftMax));
|
||||
break;
|
||||
case ShowAnimation.VerticalMove:
|
||||
notification.Opacity = 1;
|
||||
notification.Left = leftMax;
|
||||
notification.Top = desktopWorkingArea.Height;
|
||||
notification.BeginAnimation(TopProperty, AnimationHelper.CreateAnimation(topMax));
|
||||
break;
|
||||
case ShowAnimation.Fade:
|
||||
notification.Left = leftMax;
|
||||
notification.Top = topMax;
|
||||
notification.BeginAnimation(OpacityProperty, AnimationHelper.CreateAnimation(1));
|
||||
break;
|
||||
default:
|
||||
notification.Opacity = 1;
|
||||
notification.Left = leftMax;
|
||||
notification.Top = topMax;
|
||||
break;
|
||||
}
|
||||
|
||||
public static Notification Show(object content, ShowAnimation showAnimation = ShowAnimation.None, bool staysOpen = false)
|
||||
if (!staysOpen) notification.StartTimer();
|
||||
|
||||
return notification;
|
||||
}
|
||||
|
||||
protected override void OnClosing(CancelEventArgs e)
|
||||
{
|
||||
base.OnClosing(e);
|
||||
|
||||
if (_shouldBeClosed)
|
||||
{
|
||||
var notification = new Notification
|
||||
{
|
||||
Content = content,
|
||||
Opacity = 0,
|
||||
ShowAnimation = showAnimation
|
||||
};
|
||||
|
||||
notification.Show();
|
||||
|
||||
var desktopWorkingArea = SystemParameters.WorkArea;
|
||||
var leftMax = desktopWorkingArea.Width - notification.ActualWidth;
|
||||
var topMax = desktopWorkingArea.Height - notification.ActualHeight;
|
||||
|
||||
switch (showAnimation)
|
||||
{
|
||||
case ShowAnimation.None:
|
||||
notification.Opacity = 1;
|
||||
notification.Left = leftMax;
|
||||
notification.Top = topMax;
|
||||
break;
|
||||
case ShowAnimation.HorizontalMove:
|
||||
notification.Opacity = 1;
|
||||
notification.Left = desktopWorkingArea.Width;
|
||||
notification.Top = topMax;
|
||||
notification.BeginAnimation(LeftProperty, AnimationHelper.CreateAnimation(leftMax));
|
||||
break;
|
||||
case ShowAnimation.VerticalMove:
|
||||
notification.Opacity = 1;
|
||||
notification.Left = leftMax;
|
||||
notification.Top = desktopWorkingArea.Height;
|
||||
notification.BeginAnimation(TopProperty, AnimationHelper.CreateAnimation(topMax));
|
||||
break;
|
||||
case ShowAnimation.Fade:
|
||||
notification.Left = leftMax;
|
||||
notification.Top = topMax;
|
||||
notification.BeginAnimation(OpacityProperty, AnimationHelper.CreateAnimation(1));
|
||||
break;
|
||||
default:
|
||||
notification.Opacity = 1;
|
||||
notification.Left = leftMax;
|
||||
notification.Top = topMax;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!staysOpen) notification.StartTimer();
|
||||
|
||||
return notification;
|
||||
return;
|
||||
}
|
||||
var desktopWorkingArea = SystemParameters.WorkArea;
|
||||
|
||||
protected override void OnClosing(CancelEventArgs e)
|
||||
switch (ShowAnimation)
|
||||
{
|
||||
base.OnClosing(e);
|
||||
|
||||
if (_shouldBeClosed)
|
||||
case ShowAnimation.None:
|
||||
break;
|
||||
case ShowAnimation.HorizontalMove:
|
||||
{
|
||||
return;
|
||||
var animation = AnimationHelper.CreateAnimation(desktopWorkingArea.Width);
|
||||
animation.Completed += Animation_Completed;
|
||||
BeginAnimation(LeftProperty, animation);
|
||||
e.Cancel = true;
|
||||
_shouldBeClosed = true;
|
||||
}
|
||||
var desktopWorkingArea = SystemParameters.WorkArea;
|
||||
|
||||
switch (ShowAnimation)
|
||||
break;
|
||||
case ShowAnimation.VerticalMove:
|
||||
{
|
||||
case ShowAnimation.None:
|
||||
break;
|
||||
case ShowAnimation.HorizontalMove:
|
||||
{
|
||||
var animation = AnimationHelper.CreateAnimation(desktopWorkingArea.Width);
|
||||
animation.Completed += Animation_Completed;
|
||||
BeginAnimation(LeftProperty, animation);
|
||||
e.Cancel = true;
|
||||
_shouldBeClosed = true;
|
||||
}
|
||||
break;
|
||||
case ShowAnimation.VerticalMove:
|
||||
{
|
||||
var animation = AnimationHelper.CreateAnimation(desktopWorkingArea.Height);
|
||||
animation.Completed += Animation_Completed;
|
||||
BeginAnimation(TopProperty, animation);
|
||||
e.Cancel = true;
|
||||
_shouldBeClosed = true;
|
||||
}
|
||||
break;
|
||||
case ShowAnimation.Fade:
|
||||
{
|
||||
var animation = AnimationHelper.CreateAnimation(0);
|
||||
animation.Completed += Animation_Completed;
|
||||
BeginAnimation(OpacityProperty, animation);
|
||||
e.Cancel = true;
|
||||
_shouldBeClosed = true;
|
||||
}
|
||||
break;
|
||||
var animation = AnimationHelper.CreateAnimation(desktopWorkingArea.Height);
|
||||
animation.Completed += Animation_Completed;
|
||||
BeginAnimation(TopProperty, animation);
|
||||
e.Cancel = true;
|
||||
_shouldBeClosed = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void Animation_Completed(object sender, EventArgs e) => Close();
|
||||
|
||||
/// <summary>
|
||||
/// 开始计时器
|
||||
/// </summary>
|
||||
private void StartTimer()
|
||||
{
|
||||
_timerClose = new DispatcherTimer
|
||||
break;
|
||||
case ShowAnimation.Fade:
|
||||
{
|
||||
Interval = TimeSpan.FromSeconds(1)
|
||||
};
|
||||
_timerClose.Tick += delegate
|
||||
{
|
||||
if (IsMouseOver)
|
||||
{
|
||||
_tickCount = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
_tickCount++;
|
||||
if (_tickCount >= WaitTime) Close();
|
||||
};
|
||||
_timerClose.Start();
|
||||
var animation = AnimationHelper.CreateAnimation(0);
|
||||
animation.Completed += Animation_Completed;
|
||||
BeginAnimation(OpacityProperty, animation);
|
||||
e.Cancel = true;
|
||||
_shouldBeClosed = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Animation_Completed(object sender, EventArgs e) => Close();
|
||||
|
||||
/// <summary>
|
||||
/// 开始计时器
|
||||
/// </summary>
|
||||
private void StartTimer()
|
||||
{
|
||||
_timerClose = new DispatcherTimer
|
||||
{
|
||||
Interval = TimeSpan.FromSeconds(1)
|
||||
};
|
||||
_timerClose.Tick += delegate
|
||||
{
|
||||
if (IsMouseOver)
|
||||
{
|
||||
_tickCount = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
_tickCount++;
|
||||
if (_tickCount >= WaitTime) Close();
|
||||
};
|
||||
_timerClose.Start();
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -7,396 +7,395 @@ using HandyControl.Interactivity;
|
||||
using HandyControl.Tools;
|
||||
using HandyControl.Tools.Extension;
|
||||
|
||||
namespace HandyControl.Controls
|
||||
namespace HandyControl.Controls;
|
||||
|
||||
/// <summary>
|
||||
/// 页码
|
||||
/// </summary>
|
||||
[TemplatePart(Name = ElementButtonLeft, Type = typeof(Button))]
|
||||
[TemplatePart(Name = ElementButtonRight, Type = typeof(Button))]
|
||||
[TemplatePart(Name = ElementButtonFirst, Type = typeof(RadioButton))]
|
||||
[TemplatePart(Name = ElementMoreLeft, Type = typeof(FrameworkElement))]
|
||||
[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
|
||||
|
||||
private const string ElementButtonLeft = "PART_ButtonLeft";
|
||||
private const string ElementButtonRight = "PART_ButtonRight";
|
||||
private const string ElementButtonFirst = "PART_ButtonFirst";
|
||||
private const string ElementMoreLeft = "PART_MoreLeft";
|
||||
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
|
||||
|
||||
#region Data
|
||||
|
||||
private Button _buttonLeft;
|
||||
private Button _buttonRight;
|
||||
private RadioButton _buttonFirst;
|
||||
private FrameworkElement _moreLeft;
|
||||
private Panel _panelMain;
|
||||
private FrameworkElement _moreRight;
|
||||
private RadioButton _buttonLast;
|
||||
private NumericUpDown _jumpNumericUpDown;
|
||||
|
||||
private bool _appliedTemplate;
|
||||
|
||||
#endregion Data
|
||||
|
||||
#region Public Events
|
||||
|
||||
/// <summary>
|
||||
/// 页码
|
||||
/// 页面更新事件
|
||||
/// </summary>
|
||||
[TemplatePart(Name = ElementButtonLeft, Type = typeof(Button))]
|
||||
[TemplatePart(Name = ElementButtonRight, Type = typeof(Button))]
|
||||
[TemplatePart(Name = ElementButtonFirst, Type = typeof(RadioButton))]
|
||||
[TemplatePart(Name = ElementMoreLeft, Type = typeof(FrameworkElement))]
|
||||
[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
|
||||
public static readonly RoutedEvent PageUpdatedEvent =
|
||||
EventManager.RegisterRoutedEvent("PageUpdated", RoutingStrategy.Bubble,
|
||||
typeof(EventHandler<FunctionEventArgs<int>>), typeof(Pagination));
|
||||
|
||||
/// <summary>
|
||||
/// 页面更新事件
|
||||
/// </summary>
|
||||
public event EventHandler<FunctionEventArgs<int>> PageUpdated
|
||||
{
|
||||
#region Constants
|
||||
|
||||
private const string ElementButtonLeft = "PART_ButtonLeft";
|
||||
private const string ElementButtonRight = "PART_ButtonRight";
|
||||
private const string ElementButtonFirst = "PART_ButtonFirst";
|
||||
private const string ElementMoreLeft = "PART_MoreLeft";
|
||||
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
|
||||
|
||||
#region Data
|
||||
|
||||
private Button _buttonLeft;
|
||||
private Button _buttonRight;
|
||||
private RadioButton _buttonFirst;
|
||||
private FrameworkElement _moreLeft;
|
||||
private Panel _panelMain;
|
||||
private FrameworkElement _moreRight;
|
||||
private RadioButton _buttonLast;
|
||||
private NumericUpDown _jumpNumericUpDown;
|
||||
|
||||
private bool _appliedTemplate;
|
||||
|
||||
#endregion Data
|
||||
|
||||
#region Public Events
|
||||
|
||||
/// <summary>
|
||||
/// 页面更新事件
|
||||
/// </summary>
|
||||
public static readonly RoutedEvent PageUpdatedEvent =
|
||||
EventManager.RegisterRoutedEvent("PageUpdated", RoutingStrategy.Bubble,
|
||||
typeof(EventHandler<FunctionEventArgs<int>>), typeof(Pagination));
|
||||
|
||||
/// <summary>
|
||||
/// 页面更新事件
|
||||
/// </summary>
|
||||
public event EventHandler<FunctionEventArgs<int>> PageUpdated
|
||||
{
|
||||
add => AddHandler(PageUpdatedEvent, value);
|
||||
remove => RemoveHandler(PageUpdatedEvent, value);
|
||||
}
|
||||
|
||||
#endregion Public Events
|
||||
|
||||
public Pagination()
|
||||
{
|
||||
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));
|
||||
|
||||
OnAutoHidingChanged(AutoHiding);
|
||||
Update();
|
||||
}
|
||||
|
||||
#region Public Properties
|
||||
|
||||
#region MaxPageCount
|
||||
|
||||
/// <summary>
|
||||
/// 最大页数
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty MaxPageCountProperty = DependencyProperty.Register(
|
||||
"MaxPageCount", typeof(int), typeof(Pagination), new PropertyMetadata(ValueBoxes.Int1Box, OnMaxPageCountChanged, CoerceMaxPageCount), ValidateHelper.IsInRangeOfPosIntIncludeZero);
|
||||
|
||||
private static object CoerceMaxPageCount(DependencyObject d, object basevalue)
|
||||
{
|
||||
var intValue = (int) basevalue;
|
||||
return intValue < 1 ? 1 : intValue;
|
||||
}
|
||||
|
||||
private static void OnMaxPageCountChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if (d is Pagination pagination)
|
||||
{
|
||||
if (pagination.PageIndex > pagination.MaxPageCount)
|
||||
{
|
||||
pagination.PageIndex = pagination.MaxPageCount;
|
||||
}
|
||||
|
||||
pagination.CoerceValue(PageIndexProperty);
|
||||
pagination.OnAutoHidingChanged(pagination.AutoHiding);
|
||||
pagination.Update();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 最大页数
|
||||
/// </summary>
|
||||
public int MaxPageCount
|
||||
{
|
||||
get => (int) GetValue(MaxPageCountProperty);
|
||||
set => SetValue(MaxPageCountProperty, value);
|
||||
}
|
||||
|
||||
#endregion MaxPageCount
|
||||
|
||||
#region DataCountPerPage
|
||||
|
||||
/// <summary>
|
||||
/// 每页的数据量
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty DataCountPerPageProperty = DependencyProperty.Register(
|
||||
"DataCountPerPage", typeof(int), typeof(Pagination), new PropertyMetadata(20, OnDataCountPerPageChanged),
|
||||
ValidateHelper.IsInRangeOfPosInt);
|
||||
|
||||
private static void OnDataCountPerPageChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if (d is Pagination pagination)
|
||||
{
|
||||
pagination.Update();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 每页的数据量
|
||||
/// </summary>
|
||||
public int DataCountPerPage
|
||||
{
|
||||
get => (int) GetValue(DataCountPerPageProperty);
|
||||
set => SetValue(DataCountPerPageProperty, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region PageIndex
|
||||
|
||||
/// <summary>
|
||||
/// 当前页
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty PageIndexProperty = DependencyProperty.Register(
|
||||
"PageIndex", typeof(int), typeof(Pagination), new PropertyMetadata(ValueBoxes.Int1Box, OnPageIndexChanged, CoercePageIndex), ValidateHelper.IsInRangeOfPosIntIncludeZero);
|
||||
|
||||
private static object CoercePageIndex(DependencyObject d, object basevalue)
|
||||
{
|
||||
if (d is not Pagination pagination) return 1;
|
||||
|
||||
var intValue = (int) basevalue;
|
||||
return intValue < 1
|
||||
? 1
|
||||
: intValue > pagination.MaxPageCount
|
||||
? pagination.MaxPageCount
|
||||
: intValue;
|
||||
}
|
||||
|
||||
private static void OnPageIndexChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if (d is Pagination pagination && e.NewValue is int value)
|
||||
{
|
||||
pagination.Update();
|
||||
pagination.RaiseEvent(new FunctionEventArgs<int>(PageUpdatedEvent, pagination)
|
||||
{
|
||||
Info = value
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当前页
|
||||
/// </summary>
|
||||
public int PageIndex
|
||||
{
|
||||
get => (int) GetValue(PageIndexProperty);
|
||||
set => SetValue(PageIndexProperty, value);
|
||||
}
|
||||
|
||||
#endregion PageIndex
|
||||
|
||||
#region MaxPageInterval
|
||||
|
||||
/// <summary>
|
||||
/// 表示当前选中的按钮距离左右两个方向按钮的最大间隔(4表示间隔4个按钮,如果超过则用省略号表示)
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty MaxPageIntervalProperty = DependencyProperty.Register(
|
||||
"MaxPageInterval", typeof(int), typeof(Pagination), new PropertyMetadata(3, OnMaxPageIntervalChanged), ValidateHelper.IsInRangeOfPosIntIncludeZero);
|
||||
|
||||
private static void OnMaxPageIntervalChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if (d is Pagination pagination)
|
||||
{
|
||||
pagination.Update();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 表示当前选中的按钮距离左右两个方向按钮的最大间隔(4表示间隔4个按钮,如果超过则用省略号表示)
|
||||
/// </summary>
|
||||
public int MaxPageInterval
|
||||
{
|
||||
get => (int) GetValue(MaxPageIntervalProperty);
|
||||
set => SetValue(MaxPageIntervalProperty, value);
|
||||
}
|
||||
|
||||
#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
|
||||
|
||||
#region AutoHiding
|
||||
|
||||
public static readonly DependencyProperty AutoHidingProperty = DependencyProperty.Register(
|
||||
"AutoHiding", typeof(bool), typeof(Pagination), new PropertyMetadata(ValueBoxes.TrueBox, OnAutoHidingChanged));
|
||||
|
||||
private static void OnAutoHidingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if (d is Pagination pagination)
|
||||
{
|
||||
pagination.OnAutoHidingChanged((bool) e.NewValue);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnAutoHidingChanged(bool newValue) => this.Show(!newValue || MaxPageCount > 1);
|
||||
|
||||
public bool AutoHiding
|
||||
{
|
||||
get => (bool) GetValue(AutoHidingProperty);
|
||||
set => SetValue(AutoHidingProperty, ValueBoxes.BooleanBox(value));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
public override void OnApplyTemplate()
|
||||
{
|
||||
_appliedTemplate = false;
|
||||
base.OnApplyTemplate();
|
||||
|
||||
_buttonLeft = GetTemplateChild(ElementButtonLeft) as Button;
|
||||
_buttonRight = GetTemplateChild(ElementButtonRight) as Button;
|
||||
_buttonFirst = GetTemplateChild(ElementButtonFirst) as RadioButton;
|
||||
_moreLeft = GetTemplateChild(ElementMoreLeft) as FrameworkElement;
|
||||
_panelMain = GetTemplateChild(ElementPanelMain) as Panel;
|
||||
_moreRight = GetTemplateChild(ElementMoreRight) as FrameworkElement;
|
||||
_buttonLast = GetTemplateChild(ElementButtonLast) as RadioButton;
|
||||
_jumpNumericUpDown = GetTemplateChild(ElementJump) as NumericUpDown;
|
||||
|
||||
CheckNull();
|
||||
|
||||
_appliedTemplate = true;
|
||||
Update();
|
||||
}
|
||||
|
||||
#endregion Public Methods
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private void CheckNull()
|
||||
{
|
||||
if (_buttonLeft == null || _buttonRight == null || _buttonFirst == null ||
|
||||
_moreLeft == null || _panelMain == null || _moreRight == null ||
|
||||
_buttonLast == null) throw new Exception();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新
|
||||
/// </summary>
|
||||
private void Update()
|
||||
{
|
||||
if (!_appliedTemplate) return;
|
||||
_buttonLeft.IsEnabled = PageIndex > 1;
|
||||
_buttonRight.IsEnabled = PageIndex < MaxPageCount;
|
||||
if (MaxPageInterval == 0)
|
||||
{
|
||||
_buttonFirst.Collapse();
|
||||
_buttonLast.Collapse();
|
||||
_moreLeft.Collapse();
|
||||
_moreRight.Collapse();
|
||||
_panelMain.Children.Clear();
|
||||
var selectButton = CreateButton(PageIndex);
|
||||
_panelMain.Children.Add(selectButton);
|
||||
selectButton.IsChecked = true;
|
||||
return;
|
||||
}
|
||||
_buttonFirst.Show();
|
||||
_buttonLast.Show();
|
||||
_moreLeft.Show();
|
||||
_moreRight.Show();
|
||||
|
||||
//更新最后一页
|
||||
if (MaxPageCount == 1)
|
||||
{
|
||||
_buttonLast.Collapse();
|
||||
}
|
||||
else
|
||||
{
|
||||
_buttonLast.Show();
|
||||
_buttonLast.Content = MaxPageCount.ToString();
|
||||
}
|
||||
|
||||
//更新省略号
|
||||
var right = MaxPageCount - PageIndex;
|
||||
var left = PageIndex - 1;
|
||||
_moreRight.Show(right > MaxPageInterval);
|
||||
_moreLeft.Show(left > MaxPageInterval);
|
||||
|
||||
//更新中间部分
|
||||
_panelMain.Children.Clear();
|
||||
if (PageIndex > 1 && PageIndex < MaxPageCount)
|
||||
{
|
||||
var selectButton = CreateButton(PageIndex);
|
||||
_panelMain.Children.Add(selectButton);
|
||||
selectButton.IsChecked = true;
|
||||
}
|
||||
else if (PageIndex == 1)
|
||||
{
|
||||
_buttonFirst.IsChecked = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
_buttonLast.IsChecked = true;
|
||||
}
|
||||
|
||||
var sub = PageIndex;
|
||||
for (var i = 0; i < MaxPageInterval - 1; i++)
|
||||
{
|
||||
if (--sub > 1)
|
||||
{
|
||||
_panelMain.Children.Insert(0, CreateButton(sub));
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
var add = PageIndex;
|
||||
for (var i = 0; i < MaxPageInterval - 1; i++)
|
||||
{
|
||||
if (++add < MaxPageCount)
|
||||
{
|
||||
_panelMain.Children.Add(CreateButton(add));
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ButtonPrev_OnClick(object sender, RoutedEventArgs e) => PageIndex--;
|
||||
|
||||
private void ButtonNext_OnClick(object sender, RoutedEventArgs e) => PageIndex++;
|
||||
|
||||
private RadioButton CreateButton(int page)
|
||||
{
|
||||
return new()
|
||||
{
|
||||
Style = ResourceHelper.GetResourceInternal<Style>(ResourceToken.PaginationButtonStyle),
|
||||
Content = page.ToString()
|
||||
};
|
||||
}
|
||||
|
||||
private void ToggleButton_OnChecked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (e.OriginalSource is not RadioButton button) return;
|
||||
if (button.IsChecked == false) return;
|
||||
PageIndex = int.Parse(button.Content.ToString());
|
||||
}
|
||||
|
||||
#endregion Private Methods
|
||||
add => AddHandler(PageUpdatedEvent, value);
|
||||
remove => RemoveHandler(PageUpdatedEvent, value);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Public Events
|
||||
|
||||
public Pagination()
|
||||
{
|
||||
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));
|
||||
|
||||
OnAutoHidingChanged(AutoHiding);
|
||||
Update();
|
||||
}
|
||||
|
||||
#region Public Properties
|
||||
|
||||
#region MaxPageCount
|
||||
|
||||
/// <summary>
|
||||
/// 最大页数
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty MaxPageCountProperty = DependencyProperty.Register(
|
||||
"MaxPageCount", typeof(int), typeof(Pagination), new PropertyMetadata(ValueBoxes.Int1Box, OnMaxPageCountChanged, CoerceMaxPageCount), ValidateHelper.IsInRangeOfPosIntIncludeZero);
|
||||
|
||||
private static object CoerceMaxPageCount(DependencyObject d, object basevalue)
|
||||
{
|
||||
var intValue = (int) basevalue;
|
||||
return intValue < 1 ? 1 : intValue;
|
||||
}
|
||||
|
||||
private static void OnMaxPageCountChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if (d is Pagination pagination)
|
||||
{
|
||||
if (pagination.PageIndex > pagination.MaxPageCount)
|
||||
{
|
||||
pagination.PageIndex = pagination.MaxPageCount;
|
||||
}
|
||||
|
||||
pagination.CoerceValue(PageIndexProperty);
|
||||
pagination.OnAutoHidingChanged(pagination.AutoHiding);
|
||||
pagination.Update();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 最大页数
|
||||
/// </summary>
|
||||
public int MaxPageCount
|
||||
{
|
||||
get => (int) GetValue(MaxPageCountProperty);
|
||||
set => SetValue(MaxPageCountProperty, value);
|
||||
}
|
||||
|
||||
#endregion MaxPageCount
|
||||
|
||||
#region DataCountPerPage
|
||||
|
||||
/// <summary>
|
||||
/// 每页的数据量
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty DataCountPerPageProperty = DependencyProperty.Register(
|
||||
"DataCountPerPage", typeof(int), typeof(Pagination), new PropertyMetadata(20, OnDataCountPerPageChanged),
|
||||
ValidateHelper.IsInRangeOfPosInt);
|
||||
|
||||
private static void OnDataCountPerPageChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if (d is Pagination pagination)
|
||||
{
|
||||
pagination.Update();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 每页的数据量
|
||||
/// </summary>
|
||||
public int DataCountPerPage
|
||||
{
|
||||
get => (int) GetValue(DataCountPerPageProperty);
|
||||
set => SetValue(DataCountPerPageProperty, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region PageIndex
|
||||
|
||||
/// <summary>
|
||||
/// 当前页
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty PageIndexProperty = DependencyProperty.Register(
|
||||
"PageIndex", typeof(int), typeof(Pagination), new PropertyMetadata(ValueBoxes.Int1Box, OnPageIndexChanged, CoercePageIndex), ValidateHelper.IsInRangeOfPosIntIncludeZero);
|
||||
|
||||
private static object CoercePageIndex(DependencyObject d, object basevalue)
|
||||
{
|
||||
if (d is not Pagination pagination) return 1;
|
||||
|
||||
var intValue = (int) basevalue;
|
||||
return intValue < 1
|
||||
? 1
|
||||
: intValue > pagination.MaxPageCount
|
||||
? pagination.MaxPageCount
|
||||
: intValue;
|
||||
}
|
||||
|
||||
private static void OnPageIndexChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if (d is Pagination pagination && e.NewValue is int value)
|
||||
{
|
||||
pagination.Update();
|
||||
pagination.RaiseEvent(new FunctionEventArgs<int>(PageUpdatedEvent, pagination)
|
||||
{
|
||||
Info = value
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当前页
|
||||
/// </summary>
|
||||
public int PageIndex
|
||||
{
|
||||
get => (int) GetValue(PageIndexProperty);
|
||||
set => SetValue(PageIndexProperty, value);
|
||||
}
|
||||
|
||||
#endregion PageIndex
|
||||
|
||||
#region MaxPageInterval
|
||||
|
||||
/// <summary>
|
||||
/// 表示当前选中的按钮距离左右两个方向按钮的最大间隔(4表示间隔4个按钮,如果超过则用省略号表示)
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty MaxPageIntervalProperty = DependencyProperty.Register(
|
||||
"MaxPageInterval", typeof(int), typeof(Pagination), new PropertyMetadata(3, OnMaxPageIntervalChanged), ValidateHelper.IsInRangeOfPosIntIncludeZero);
|
||||
|
||||
private static void OnMaxPageIntervalChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if (d is Pagination pagination)
|
||||
{
|
||||
pagination.Update();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 表示当前选中的按钮距离左右两个方向按钮的最大间隔(4表示间隔4个按钮,如果超过则用省略号表示)
|
||||
/// </summary>
|
||||
public int MaxPageInterval
|
||||
{
|
||||
get => (int) GetValue(MaxPageIntervalProperty);
|
||||
set => SetValue(MaxPageIntervalProperty, value);
|
||||
}
|
||||
|
||||
#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
|
||||
|
||||
#region AutoHiding
|
||||
|
||||
public static readonly DependencyProperty AutoHidingProperty = DependencyProperty.Register(
|
||||
"AutoHiding", typeof(bool), typeof(Pagination), new PropertyMetadata(ValueBoxes.TrueBox, OnAutoHidingChanged));
|
||||
|
||||
private static void OnAutoHidingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if (d is Pagination pagination)
|
||||
{
|
||||
pagination.OnAutoHidingChanged((bool) e.NewValue);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnAutoHidingChanged(bool newValue) => this.Show(!newValue || MaxPageCount > 1);
|
||||
|
||||
public bool AutoHiding
|
||||
{
|
||||
get => (bool) GetValue(AutoHidingProperty);
|
||||
set => SetValue(AutoHidingProperty, ValueBoxes.BooleanBox(value));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
|
||||
public override void OnApplyTemplate()
|
||||
{
|
||||
_appliedTemplate = false;
|
||||
base.OnApplyTemplate();
|
||||
|
||||
_buttonLeft = GetTemplateChild(ElementButtonLeft) as Button;
|
||||
_buttonRight = GetTemplateChild(ElementButtonRight) as Button;
|
||||
_buttonFirst = GetTemplateChild(ElementButtonFirst) as RadioButton;
|
||||
_moreLeft = GetTemplateChild(ElementMoreLeft) as FrameworkElement;
|
||||
_panelMain = GetTemplateChild(ElementPanelMain) as Panel;
|
||||
_moreRight = GetTemplateChild(ElementMoreRight) as FrameworkElement;
|
||||
_buttonLast = GetTemplateChild(ElementButtonLast) as RadioButton;
|
||||
_jumpNumericUpDown = GetTemplateChild(ElementJump) as NumericUpDown;
|
||||
|
||||
CheckNull();
|
||||
|
||||
_appliedTemplate = true;
|
||||
Update();
|
||||
}
|
||||
|
||||
#endregion Public Methods
|
||||
|
||||
#region Private Methods
|
||||
|
||||
private void CheckNull()
|
||||
{
|
||||
if (_buttonLeft == null || _buttonRight == null || _buttonFirst == null ||
|
||||
_moreLeft == null || _panelMain == null || _moreRight == null ||
|
||||
_buttonLast == null) throw new Exception();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新
|
||||
/// </summary>
|
||||
private void Update()
|
||||
{
|
||||
if (!_appliedTemplate) return;
|
||||
_buttonLeft.IsEnabled = PageIndex > 1;
|
||||
_buttonRight.IsEnabled = PageIndex < MaxPageCount;
|
||||
if (MaxPageInterval == 0)
|
||||
{
|
||||
_buttonFirst.Collapse();
|
||||
_buttonLast.Collapse();
|
||||
_moreLeft.Collapse();
|
||||
_moreRight.Collapse();
|
||||
_panelMain.Children.Clear();
|
||||
var selectButton = CreateButton(PageIndex);
|
||||
_panelMain.Children.Add(selectButton);
|
||||
selectButton.IsChecked = true;
|
||||
return;
|
||||
}
|
||||
_buttonFirst.Show();
|
||||
_buttonLast.Show();
|
||||
_moreLeft.Show();
|
||||
_moreRight.Show();
|
||||
|
||||
//更新最后一页
|
||||
if (MaxPageCount == 1)
|
||||
{
|
||||
_buttonLast.Collapse();
|
||||
}
|
||||
else
|
||||
{
|
||||
_buttonLast.Show();
|
||||
_buttonLast.Content = MaxPageCount.ToString();
|
||||
}
|
||||
|
||||
//更新省略号
|
||||
var right = MaxPageCount - PageIndex;
|
||||
var left = PageIndex - 1;
|
||||
_moreRight.Show(right > MaxPageInterval);
|
||||
_moreLeft.Show(left > MaxPageInterval);
|
||||
|
||||
//更新中间部分
|
||||
_panelMain.Children.Clear();
|
||||
if (PageIndex > 1 && PageIndex < MaxPageCount)
|
||||
{
|
||||
var selectButton = CreateButton(PageIndex);
|
||||
_panelMain.Children.Add(selectButton);
|
||||
selectButton.IsChecked = true;
|
||||
}
|
||||
else if (PageIndex == 1)
|
||||
{
|
||||
_buttonFirst.IsChecked = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
_buttonLast.IsChecked = true;
|
||||
}
|
||||
|
||||
var sub = PageIndex;
|
||||
for (var i = 0; i < MaxPageInterval - 1; i++)
|
||||
{
|
||||
if (--sub > 1)
|
||||
{
|
||||
_panelMain.Children.Insert(0, CreateButton(sub));
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
var add = PageIndex;
|
||||
for (var i = 0; i < MaxPageInterval - 1; i++)
|
||||
{
|
||||
if (++add < MaxPageCount)
|
||||
{
|
||||
_panelMain.Children.Add(CreateButton(add));
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ButtonPrev_OnClick(object sender, RoutedEventArgs e) => PageIndex--;
|
||||
|
||||
private void ButtonNext_OnClick(object sender, RoutedEventArgs e) => PageIndex++;
|
||||
|
||||
private RadioButton CreateButton(int page)
|
||||
{
|
||||
return new()
|
||||
{
|
||||
Style = ResourceHelper.GetResourceInternal<Style>(ResourceToken.PaginationButtonStyle),
|
||||
Content = page.ToString()
|
||||
};
|
||||
}
|
||||
|
||||
private void ToggleButton_OnChecked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (e.OriginalSource is not RadioButton button) return;
|
||||
if (button.IsChecked == false) return;
|
||||
PageIndex = int.Parse(button.Content.ToString());
|
||||
}
|
||||
|
||||
#endregion Private Methods
|
||||
}
|
||||
@@ -7,323 +7,322 @@ using System.Windows.Input;
|
||||
using HandyControl.Data;
|
||||
using HandyControl.Data.Enum;
|
||||
|
||||
namespace HandyControl.Controls
|
||||
namespace HandyControl.Controls;
|
||||
|
||||
public class Poptip : AdornerElement
|
||||
{
|
||||
public class Poptip : AdornerElement
|
||||
private readonly Popup _popup;
|
||||
|
||||
public Poptip()
|
||||
{
|
||||
private readonly Popup _popup;
|
||||
|
||||
public Poptip()
|
||||
_popup = new Popup
|
||||
{
|
||||
_popup = new Popup
|
||||
{
|
||||
AllowsTransparency = true,
|
||||
Child = this,
|
||||
Placement = PlacementMode.Relative
|
||||
};
|
||||
AllowsTransparency = true,
|
||||
Child = this,
|
||||
Placement = PlacementMode.Relative
|
||||
};
|
||||
|
||||
_popup.SetBinding(DataContextProperty, new Binding(DataContextProperty.Name) { Source = this });
|
||||
}
|
||||
_popup.SetBinding(DataContextProperty, new Binding(DataContextProperty.Name) { Source = this });
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty HitModeProperty = DependencyProperty.RegisterAttached(
|
||||
"HitMode", typeof(HitMode), typeof(Poptip), new PropertyMetadata(HitMode.Hover));
|
||||
public static readonly DependencyProperty HitModeProperty = DependencyProperty.RegisterAttached(
|
||||
"HitMode", typeof(HitMode), typeof(Poptip), new PropertyMetadata(HitMode.Hover));
|
||||
|
||||
public static void SetHitMode(DependencyObject element, HitMode value)
|
||||
=> element.SetValue(HitModeProperty, value);
|
||||
public static void SetHitMode(DependencyObject element, HitMode value)
|
||||
=> element.SetValue(HitModeProperty, value);
|
||||
|
||||
public static HitMode GetHitMode(DependencyObject element)
|
||||
=> (HitMode) element.GetValue(HitModeProperty);
|
||||
public static HitMode GetHitMode(DependencyObject element)
|
||||
=> (HitMode) element.GetValue(HitModeProperty);
|
||||
|
||||
public HitMode HitMode
|
||||
public HitMode HitMode
|
||||
{
|
||||
get => (HitMode) GetValue(HitModeProperty);
|
||||
set => SetValue(HitModeProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ContentProperty = DependencyProperty.RegisterAttached(
|
||||
"Content", typeof(object), typeof(Poptip), new PropertyMetadata(default, OnContentChanged));
|
||||
|
||||
private static void OnContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if (d is Poptip) return;
|
||||
if (GetInstance(d) == null)
|
||||
{
|
||||
get => (HitMode) GetValue(HitModeProperty);
|
||||
set => SetValue(HitModeProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ContentProperty = DependencyProperty.RegisterAttached(
|
||||
"Content", typeof(object), typeof(Poptip), new PropertyMetadata(default, OnContentChanged));
|
||||
|
||||
private static void OnContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if (d is Poptip) return;
|
||||
if (GetInstance(d) == null)
|
||||
{
|
||||
SetInstance(d, Default);
|
||||
SetIsInstance(d, false);
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetContent(DependencyObject element, object value)
|
||||
=> element.SetValue(ContentProperty, value);
|
||||
|
||||
public static object GetContent(DependencyObject element)
|
||||
=> element.GetValue(ContentProperty);
|
||||
|
||||
public object Content
|
||||
{
|
||||
get => GetValue(ContentProperty);
|
||||
set => SetValue(ContentProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ContentTemplateProperty = DependencyProperty.Register(
|
||||
"ContentTemplate", typeof(DataTemplate), typeof(Poptip), new PropertyMetadata(default(DataTemplate)));
|
||||
|
||||
public DataTemplate ContentTemplate
|
||||
{
|
||||
get => (DataTemplate) GetValue(ContentTemplateProperty);
|
||||
set => SetValue(ContentTemplateProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ContentStringFormatProperty = DependencyProperty.Register(
|
||||
"ContentStringFormat", typeof(string), typeof(Poptip), new PropertyMetadata(default(string)));
|
||||
|
||||
public string ContentStringFormat
|
||||
{
|
||||
get => (string) GetValue(ContentStringFormatProperty);
|
||||
set => SetValue(ContentStringFormatProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ContentTemplateSelectorProperty = DependencyProperty.Register(
|
||||
"ContentTemplateSelector", typeof(DataTemplateSelector), typeof(Poptip), new PropertyMetadata(default(DataTemplateSelector)));
|
||||
|
||||
public DataTemplateSelector ContentTemplateSelector
|
||||
{
|
||||
get => (DataTemplateSelector) GetValue(ContentTemplateSelectorProperty);
|
||||
set => SetValue(ContentTemplateSelectorProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty VerticalOffsetProperty = DependencyProperty.RegisterAttached(
|
||||
"VerticalOffset", typeof(double), typeof(Poptip), new PropertyMetadata(ValueBoxes.Double0Box));
|
||||
|
||||
public static void SetVerticalOffset(DependencyObject element, double value)
|
||||
{
|
||||
element.SetValue(VerticalOffsetProperty, value);
|
||||
}
|
||||
|
||||
public static double GetVerticalOffset(DependencyObject element)
|
||||
{
|
||||
return (double) element.GetValue(VerticalOffsetProperty);
|
||||
}
|
||||
|
||||
public double VerticalOffset
|
||||
{
|
||||
get => (double) GetValue(VerticalOffsetProperty);
|
||||
set => SetValue(VerticalOffsetProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty HorizontalOffsetProperty = DependencyProperty.RegisterAttached(
|
||||
"HorizontalOffset", typeof(double), typeof(Poptip), new PropertyMetadata(ValueBoxes.Double0Box));
|
||||
|
||||
public static void SetHorizontalOffset(DependencyObject element, double value)
|
||||
{
|
||||
element.SetValue(HorizontalOffsetProperty, value);
|
||||
}
|
||||
|
||||
public static double GetHorizontalOffset(DependencyObject element)
|
||||
{
|
||||
return (double) element.GetValue(HorizontalOffsetProperty);
|
||||
}
|
||||
|
||||
public double HorizontalOffset
|
||||
{
|
||||
get => (double) GetValue(HorizontalOffsetProperty);
|
||||
set => SetValue(HorizontalOffsetProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty PlacementTypeProperty = DependencyProperty.RegisterAttached(
|
||||
"PlacementType", typeof(PlacementType), typeof(Poptip), new PropertyMetadata(PlacementType.Top));
|
||||
|
||||
public static void SetPlacement(DependencyObject element, PlacementType value)
|
||||
=> element.SetValue(PlacementTypeProperty, value);
|
||||
|
||||
public static PlacementType GetPlacement(DependencyObject element)
|
||||
=> (PlacementType) element.GetValue(PlacementTypeProperty);
|
||||
|
||||
public PlacementType PlacementType
|
||||
{
|
||||
get => (PlacementType) GetValue(PlacementTypeProperty);
|
||||
set => SetValue(PlacementTypeProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty IsOpenProperty = DependencyProperty.RegisterAttached(
|
||||
"IsOpen", typeof(bool), typeof(Poptip), new PropertyMetadata(ValueBoxes.FalseBox, OnIsOpenChanged));
|
||||
|
||||
private static void OnIsOpenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if (d is Poptip poptip)
|
||||
{
|
||||
poptip.SwitchPoptip((bool) e.NewValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
((Poptip) GetInstance(d))?.SwitchPoptip((bool) e.NewValue);
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetIsOpen(DependencyObject element, bool value)
|
||||
=> element.SetValue(IsOpenProperty, ValueBoxes.BooleanBox(value));
|
||||
|
||||
public static bool GetIsOpen(DependencyObject element)
|
||||
=> (bool) element.GetValue(IsOpenProperty);
|
||||
|
||||
public bool IsOpen
|
||||
{
|
||||
get => (bool) GetValue(IsOpenProperty);
|
||||
set => SetValue(IsOpenProperty, ValueBoxes.BooleanBox(value));
|
||||
}
|
||||
|
||||
public static Poptip Default => new();
|
||||
|
||||
protected sealed override void OnTargetChanged(FrameworkElement element, bool isNew)
|
||||
{
|
||||
base.OnTargetChanged(element, isNew);
|
||||
|
||||
if (element == null) return;
|
||||
|
||||
if (!isNew)
|
||||
{
|
||||
element.MouseEnter -= Element_MouseEnter;
|
||||
element.MouseLeave -= Element_MouseLeave;
|
||||
element.GotFocus -= Element_GotFocus;
|
||||
element.LostFocus -= Element_LostFocus;
|
||||
ElementTarget = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
element.MouseEnter += Element_MouseEnter;
|
||||
element.MouseLeave += Element_MouseLeave;
|
||||
element.GotFocus += Element_GotFocus;
|
||||
element.LostFocus += Element_LostFocus;
|
||||
ElementTarget = element;
|
||||
_popup.PlacementTarget = ElementTarget;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Dispose() => SwitchPoptip(false);
|
||||
|
||||
private void UpdateLocation()
|
||||
{
|
||||
var targetWidth = Target.RenderSize.Width;
|
||||
var targetHeight = Target.RenderSize.Height;
|
||||
|
||||
Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
|
||||
var size = DesiredSize;
|
||||
|
||||
var width = size.Width;
|
||||
var height = size.Height;
|
||||
|
||||
var offsetX = .0;
|
||||
var offsetY = .0;
|
||||
|
||||
var poptip = (Poptip) GetInstance(Target);
|
||||
var popupPlacement = poptip.PlacementType;
|
||||
var popupOffsetX = poptip.HorizontalOffset;
|
||||
var popupOffsetY = poptip.VerticalOffset;
|
||||
|
||||
switch (popupPlacement)
|
||||
{
|
||||
case PlacementType.LeftTop:
|
||||
break;
|
||||
case PlacementType.Left:
|
||||
offsetY = -(height - targetHeight) * 0.5;
|
||||
break;
|
||||
case PlacementType.LeftBottom:
|
||||
offsetY = -(height - targetHeight);
|
||||
break;
|
||||
case PlacementType.TopLeft:
|
||||
offsetX = width;
|
||||
offsetY = -height;
|
||||
break;
|
||||
case PlacementType.Top:
|
||||
offsetX = (width + targetWidth) * 0.5;
|
||||
offsetY = -height;
|
||||
break;
|
||||
case PlacementType.TopRight:
|
||||
offsetX = targetWidth;
|
||||
offsetY = -height;
|
||||
break;
|
||||
case PlacementType.RightTop:
|
||||
offsetX = width + targetWidth;
|
||||
break;
|
||||
case PlacementType.Right:
|
||||
offsetX = width + targetWidth;
|
||||
offsetY = -(height - targetHeight) * 0.5;
|
||||
break;
|
||||
case PlacementType.RightBottom:
|
||||
offsetX = width + targetWidth;
|
||||
offsetY = -(height - targetHeight);
|
||||
break;
|
||||
case PlacementType.BottomLeft:
|
||||
offsetX = width;
|
||||
offsetY = targetHeight;
|
||||
break;
|
||||
case PlacementType.Bottom:
|
||||
offsetX = (width + targetWidth) * 0.5;
|
||||
offsetY = targetHeight;
|
||||
break;
|
||||
case PlacementType.BottomRight:
|
||||
offsetX = targetWidth;
|
||||
offsetY = targetHeight;
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
|
||||
_popup.HorizontalOffset = offsetX + popupOffsetX;
|
||||
_popup.VerticalOffset = offsetY + popupOffsetY;
|
||||
}
|
||||
|
||||
private void SwitchPoptip(bool isShow)
|
||||
{
|
||||
if (isShow)
|
||||
{
|
||||
if (!GetIsInstance(Target))
|
||||
{
|
||||
SetCurrentValue(ContentProperty, GetContent(Target));
|
||||
SetCurrentValue(PlacementTypeProperty, GetPlacement(Target));
|
||||
SetCurrentValue(HitModeProperty, GetHitMode(Target));
|
||||
SetCurrentValue(HorizontalOffsetProperty, GetHorizontalOffset(Target));
|
||||
SetCurrentValue(VerticalOffsetProperty, GetVerticalOffset(Target));
|
||||
SetCurrentValue(IsOpenProperty, GetIsOpen(Target));
|
||||
}
|
||||
|
||||
_popup.PlacementTarget = Target;
|
||||
UpdateLocation();
|
||||
}
|
||||
_popup.IsOpen = isShow;
|
||||
Target.SetCurrentValue(IsOpenProperty, isShow);
|
||||
}
|
||||
|
||||
private void Element_MouseEnter(object sender, MouseEventArgs e)
|
||||
{
|
||||
var hitMode = GetIsInstance(Target) ? HitMode : GetHitMode(Target);
|
||||
if (hitMode != HitMode.Hover) return;
|
||||
|
||||
SwitchPoptip(true);
|
||||
}
|
||||
|
||||
private void Element_MouseLeave(object sender, MouseEventArgs e)
|
||||
{
|
||||
var hitMode = GetIsInstance(Target) ? HitMode : GetHitMode(Target);
|
||||
if (hitMode != HitMode.Hover) return;
|
||||
|
||||
SwitchPoptip(false);
|
||||
}
|
||||
|
||||
private void Element_GotFocus(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var hitMode = GetIsInstance(Target) ? HitMode : GetHitMode(Target);
|
||||
if (hitMode != HitMode.Focus) return;
|
||||
|
||||
SwitchPoptip(true);
|
||||
}
|
||||
|
||||
private void Element_LostFocus(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var hitMode = GetIsInstance(Target) ? HitMode : GetHitMode(Target);
|
||||
if (hitMode != HitMode.Focus) return;
|
||||
|
||||
SwitchPoptip(false);
|
||||
SetInstance(d, Default);
|
||||
SetIsInstance(d, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetContent(DependencyObject element, object value)
|
||||
=> element.SetValue(ContentProperty, value);
|
||||
|
||||
public static object GetContent(DependencyObject element)
|
||||
=> element.GetValue(ContentProperty);
|
||||
|
||||
public object Content
|
||||
{
|
||||
get => GetValue(ContentProperty);
|
||||
set => SetValue(ContentProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ContentTemplateProperty = DependencyProperty.Register(
|
||||
"ContentTemplate", typeof(DataTemplate), typeof(Poptip), new PropertyMetadata(default(DataTemplate)));
|
||||
|
||||
public DataTemplate ContentTemplate
|
||||
{
|
||||
get => (DataTemplate) GetValue(ContentTemplateProperty);
|
||||
set => SetValue(ContentTemplateProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ContentStringFormatProperty = DependencyProperty.Register(
|
||||
"ContentStringFormat", typeof(string), typeof(Poptip), new PropertyMetadata(default(string)));
|
||||
|
||||
public string ContentStringFormat
|
||||
{
|
||||
get => (string) GetValue(ContentStringFormatProperty);
|
||||
set => SetValue(ContentStringFormatProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ContentTemplateSelectorProperty = DependencyProperty.Register(
|
||||
"ContentTemplateSelector", typeof(DataTemplateSelector), typeof(Poptip), new PropertyMetadata(default(DataTemplateSelector)));
|
||||
|
||||
public DataTemplateSelector ContentTemplateSelector
|
||||
{
|
||||
get => (DataTemplateSelector) GetValue(ContentTemplateSelectorProperty);
|
||||
set => SetValue(ContentTemplateSelectorProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty VerticalOffsetProperty = DependencyProperty.RegisterAttached(
|
||||
"VerticalOffset", typeof(double), typeof(Poptip), new PropertyMetadata(ValueBoxes.Double0Box));
|
||||
|
||||
public static void SetVerticalOffset(DependencyObject element, double value)
|
||||
{
|
||||
element.SetValue(VerticalOffsetProperty, value);
|
||||
}
|
||||
|
||||
public static double GetVerticalOffset(DependencyObject element)
|
||||
{
|
||||
return (double) element.GetValue(VerticalOffsetProperty);
|
||||
}
|
||||
|
||||
public double VerticalOffset
|
||||
{
|
||||
get => (double) GetValue(VerticalOffsetProperty);
|
||||
set => SetValue(VerticalOffsetProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty HorizontalOffsetProperty = DependencyProperty.RegisterAttached(
|
||||
"HorizontalOffset", typeof(double), typeof(Poptip), new PropertyMetadata(ValueBoxes.Double0Box));
|
||||
|
||||
public static void SetHorizontalOffset(DependencyObject element, double value)
|
||||
{
|
||||
element.SetValue(HorizontalOffsetProperty, value);
|
||||
}
|
||||
|
||||
public static double GetHorizontalOffset(DependencyObject element)
|
||||
{
|
||||
return (double) element.GetValue(HorizontalOffsetProperty);
|
||||
}
|
||||
|
||||
public double HorizontalOffset
|
||||
{
|
||||
get => (double) GetValue(HorizontalOffsetProperty);
|
||||
set => SetValue(HorizontalOffsetProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty PlacementTypeProperty = DependencyProperty.RegisterAttached(
|
||||
"PlacementType", typeof(PlacementType), typeof(Poptip), new PropertyMetadata(PlacementType.Top));
|
||||
|
||||
public static void SetPlacement(DependencyObject element, PlacementType value)
|
||||
=> element.SetValue(PlacementTypeProperty, value);
|
||||
|
||||
public static PlacementType GetPlacement(DependencyObject element)
|
||||
=> (PlacementType) element.GetValue(PlacementTypeProperty);
|
||||
|
||||
public PlacementType PlacementType
|
||||
{
|
||||
get => (PlacementType) GetValue(PlacementTypeProperty);
|
||||
set => SetValue(PlacementTypeProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty IsOpenProperty = DependencyProperty.RegisterAttached(
|
||||
"IsOpen", typeof(bool), typeof(Poptip), new PropertyMetadata(ValueBoxes.FalseBox, OnIsOpenChanged));
|
||||
|
||||
private static void OnIsOpenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if (d is Poptip poptip)
|
||||
{
|
||||
poptip.SwitchPoptip((bool) e.NewValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
((Poptip) GetInstance(d))?.SwitchPoptip((bool) e.NewValue);
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetIsOpen(DependencyObject element, bool value)
|
||||
=> element.SetValue(IsOpenProperty, ValueBoxes.BooleanBox(value));
|
||||
|
||||
public static bool GetIsOpen(DependencyObject element)
|
||||
=> (bool) element.GetValue(IsOpenProperty);
|
||||
|
||||
public bool IsOpen
|
||||
{
|
||||
get => (bool) GetValue(IsOpenProperty);
|
||||
set => SetValue(IsOpenProperty, ValueBoxes.BooleanBox(value));
|
||||
}
|
||||
|
||||
public static Poptip Default => new();
|
||||
|
||||
protected sealed override void OnTargetChanged(FrameworkElement element, bool isNew)
|
||||
{
|
||||
base.OnTargetChanged(element, isNew);
|
||||
|
||||
if (element == null) return;
|
||||
|
||||
if (!isNew)
|
||||
{
|
||||
element.MouseEnter -= Element_MouseEnter;
|
||||
element.MouseLeave -= Element_MouseLeave;
|
||||
element.GotFocus -= Element_GotFocus;
|
||||
element.LostFocus -= Element_LostFocus;
|
||||
ElementTarget = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
element.MouseEnter += Element_MouseEnter;
|
||||
element.MouseLeave += Element_MouseLeave;
|
||||
element.GotFocus += Element_GotFocus;
|
||||
element.LostFocus += Element_LostFocus;
|
||||
ElementTarget = element;
|
||||
_popup.PlacementTarget = ElementTarget;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Dispose() => SwitchPoptip(false);
|
||||
|
||||
private void UpdateLocation()
|
||||
{
|
||||
var targetWidth = Target.RenderSize.Width;
|
||||
var targetHeight = Target.RenderSize.Height;
|
||||
|
||||
Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
|
||||
var size = DesiredSize;
|
||||
|
||||
var width = size.Width;
|
||||
var height = size.Height;
|
||||
|
||||
var offsetX = .0;
|
||||
var offsetY = .0;
|
||||
|
||||
var poptip = (Poptip) GetInstance(Target);
|
||||
var popupPlacement = poptip.PlacementType;
|
||||
var popupOffsetX = poptip.HorizontalOffset;
|
||||
var popupOffsetY = poptip.VerticalOffset;
|
||||
|
||||
switch (popupPlacement)
|
||||
{
|
||||
case PlacementType.LeftTop:
|
||||
break;
|
||||
case PlacementType.Left:
|
||||
offsetY = -(height - targetHeight) * 0.5;
|
||||
break;
|
||||
case PlacementType.LeftBottom:
|
||||
offsetY = -(height - targetHeight);
|
||||
break;
|
||||
case PlacementType.TopLeft:
|
||||
offsetX = width;
|
||||
offsetY = -height;
|
||||
break;
|
||||
case PlacementType.Top:
|
||||
offsetX = (width + targetWidth) * 0.5;
|
||||
offsetY = -height;
|
||||
break;
|
||||
case PlacementType.TopRight:
|
||||
offsetX = targetWidth;
|
||||
offsetY = -height;
|
||||
break;
|
||||
case PlacementType.RightTop:
|
||||
offsetX = width + targetWidth;
|
||||
break;
|
||||
case PlacementType.Right:
|
||||
offsetX = width + targetWidth;
|
||||
offsetY = -(height - targetHeight) * 0.5;
|
||||
break;
|
||||
case PlacementType.RightBottom:
|
||||
offsetX = width + targetWidth;
|
||||
offsetY = -(height - targetHeight);
|
||||
break;
|
||||
case PlacementType.BottomLeft:
|
||||
offsetX = width;
|
||||
offsetY = targetHeight;
|
||||
break;
|
||||
case PlacementType.Bottom:
|
||||
offsetX = (width + targetWidth) * 0.5;
|
||||
offsetY = targetHeight;
|
||||
break;
|
||||
case PlacementType.BottomRight:
|
||||
offsetX = targetWidth;
|
||||
offsetY = targetHeight;
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
|
||||
_popup.HorizontalOffset = offsetX + popupOffsetX;
|
||||
_popup.VerticalOffset = offsetY + popupOffsetY;
|
||||
}
|
||||
|
||||
private void SwitchPoptip(bool isShow)
|
||||
{
|
||||
if (isShow)
|
||||
{
|
||||
if (!GetIsInstance(Target))
|
||||
{
|
||||
SetCurrentValue(ContentProperty, GetContent(Target));
|
||||
SetCurrentValue(PlacementTypeProperty, GetPlacement(Target));
|
||||
SetCurrentValue(HitModeProperty, GetHitMode(Target));
|
||||
SetCurrentValue(HorizontalOffsetProperty, GetHorizontalOffset(Target));
|
||||
SetCurrentValue(VerticalOffsetProperty, GetVerticalOffset(Target));
|
||||
SetCurrentValue(IsOpenProperty, GetIsOpen(Target));
|
||||
}
|
||||
|
||||
_popup.PlacementTarget = Target;
|
||||
UpdateLocation();
|
||||
}
|
||||
_popup.IsOpen = isShow;
|
||||
Target.SetCurrentValue(IsOpenProperty, isShow);
|
||||
}
|
||||
|
||||
private void Element_MouseEnter(object sender, MouseEventArgs e)
|
||||
{
|
||||
var hitMode = GetIsInstance(Target) ? HitMode : GetHitMode(Target);
|
||||
if (hitMode != HitMode.Hover) return;
|
||||
|
||||
SwitchPoptip(true);
|
||||
}
|
||||
|
||||
private void Element_MouseLeave(object sender, MouseEventArgs e)
|
||||
{
|
||||
var hitMode = GetIsInstance(Target) ? HitMode : GetHitMode(Target);
|
||||
if (hitMode != HitMode.Hover) return;
|
||||
|
||||
SwitchPoptip(false);
|
||||
}
|
||||
|
||||
private void Element_GotFocus(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var hitMode = GetIsInstance(Target) ? HitMode : GetHitMode(Target);
|
||||
if (hitMode != HitMode.Focus) return;
|
||||
|
||||
SwitchPoptip(true);
|
||||
}
|
||||
|
||||
private void Element_LostFocus(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var hitMode = GetIsInstance(Target) ? HitMode : GetHitMode(Target);
|
||||
if (hitMode != HitMode.Focus) return;
|
||||
|
||||
SwitchPoptip(false);
|
||||
}
|
||||
}
|
||||
@@ -7,206 +7,205 @@ using System.Windows.Media.Animation;
|
||||
using HandyControl.Data;
|
||||
using HandyControl.Tools;
|
||||
|
||||
namespace HandyControl.Controls
|
||||
namespace HandyControl.Controls;
|
||||
|
||||
public class ScrollViewer : System.Windows.Controls.ScrollViewer
|
||||
{
|
||||
public class ScrollViewer : System.Windows.Controls.ScrollViewer
|
||||
private double _totalVerticalOffset;
|
||||
|
||||
private double _totalHorizontalOffset;
|
||||
|
||||
private bool _isRunning;
|
||||
|
||||
/// <summary>
|
||||
/// 是否响应鼠标滚轮操作
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty CanMouseWheelProperty = DependencyProperty.Register(
|
||||
"CanMouseWheel", typeof(bool), typeof(ScrollViewer), new PropertyMetadata(ValueBoxes.TrueBox));
|
||||
|
||||
/// <summary>
|
||||
/// 是否响应鼠标滚轮操作
|
||||
/// </summary>
|
||||
public bool CanMouseWheel
|
||||
{
|
||||
private double _totalVerticalOffset;
|
||||
get => (bool) GetValue(CanMouseWheelProperty);
|
||||
set => SetValue(CanMouseWheelProperty, ValueBoxes.BooleanBox(value));
|
||||
}
|
||||
|
||||
private double _totalHorizontalOffset;
|
||||
protected override void OnMouseWheel(MouseWheelEventArgs e)
|
||||
{
|
||||
if (!CanMouseWheel) return;
|
||||
|
||||
private bool _isRunning;
|
||||
|
||||
/// <summary>
|
||||
/// 是否响应鼠标滚轮操作
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty CanMouseWheelProperty = DependencyProperty.Register(
|
||||
"CanMouseWheel", typeof(bool), typeof(ScrollViewer), new PropertyMetadata(ValueBoxes.TrueBox));
|
||||
|
||||
/// <summary>
|
||||
/// 是否响应鼠标滚轮操作
|
||||
/// </summary>
|
||||
public bool CanMouseWheel
|
||||
if (!IsInertiaEnabled)
|
||||
{
|
||||
get => (bool) GetValue(CanMouseWheelProperty);
|
||||
set => SetValue(CanMouseWheelProperty, ValueBoxes.BooleanBox(value));
|
||||
}
|
||||
|
||||
protected override void OnMouseWheel(MouseWheelEventArgs e)
|
||||
{
|
||||
if (!CanMouseWheel) return;
|
||||
|
||||
if (!IsInertiaEnabled)
|
||||
{
|
||||
if (ScrollViewerAttach.GetOrientation(this) == Orientation.Vertical)
|
||||
{
|
||||
base.OnMouseWheel(e);
|
||||
}
|
||||
else
|
||||
{
|
||||
_totalHorizontalOffset = HorizontalOffset;
|
||||
CurrentHorizontalOffset = HorizontalOffset;
|
||||
_totalHorizontalOffset = Math.Min(Math.Max(0, _totalHorizontalOffset - e.Delta), ScrollableWidth);
|
||||
CurrentHorizontalOffset = _totalHorizontalOffset;
|
||||
}
|
||||
return;
|
||||
}
|
||||
e.Handled = true;
|
||||
|
||||
if (ScrollViewerAttach.GetOrientation(this) == Orientation.Vertical)
|
||||
{
|
||||
if (!_isRunning)
|
||||
{
|
||||
_totalVerticalOffset = VerticalOffset;
|
||||
CurrentVerticalOffset = VerticalOffset;
|
||||
}
|
||||
_totalVerticalOffset = Math.Min(Math.Max(0, _totalVerticalOffset - e.Delta), ScrollableHeight);
|
||||
ScrollToVerticalOffsetWithAnimation(_totalVerticalOffset);
|
||||
base.OnMouseWheel(e);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!_isRunning)
|
||||
{
|
||||
_totalHorizontalOffset = HorizontalOffset;
|
||||
CurrentHorizontalOffset = HorizontalOffset;
|
||||
}
|
||||
_totalHorizontalOffset = HorizontalOffset;
|
||||
CurrentHorizontalOffset = HorizontalOffset;
|
||||
_totalHorizontalOffset = Math.Min(Math.Max(0, _totalHorizontalOffset - e.Delta), ScrollableWidth);
|
||||
ScrollToHorizontalOffsetWithAnimation(_totalHorizontalOffset);
|
||||
CurrentHorizontalOffset = _totalHorizontalOffset;
|
||||
}
|
||||
return;
|
||||
}
|
||||
e.Handled = true;
|
||||
|
||||
internal void ScrollToTopInternal(double milliseconds = 500)
|
||||
if (ScrollViewerAttach.GetOrientation(this) == Orientation.Vertical)
|
||||
{
|
||||
if (!_isRunning)
|
||||
{
|
||||
_totalVerticalOffset = VerticalOffset;
|
||||
CurrentVerticalOffset = VerticalOffset;
|
||||
}
|
||||
ScrollToVerticalOffsetWithAnimation(0, milliseconds);
|
||||
_totalVerticalOffset = Math.Min(Math.Max(0, _totalVerticalOffset - e.Delta), ScrollableHeight);
|
||||
ScrollToVerticalOffsetWithAnimation(_totalVerticalOffset);
|
||||
}
|
||||
|
||||
public void ScrollToVerticalOffsetWithAnimation(double offset, double milliseconds = 500)
|
||||
else
|
||||
{
|
||||
var animation = AnimationHelper.CreateAnimation(offset, milliseconds);
|
||||
animation.EasingFunction = new CubicEase
|
||||
if (!_isRunning)
|
||||
{
|
||||
EasingMode = EasingMode.EaseOut
|
||||
};
|
||||
animation.FillBehavior = FillBehavior.Stop;
|
||||
animation.Completed += (s, e1) =>
|
||||
{
|
||||
CurrentVerticalOffset = offset;
|
||||
_isRunning = false;
|
||||
};
|
||||
_isRunning = true;
|
||||
|
||||
BeginAnimation(CurrentVerticalOffsetProperty, animation, HandoffBehavior.Compose);
|
||||
}
|
||||
|
||||
public void ScrollToHorizontalOffsetWithAnimation(double offset, double milliseconds = 500)
|
||||
{
|
||||
var animation = AnimationHelper.CreateAnimation(offset, milliseconds);
|
||||
animation.EasingFunction = new CubicEase
|
||||
{
|
||||
EasingMode = EasingMode.EaseOut
|
||||
};
|
||||
animation.FillBehavior = FillBehavior.Stop;
|
||||
animation.Completed += (s, e1) =>
|
||||
{
|
||||
CurrentHorizontalOffset = offset;
|
||||
_isRunning = false;
|
||||
};
|
||||
_isRunning = true;
|
||||
|
||||
BeginAnimation(CurrentHorizontalOffsetProperty, animation, HandoffBehavior.Compose);
|
||||
}
|
||||
|
||||
protected override HitTestResult HitTestCore(PointHitTestParameters hitTestParameters) =>
|
||||
IsPenetrating ? null : base.HitTestCore(hitTestParameters);
|
||||
|
||||
/// <summary>
|
||||
/// 是否支持惯性
|
||||
/// </summary>
|
||||
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, ValueBoxes.BooleanBox(value));
|
||||
|
||||
public static bool GetIsInertiaEnabled(DependencyObject element) => (bool) element.GetValue(IsInertiaEnabledProperty);
|
||||
|
||||
/// <summary>
|
||||
/// 是否支持惯性
|
||||
/// </summary>
|
||||
public bool IsInertiaEnabled
|
||||
{
|
||||
get => (bool) GetValue(IsInertiaEnabledProperty);
|
||||
set => SetValue(IsInertiaEnabledProperty, ValueBoxes.BooleanBox(value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 控件是否可以穿透点击
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty IsPenetratingProperty = DependencyProperty.RegisterAttached(
|
||||
"IsPenetrating", typeof(bool), typeof(ScrollViewer), new PropertyMetadata(ValueBoxes.FalseBox));
|
||||
|
||||
/// <summary>
|
||||
/// 控件是否可以穿透点击
|
||||
/// </summary>
|
||||
public bool IsPenetrating
|
||||
{
|
||||
get => (bool) GetValue(IsPenetratingProperty);
|
||||
set => SetValue(IsPenetratingProperty, ValueBoxes.BooleanBox(value));
|
||||
}
|
||||
|
||||
public static void SetIsPenetrating(DependencyObject element, bool value) => element.SetValue(IsPenetratingProperty, ValueBoxes.BooleanBox(value));
|
||||
|
||||
public static bool GetIsPenetrating(DependencyObject element) => (bool) element.GetValue(IsPenetratingProperty);
|
||||
|
||||
/// <summary>
|
||||
/// 当前垂直滚动偏移
|
||||
/// </summary>
|
||||
internal static readonly DependencyProperty CurrentVerticalOffsetProperty = DependencyProperty.Register(
|
||||
"CurrentVerticalOffset", typeof(double), typeof(ScrollViewer), new PropertyMetadata(ValueBoxes.Double0Box, OnCurrentVerticalOffsetChanged));
|
||||
|
||||
private static void OnCurrentVerticalOffsetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if (d is ScrollViewer ctl && e.NewValue is double v)
|
||||
{
|
||||
ctl.ScrollToVerticalOffset(v);
|
||||
_totalHorizontalOffset = HorizontalOffset;
|
||||
CurrentHorizontalOffset = HorizontalOffset;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当前垂直滚动偏移
|
||||
/// </summary>
|
||||
internal double CurrentVerticalOffset
|
||||
{
|
||||
// ReSharper disable once UnusedMember.Local
|
||||
get => (double) GetValue(CurrentVerticalOffsetProperty);
|
||||
set => SetValue(CurrentVerticalOffsetProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当前水平滚动偏移
|
||||
/// </summary>
|
||||
internal static readonly DependencyProperty CurrentHorizontalOffsetProperty = DependencyProperty.Register(
|
||||
"CurrentHorizontalOffset", typeof(double), typeof(ScrollViewer), new PropertyMetadata(ValueBoxes.Double0Box, OnCurrentHorizontalOffsetChanged));
|
||||
|
||||
private static void OnCurrentHorizontalOffsetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if (d is ScrollViewer ctl && e.NewValue is double v)
|
||||
{
|
||||
ctl.ScrollToHorizontalOffset(v);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当前水平滚动偏移
|
||||
/// </summary>
|
||||
internal double CurrentHorizontalOffset
|
||||
{
|
||||
get => (double) GetValue(CurrentHorizontalOffsetProperty);
|
||||
set => SetValue(CurrentHorizontalOffsetProperty, value);
|
||||
_totalHorizontalOffset = Math.Min(Math.Max(0, _totalHorizontalOffset - e.Delta), ScrollableWidth);
|
||||
ScrollToHorizontalOffsetWithAnimation(_totalHorizontalOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void ScrollToTopInternal(double milliseconds = 500)
|
||||
{
|
||||
if (!_isRunning)
|
||||
{
|
||||
_totalVerticalOffset = VerticalOffset;
|
||||
CurrentVerticalOffset = VerticalOffset;
|
||||
}
|
||||
ScrollToVerticalOffsetWithAnimation(0, milliseconds);
|
||||
}
|
||||
|
||||
public void ScrollToVerticalOffsetWithAnimation(double offset, double milliseconds = 500)
|
||||
{
|
||||
var animation = AnimationHelper.CreateAnimation(offset, milliseconds);
|
||||
animation.EasingFunction = new CubicEase
|
||||
{
|
||||
EasingMode = EasingMode.EaseOut
|
||||
};
|
||||
animation.FillBehavior = FillBehavior.Stop;
|
||||
animation.Completed += (s, e1) =>
|
||||
{
|
||||
CurrentVerticalOffset = offset;
|
||||
_isRunning = false;
|
||||
};
|
||||
_isRunning = true;
|
||||
|
||||
BeginAnimation(CurrentVerticalOffsetProperty, animation, HandoffBehavior.Compose);
|
||||
}
|
||||
|
||||
public void ScrollToHorizontalOffsetWithAnimation(double offset, double milliseconds = 500)
|
||||
{
|
||||
var animation = AnimationHelper.CreateAnimation(offset, milliseconds);
|
||||
animation.EasingFunction = new CubicEase
|
||||
{
|
||||
EasingMode = EasingMode.EaseOut
|
||||
};
|
||||
animation.FillBehavior = FillBehavior.Stop;
|
||||
animation.Completed += (s, e1) =>
|
||||
{
|
||||
CurrentHorizontalOffset = offset;
|
||||
_isRunning = false;
|
||||
};
|
||||
_isRunning = true;
|
||||
|
||||
BeginAnimation(CurrentHorizontalOffsetProperty, animation, HandoffBehavior.Compose);
|
||||
}
|
||||
|
||||
protected override HitTestResult HitTestCore(PointHitTestParameters hitTestParameters) =>
|
||||
IsPenetrating ? null : base.HitTestCore(hitTestParameters);
|
||||
|
||||
/// <summary>
|
||||
/// 是否支持惯性
|
||||
/// </summary>
|
||||
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, ValueBoxes.BooleanBox(value));
|
||||
|
||||
public static bool GetIsInertiaEnabled(DependencyObject element) => (bool) element.GetValue(IsInertiaEnabledProperty);
|
||||
|
||||
/// <summary>
|
||||
/// 是否支持惯性
|
||||
/// </summary>
|
||||
public bool IsInertiaEnabled
|
||||
{
|
||||
get => (bool) GetValue(IsInertiaEnabledProperty);
|
||||
set => SetValue(IsInertiaEnabledProperty, ValueBoxes.BooleanBox(value));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 控件是否可以穿透点击
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty IsPenetratingProperty = DependencyProperty.RegisterAttached(
|
||||
"IsPenetrating", typeof(bool), typeof(ScrollViewer), new PropertyMetadata(ValueBoxes.FalseBox));
|
||||
|
||||
/// <summary>
|
||||
/// 控件是否可以穿透点击
|
||||
/// </summary>
|
||||
public bool IsPenetrating
|
||||
{
|
||||
get => (bool) GetValue(IsPenetratingProperty);
|
||||
set => SetValue(IsPenetratingProperty, ValueBoxes.BooleanBox(value));
|
||||
}
|
||||
|
||||
public static void SetIsPenetrating(DependencyObject element, bool value) => element.SetValue(IsPenetratingProperty, ValueBoxes.BooleanBox(value));
|
||||
|
||||
public static bool GetIsPenetrating(DependencyObject element) => (bool) element.GetValue(IsPenetratingProperty);
|
||||
|
||||
/// <summary>
|
||||
/// 当前垂直滚动偏移
|
||||
/// </summary>
|
||||
internal static readonly DependencyProperty CurrentVerticalOffsetProperty = DependencyProperty.Register(
|
||||
"CurrentVerticalOffset", typeof(double), typeof(ScrollViewer), new PropertyMetadata(ValueBoxes.Double0Box, OnCurrentVerticalOffsetChanged));
|
||||
|
||||
private static void OnCurrentVerticalOffsetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if (d is ScrollViewer ctl && e.NewValue is double v)
|
||||
{
|
||||
ctl.ScrollToVerticalOffset(v);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当前垂直滚动偏移
|
||||
/// </summary>
|
||||
internal double CurrentVerticalOffset
|
||||
{
|
||||
// ReSharper disable once UnusedMember.Local
|
||||
get => (double) GetValue(CurrentVerticalOffsetProperty);
|
||||
set => SetValue(CurrentVerticalOffsetProperty, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当前水平滚动偏移
|
||||
/// </summary>
|
||||
internal static readonly DependencyProperty CurrentHorizontalOffsetProperty = DependencyProperty.Register(
|
||||
"CurrentHorizontalOffset", typeof(double), typeof(ScrollViewer), new PropertyMetadata(ValueBoxes.Double0Box, OnCurrentHorizontalOffsetChanged));
|
||||
|
||||
private static void OnCurrentHorizontalOffsetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if (d is ScrollViewer ctl && e.NewValue is double v)
|
||||
{
|
||||
ctl.ScrollToHorizontalOffset(v);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当前水平滚动偏移
|
||||
/// </summary>
|
||||
internal double CurrentHorizontalOffset
|
||||
{
|
||||
get => (double) GetValue(CurrentHorizontalOffsetProperty);
|
||||
set => SetValue(CurrentHorizontalOffsetProperty, value);
|
||||
}
|
||||
}
|
||||
@@ -3,36 +3,35 @@ using System.Windows.Controls.Primitives;
|
||||
using System.Windows.Markup;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace HandyControl.Controls
|
||||
namespace HandyControl.Controls;
|
||||
|
||||
[ContentProperty(nameof(Status))]
|
||||
public class Shield : ButtonBase
|
||||
{
|
||||
[ContentProperty(nameof(Status))]
|
||||
public class Shield : ButtonBase
|
||||
public static readonly DependencyProperty SubjectProperty = DependencyProperty.Register(
|
||||
"Subject", typeof(string), typeof(Shield), new PropertyMetadata(default(string)));
|
||||
|
||||
public string Subject
|
||||
{
|
||||
public static readonly DependencyProperty SubjectProperty = DependencyProperty.Register(
|
||||
"Subject", typeof(string), typeof(Shield), new PropertyMetadata(default(string)));
|
||||
|
||||
public string Subject
|
||||
{
|
||||
get => (string) GetValue(SubjectProperty);
|
||||
set => SetValue(SubjectProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty StatusProperty = DependencyProperty.Register(
|
||||
"Status", typeof(object), typeof(Shield), new PropertyMetadata(default(object)));
|
||||
|
||||
public object Status
|
||||
{
|
||||
get => GetValue(StatusProperty);
|
||||
set => SetValue(StatusProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ColorProperty = DependencyProperty.Register(
|
||||
"Color", typeof(Brush), typeof(Shield), new PropertyMetadata(default(Brush)));
|
||||
|
||||
public Brush Color
|
||||
{
|
||||
get => (Brush) GetValue(ColorProperty);
|
||||
set => SetValue(ColorProperty, value);
|
||||
}
|
||||
get => (string) GetValue(SubjectProperty);
|
||||
set => SetValue(SubjectProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty StatusProperty = DependencyProperty.Register(
|
||||
"Status", typeof(object), typeof(Shield), new PropertyMetadata(default(object)));
|
||||
|
||||
public object Status
|
||||
{
|
||||
get => GetValue(StatusProperty);
|
||||
set => SetValue(StatusProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ColorProperty = DependencyProperty.Register(
|
||||
"Color", typeof(Brush), typeof(Shield), new PropertyMetadata(default(Brush)));
|
||||
|
||||
public Brush Color
|
||||
{
|
||||
get => (Brush) GetValue(ColorProperty);
|
||||
set => SetValue(ColorProperty, value);
|
||||
}
|
||||
}
|
||||
@@ -1,29 +1,28 @@
|
||||
using System.Windows;
|
||||
|
||||
namespace HandyControl.Controls
|
||||
namespace HandyControl.Controls;
|
||||
|
||||
public sealed class Sprite : System.Windows.Window
|
||||
{
|
||||
public sealed class Sprite : System.Windows.Window
|
||||
private Sprite()
|
||||
{
|
||||
private Sprite()
|
||||
{
|
||||
WindowStyle = WindowStyle.None;
|
||||
AllowsTransparency = true;
|
||||
}
|
||||
|
||||
public static Sprite Show(object content)
|
||||
{
|
||||
var sprite = new Sprite
|
||||
{
|
||||
Content = content
|
||||
};
|
||||
|
||||
sprite.Show();
|
||||
|
||||
var desktopWorkingArea = SystemParameters.WorkArea;
|
||||
sprite.Left = desktopWorkingArea.Width - sprite.ActualWidth - 50;
|
||||
sprite.Top = 50 - sprite.Padding.Top;
|
||||
|
||||
return sprite;
|
||||
}
|
||||
WindowStyle = WindowStyle.None;
|
||||
AllowsTransparency = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static Sprite Show(object content)
|
||||
{
|
||||
var sprite = new Sprite
|
||||
{
|
||||
Content = content
|
||||
};
|
||||
|
||||
sprite.Show();
|
||||
|
||||
var desktopWorkingArea = SystemParameters.WorkArea;
|
||||
sprite.Left = desktopWorkingArea.Width - sprite.ActualWidth - 50;
|
||||
sprite.Top = 50 - sprite.Padding.Top;
|
||||
|
||||
return sprite;
|
||||
}
|
||||
}
|
||||
@@ -5,104 +5,103 @@ using System.Windows.Media.Animation;
|
||||
using HandyControl.Data;
|
||||
using HandyControl.Tools;
|
||||
|
||||
namespace HandyControl.Controls
|
||||
namespace HandyControl.Controls;
|
||||
|
||||
public class TransitioningContentControl : ContentControl
|
||||
{
|
||||
public class TransitioningContentControl : ContentControl
|
||||
private FrameworkElement _contentPresenter;
|
||||
|
||||
private static Storyboard StoryboardBuildInDefault;
|
||||
|
||||
private Storyboard _storyboardBuildIn;
|
||||
|
||||
public TransitioningContentControl()
|
||||
{
|
||||
private FrameworkElement _contentPresenter;
|
||||
Loaded += TransitioningContentControl_Loaded;
|
||||
Unloaded += TransitioningContentControl_Unloaded;
|
||||
}
|
||||
|
||||
private static Storyboard StoryboardBuildInDefault;
|
||||
public static readonly DependencyProperty TransitionModeProperty = DependencyProperty.Register(
|
||||
"TransitionMode", typeof(TransitionMode), typeof(TransitioningContentControl), new PropertyMetadata(default(TransitionMode), OnTransitionModeChanged));
|
||||
|
||||
private Storyboard _storyboardBuildIn;
|
||||
private static void OnTransitionModeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
var ctl = (TransitioningContentControl) d;
|
||||
ctl.OnTransitionModeChanged((TransitionMode) e.NewValue);
|
||||
}
|
||||
|
||||
public TransitioningContentControl()
|
||||
private void OnTransitionModeChanged(TransitionMode newValue)
|
||||
{
|
||||
_storyboardBuildIn = ResourceHelper.GetResourceInternal<Storyboard>($"{newValue}Transition");
|
||||
StartTransition();
|
||||
}
|
||||
|
||||
public TransitionMode TransitionMode
|
||||
{
|
||||
get => (TransitionMode) GetValue(TransitionModeProperty);
|
||||
set => SetValue(TransitionModeProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty TransitionStoryboardProperty = DependencyProperty.Register(
|
||||
"TransitionStoryboard", typeof(Storyboard), typeof(TransitioningContentControl), new PropertyMetadata(default(Storyboard)));
|
||||
|
||||
public Storyboard TransitionStoryboard
|
||||
{
|
||||
get => (Storyboard) GetValue(TransitionStoryboardProperty);
|
||||
set => SetValue(TransitionStoryboardProperty, value);
|
||||
}
|
||||
|
||||
private void TransitioningContentControl_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e) => StartTransition();
|
||||
|
||||
private void TransitioningContentControl_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
IsVisibleChanged += TransitioningContentControl_IsVisibleChanged;
|
||||
}
|
||||
|
||||
private void TransitioningContentControl_Unloaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
IsVisibleChanged -= TransitioningContentControl_IsVisibleChanged;
|
||||
}
|
||||
|
||||
private void StartTransition()
|
||||
{
|
||||
if (_contentPresenter == null || !IsVisible) return;
|
||||
|
||||
if (TransitionStoryboard != null)
|
||||
{
|
||||
Loaded += TransitioningContentControl_Loaded;
|
||||
Unloaded += TransitioningContentControl_Unloaded;
|
||||
TransitionStoryboard.Begin(_contentPresenter);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty TransitionModeProperty = DependencyProperty.Register(
|
||||
"TransitionMode", typeof(TransitionMode), typeof(TransitioningContentControl), new PropertyMetadata(default(TransitionMode), OnTransitionModeChanged));
|
||||
|
||||
private static void OnTransitionModeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
else if (_storyboardBuildIn != null)
|
||||
{
|
||||
var ctl = (TransitioningContentControl) d;
|
||||
ctl.OnTransitionModeChanged((TransitionMode) e.NewValue);
|
||||
_storyboardBuildIn?.Begin(_contentPresenter);
|
||||
}
|
||||
|
||||
private void OnTransitionModeChanged(TransitionMode newValue)
|
||||
else
|
||||
{
|
||||
_storyboardBuildIn = ResourceHelper.GetResourceInternal<Storyboard>($"{newValue}Transition");
|
||||
StartTransition();
|
||||
}
|
||||
|
||||
public TransitionMode TransitionMode
|
||||
{
|
||||
get => (TransitionMode) GetValue(TransitionModeProperty);
|
||||
set => SetValue(TransitionModeProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty TransitionStoryboardProperty = DependencyProperty.Register(
|
||||
"TransitionStoryboard", typeof(Storyboard), typeof(TransitioningContentControl), new PropertyMetadata(default(Storyboard)));
|
||||
|
||||
public Storyboard TransitionStoryboard
|
||||
{
|
||||
get => (Storyboard) GetValue(TransitionStoryboardProperty);
|
||||
set => SetValue(TransitionStoryboardProperty, value);
|
||||
}
|
||||
|
||||
private void TransitioningContentControl_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e) => StartTransition();
|
||||
|
||||
private void TransitioningContentControl_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
IsVisibleChanged += TransitioningContentControl_IsVisibleChanged;
|
||||
}
|
||||
|
||||
private void TransitioningContentControl_Unloaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
IsVisibleChanged -= TransitioningContentControl_IsVisibleChanged;
|
||||
}
|
||||
|
||||
private void StartTransition()
|
||||
{
|
||||
if (_contentPresenter == null || !IsVisible) return;
|
||||
|
||||
if (TransitionStoryboard != null)
|
||||
{
|
||||
TransitionStoryboard.Begin(_contentPresenter);
|
||||
}
|
||||
else if (_storyboardBuildIn != null)
|
||||
{
|
||||
_storyboardBuildIn?.Begin(_contentPresenter);
|
||||
}
|
||||
else
|
||||
{
|
||||
StoryboardBuildInDefault ??= ResourceHelper.GetResourceInternal<Storyboard>($"{default(TransitionMode)}Transition");
|
||||
StoryboardBuildInDefault?.Begin(_contentPresenter);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnApplyTemplate()
|
||||
{
|
||||
base.OnApplyTemplate();
|
||||
|
||||
_contentPresenter = VisualTreeHelper.GetChild(this, 0) as FrameworkElement;
|
||||
if (_contentPresenter != null)
|
||||
{
|
||||
_contentPresenter.RenderTransformOrigin = new Point(0.5, 0.5);
|
||||
_contentPresenter.RenderTransform = new TransformGroup
|
||||
{
|
||||
Children =
|
||||
{
|
||||
new ScaleTransform(),
|
||||
new SkewTransform(),
|
||||
new RotateTransform(),
|
||||
new TranslateTransform()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
StartTransition();
|
||||
StoryboardBuildInDefault ??= ResourceHelper.GetResourceInternal<Storyboard>($"{default(TransitionMode)}Transition");
|
||||
StoryboardBuildInDefault?.Begin(_contentPresenter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnApplyTemplate()
|
||||
{
|
||||
base.OnApplyTemplate();
|
||||
|
||||
_contentPresenter = VisualTreeHelper.GetChild(this, 0) as FrameworkElement;
|
||||
if (_contentPresenter != null)
|
||||
{
|
||||
_contentPresenter.RenderTransformOrigin = new Point(0.5, 0.5);
|
||||
_contentPresenter.RenderTransform = new TransformGroup
|
||||
{
|
||||
Children =
|
||||
{
|
||||
new ScaleTransform(),
|
||||
new SkewTransform(),
|
||||
new RotateTransform(),
|
||||
new TranslateTransform()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
StartTransition();
|
||||
}
|
||||
}
|
||||
@@ -5,161 +5,160 @@ using System.Windows.Media;
|
||||
using System.Windows.Shapes;
|
||||
using HandyControl.Data;
|
||||
|
||||
namespace HandyControl.Controls
|
||||
namespace HandyControl.Controls;
|
||||
|
||||
[TemplatePart(Name = ElementRoot, Type = typeof(Border))]
|
||||
[ContentProperty(nameof(Content))]
|
||||
public class Watermark : Control
|
||||
{
|
||||
[TemplatePart(Name = ElementRoot, Type = typeof(Border))]
|
||||
[ContentProperty(nameof(Content))]
|
||||
public class Watermark : Control
|
||||
private const string ElementRoot = "PART_Root";
|
||||
|
||||
private Border _borderRoot;
|
||||
|
||||
private DrawingBrush _brush;
|
||||
|
||||
public static readonly DependencyProperty AngleProperty = DependencyProperty.Register(
|
||||
"Angle", typeof(double), typeof(Watermark), new FrameworkPropertyMetadata(ValueBoxes.Double0Box, FrameworkPropertyMetadataOptions.AffectsRender));
|
||||
|
||||
public double Angle
|
||||
{
|
||||
private const string ElementRoot = "PART_Root";
|
||||
|
||||
private Border _borderRoot;
|
||||
|
||||
private DrawingBrush _brush;
|
||||
|
||||
public static readonly DependencyProperty AngleProperty = DependencyProperty.Register(
|
||||
"Angle", typeof(double), typeof(Watermark), new FrameworkPropertyMetadata(ValueBoxes.Double0Box, FrameworkPropertyMetadataOptions.AffectsRender));
|
||||
|
||||
public double Angle
|
||||
{
|
||||
get => (double) GetValue(AngleProperty);
|
||||
set => SetValue(AngleProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ContentProperty = DependencyProperty.Register(
|
||||
"Content", typeof(object), typeof(Watermark), new PropertyMetadata(default));
|
||||
|
||||
public object Content
|
||||
{
|
||||
get => GetValue(ContentProperty);
|
||||
set => SetValue(ContentProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty MarkProperty = DependencyProperty.Register(
|
||||
"Mark", typeof(object), typeof(Watermark), new FrameworkPropertyMetadata(default, FrameworkPropertyMetadataOptions.AffectsRender));
|
||||
|
||||
public object Mark
|
||||
{
|
||||
get => GetValue(MarkProperty);
|
||||
set => SetValue(MarkProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty MarkWidthProperty = DependencyProperty.Register(
|
||||
"MarkWidth", typeof(double), typeof(Watermark), new FrameworkPropertyMetadata(ValueBoxes.Double0Box, FrameworkPropertyMetadataOptions.AffectsRender));
|
||||
|
||||
public double MarkWidth
|
||||
{
|
||||
get => (double) GetValue(MarkWidthProperty);
|
||||
set => SetValue(MarkWidthProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty MarkHeightProperty = DependencyProperty.Register(
|
||||
"MarkHeight", typeof(double), typeof(Watermark), new FrameworkPropertyMetadata(ValueBoxes.Double0Box, FrameworkPropertyMetadataOptions.AffectsRender));
|
||||
|
||||
public double MarkHeight
|
||||
{
|
||||
get => (double) GetValue(MarkHeightProperty);
|
||||
set => SetValue(MarkHeightProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty MarkBrushProperty = DependencyProperty.Register(
|
||||
"MarkBrush", typeof(Brush), typeof(Watermark), new FrameworkPropertyMetadata(default(Brush), FrameworkPropertyMetadataOptions.AffectsRender));
|
||||
|
||||
public Brush MarkBrush
|
||||
{
|
||||
get => (Brush) GetValue(MarkBrushProperty);
|
||||
set => SetValue(MarkBrushProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty AutoSizeEnabledProperty = DependencyProperty.Register(
|
||||
"AutoSizeEnabled", typeof(bool), typeof(Watermark), new FrameworkPropertyMetadata(ValueBoxes.TrueBox, FrameworkPropertyMetadataOptions.AffectsRender));
|
||||
|
||||
public bool AutoSizeEnabled
|
||||
{
|
||||
get => (bool) GetValue(AutoSizeEnabledProperty);
|
||||
set => SetValue(AutoSizeEnabledProperty, ValueBoxes.BooleanBox(value));
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty MarkMarginProperty = DependencyProperty.Register(
|
||||
"MarkMargin", typeof(Thickness), typeof(Watermark), new FrameworkPropertyMetadata(default(Thickness), FrameworkPropertyMetadataOptions.AffectsRender));
|
||||
|
||||
public Thickness MarkMargin
|
||||
{
|
||||
get => (Thickness) GetValue(MarkMarginProperty);
|
||||
set => SetValue(MarkMarginProperty, value);
|
||||
}
|
||||
|
||||
public override void OnApplyTemplate() => _borderRoot = GetTemplateChild(ElementRoot) as Border;
|
||||
|
||||
private void EnsureBrush()
|
||||
{
|
||||
var presenter = new ContentPresenter();
|
||||
|
||||
if (Mark is Geometry geometry)
|
||||
{
|
||||
presenter.Content = new Path
|
||||
{
|
||||
Width = MarkWidth,
|
||||
Height = MarkHeight,
|
||||
Fill = MarkBrush,
|
||||
Stretch = Stretch.Uniform,
|
||||
Data = geometry
|
||||
};
|
||||
}
|
||||
else if (Mark is string str)
|
||||
{
|
||||
presenter.Content = new TextBlock
|
||||
{
|
||||
Text = str,
|
||||
FontSize = FontSize,
|
||||
Foreground = MarkBrush
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
presenter.Content = Mark;
|
||||
}
|
||||
|
||||
Size markSize;
|
||||
if (AutoSizeEnabled)
|
||||
{
|
||||
presenter.Measure(new Size(double.MaxValue, double.MaxValue));
|
||||
markSize = presenter.DesiredSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
markSize = new Size(MarkWidth, MarkHeight);
|
||||
}
|
||||
|
||||
_brush = new DrawingBrush
|
||||
{
|
||||
ViewportUnits = BrushMappingMode.Absolute,
|
||||
Stretch = Stretch.Uniform,
|
||||
TileMode = TileMode.Tile,
|
||||
Transform = new RotateTransform(Angle),
|
||||
Drawing = new GeometryDrawing
|
||||
{
|
||||
Brush = new VisualBrush(new Border
|
||||
{
|
||||
Background = Brushes.Transparent,
|
||||
Padding = MarkMargin,
|
||||
Child = presenter
|
||||
}),
|
||||
Geometry = new RectangleGeometry(new Rect(markSize))
|
||||
},
|
||||
Viewport = new Rect(markSize)
|
||||
};
|
||||
|
||||
RenderOptions.SetCacheInvalidationThresholdMinimum(_brush, 0.5);
|
||||
RenderOptions.SetCacheInvalidationThresholdMaximum(_brush, 2);
|
||||
RenderOptions.SetCachingHint(_brush, CachingHint.Cache);
|
||||
|
||||
if (_borderRoot != null)
|
||||
{
|
||||
_borderRoot.Background = _brush;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnRender(DrawingContext drawingContext) => EnsureBrush();
|
||||
get => (double) GetValue(AngleProperty);
|
||||
set => SetValue(AngleProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ContentProperty = DependencyProperty.Register(
|
||||
"Content", typeof(object), typeof(Watermark), new PropertyMetadata(default));
|
||||
|
||||
public object Content
|
||||
{
|
||||
get => GetValue(ContentProperty);
|
||||
set => SetValue(ContentProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty MarkProperty = DependencyProperty.Register(
|
||||
"Mark", typeof(object), typeof(Watermark), new FrameworkPropertyMetadata(default, FrameworkPropertyMetadataOptions.AffectsRender));
|
||||
|
||||
public object Mark
|
||||
{
|
||||
get => GetValue(MarkProperty);
|
||||
set => SetValue(MarkProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty MarkWidthProperty = DependencyProperty.Register(
|
||||
"MarkWidth", typeof(double), typeof(Watermark), new FrameworkPropertyMetadata(ValueBoxes.Double0Box, FrameworkPropertyMetadataOptions.AffectsRender));
|
||||
|
||||
public double MarkWidth
|
||||
{
|
||||
get => (double) GetValue(MarkWidthProperty);
|
||||
set => SetValue(MarkWidthProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty MarkHeightProperty = DependencyProperty.Register(
|
||||
"MarkHeight", typeof(double), typeof(Watermark), new FrameworkPropertyMetadata(ValueBoxes.Double0Box, FrameworkPropertyMetadataOptions.AffectsRender));
|
||||
|
||||
public double MarkHeight
|
||||
{
|
||||
get => (double) GetValue(MarkHeightProperty);
|
||||
set => SetValue(MarkHeightProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty MarkBrushProperty = DependencyProperty.Register(
|
||||
"MarkBrush", typeof(Brush), typeof(Watermark), new FrameworkPropertyMetadata(default(Brush), FrameworkPropertyMetadataOptions.AffectsRender));
|
||||
|
||||
public Brush MarkBrush
|
||||
{
|
||||
get => (Brush) GetValue(MarkBrushProperty);
|
||||
set => SetValue(MarkBrushProperty, value);
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty AutoSizeEnabledProperty = DependencyProperty.Register(
|
||||
"AutoSizeEnabled", typeof(bool), typeof(Watermark), new FrameworkPropertyMetadata(ValueBoxes.TrueBox, FrameworkPropertyMetadataOptions.AffectsRender));
|
||||
|
||||
public bool AutoSizeEnabled
|
||||
{
|
||||
get => (bool) GetValue(AutoSizeEnabledProperty);
|
||||
set => SetValue(AutoSizeEnabledProperty, ValueBoxes.BooleanBox(value));
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty MarkMarginProperty = DependencyProperty.Register(
|
||||
"MarkMargin", typeof(Thickness), typeof(Watermark), new FrameworkPropertyMetadata(default(Thickness), FrameworkPropertyMetadataOptions.AffectsRender));
|
||||
|
||||
public Thickness MarkMargin
|
||||
{
|
||||
get => (Thickness) GetValue(MarkMarginProperty);
|
||||
set => SetValue(MarkMarginProperty, value);
|
||||
}
|
||||
|
||||
public override void OnApplyTemplate() => _borderRoot = GetTemplateChild(ElementRoot) as Border;
|
||||
|
||||
private void EnsureBrush()
|
||||
{
|
||||
var presenter = new ContentPresenter();
|
||||
|
||||
if (Mark is Geometry geometry)
|
||||
{
|
||||
presenter.Content = new Path
|
||||
{
|
||||
Width = MarkWidth,
|
||||
Height = MarkHeight,
|
||||
Fill = MarkBrush,
|
||||
Stretch = Stretch.Uniform,
|
||||
Data = geometry
|
||||
};
|
||||
}
|
||||
else if (Mark is string str)
|
||||
{
|
||||
presenter.Content = new TextBlock
|
||||
{
|
||||
Text = str,
|
||||
FontSize = FontSize,
|
||||
Foreground = MarkBrush
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
presenter.Content = Mark;
|
||||
}
|
||||
|
||||
Size markSize;
|
||||
if (AutoSizeEnabled)
|
||||
{
|
||||
presenter.Measure(new Size(double.MaxValue, double.MaxValue));
|
||||
markSize = presenter.DesiredSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
markSize = new Size(MarkWidth, MarkHeight);
|
||||
}
|
||||
|
||||
_brush = new DrawingBrush
|
||||
{
|
||||
ViewportUnits = BrushMappingMode.Absolute,
|
||||
Stretch = Stretch.Uniform,
|
||||
TileMode = TileMode.Tile,
|
||||
Transform = new RotateTransform(Angle),
|
||||
Drawing = new GeometryDrawing
|
||||
{
|
||||
Brush = new VisualBrush(new Border
|
||||
{
|
||||
Background = Brushes.Transparent,
|
||||
Padding = MarkMargin,
|
||||
Child = presenter
|
||||
}),
|
||||
Geometry = new RectangleGeometry(new Rect(markSize))
|
||||
},
|
||||
Viewport = new Rect(markSize)
|
||||
};
|
||||
|
||||
RenderOptions.SetCacheInvalidationThresholdMinimum(_brush, 0.5);
|
||||
RenderOptions.SetCacheInvalidationThresholdMaximum(_brush, 2);
|
||||
RenderOptions.SetCachingHint(_brush, CachingHint.Cache);
|
||||
|
||||
if (_borderRoot != null)
|
||||
{
|
||||
_borderRoot.Background = _brush;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnRender(DrawingContext drawingContext) => EnsureBrush();
|
||||
}
|
||||
Reference in new issue
Block a user