将以往的代码复制到代码库
This commit is contained in:
215
Future.Contract/Adorners/LoadingAdorner.cs
Normal file
215
Future.Contract/Adorners/LoadingAdorner.cs
Normal file
@@ -0,0 +1,215 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace Future.Contract
|
||||
{
|
||||
/// <summary>
|
||||
/// 加载遮罩:用于后台执行耗时加载任务时提供操作遮罩
|
||||
/// </summary>
|
||||
public class LoadingAdorner : Adorner
|
||||
{
|
||||
[AllowNull]
|
||||
private Grid _Layout;
|
||||
[AllowNull]
|
||||
private TextBlock _Feedback;
|
||||
[AllowNull]
|
||||
private AdornerLayer _AdornerLayer;
|
||||
[AllowNull]
|
||||
private VisualCollection _Visuals;
|
||||
|
||||
private Cursor _Cursor;
|
||||
|
||||
private System.Windows.Threading.DispatcherTimer _UiTimer = new System.Windows.Threading.DispatcherTimer();
|
||||
/// <summary>
|
||||
/// 对目标元素提供加载遮罩
|
||||
/// </summary>
|
||||
/// <param name="adornedElement">要进行遮盖的视觉元素</param>
|
||||
private LoadingAdorner(UIElement adornedElement) : base(adornedElement)
|
||||
{
|
||||
PrepareLoading();
|
||||
}
|
||||
private LoadingAdorner(UIElement adornedElement, string feedback, double progress = -1.1) : base(adornedElement)
|
||||
{
|
||||
PrepareLoading(feedback, progress);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 反馈信息
|
||||
/// </summary>
|
||||
public string Feedback
|
||||
{
|
||||
get { return (string)GetValue(FeedbackProperty); }
|
||||
set { SetValue(FeedbackProperty, value); Refresh(); }
|
||||
}
|
||||
|
||||
// Using a DependencyProperty as the backing store for Feedback. This enables animation, styling, binding, etc...
|
||||
public static readonly DependencyProperty FeedbackProperty =
|
||||
DependencyProperty.Register("Feedback", typeof(string), typeof(LoadingAdorner), new PropertyMetadata("请稍等..."));
|
||||
|
||||
/// <summary>
|
||||
/// 进度信息
|
||||
/// </summary>
|
||||
public double Progress
|
||||
{
|
||||
get { return (double)GetValue(ProgressProperty); }
|
||||
set { SetValue(ProgressProperty, value); Refresh(); }
|
||||
}
|
||||
|
||||
// Using a DependencyProperty as the backing store for Progress. This enables animation, styling, binding, etc...
|
||||
public static readonly DependencyProperty ProgressProperty =
|
||||
DependencyProperty.Register("Progress", typeof(double), typeof(LoadingAdorner), new PropertyMetadata(-1.1));
|
||||
|
||||
/// <summary>
|
||||
/// 准备启动:生成装饰器需要的内容
|
||||
/// </summary>
|
||||
/// <param name="feedback"></param>
|
||||
private void PrepareLoading(string feedback = "", double progress = -1.1)
|
||||
{
|
||||
_Visuals = new VisualCollection(this);
|
||||
_Layout = new Grid
|
||||
{
|
||||
Cursor = Cursors.Wait,
|
||||
ForceCursor = true
|
||||
};
|
||||
_Layout.Children.Add(new Border()
|
||||
{
|
||||
Background = Brushes.Gray,
|
||||
Opacity = 0.85,
|
||||
});
|
||||
_Feedback = new TextBlock()
|
||||
{
|
||||
Text = feedback,
|
||||
//FontSize=14,
|
||||
Foreground = Brushes.White,
|
||||
HorizontalAlignment = HorizontalAlignment.Center,
|
||||
VerticalAlignment = VerticalAlignment.Center,
|
||||
Margin = new Thickness(10)
|
||||
};
|
||||
_Layout.Children.Add(_Feedback);
|
||||
|
||||
_Visuals.Add(_Layout);
|
||||
|
||||
FeedbackProgress(feedback, progress);
|
||||
|
||||
_UiTimer.Interval = TimeSpan.FromMilliseconds(200);
|
||||
_UiTimer.Tick += (s, e) => Animate();
|
||||
_UiTimer.Start();
|
||||
|
||||
_AdornerLayer = AdornerLayer.GetAdornerLayer(AdornedElement);
|
||||
_AdornerLayer?.Add(this);
|
||||
|
||||
if (AdornedElement is FrameworkElement)
|
||||
{
|
||||
FrameworkElement target = (FrameworkElement)AdornedElement;
|
||||
_Cursor = target.Cursor;
|
||||
target.Cursor = Cursors.Wait;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 开始装载:可以保证每个控件上方只会出现一个加载遮罩层
|
||||
/// </summary>
|
||||
/// <param name="adornedElement">加载目标</param>
|
||||
/// <param name="feedback">反馈信息</param>
|
||||
/// <param name="progress">进度信息</param>
|
||||
/// <returns>加载遮罩装饰器</returns>
|
||||
public static LoadingAdorner BeginLoading(UIElement adornedElement, string feedback = "", double progress = -1)
|
||||
{
|
||||
var adorners = AdornerLayer.GetAdornerLayer(adornedElement)?.GetAdorners(adornedElement)?.OfType<LoadingAdorner>();
|
||||
if (adorners != null && adorners.Count() == 1) return adorners.ToArray()[0];
|
||||
|
||||
return new LoadingAdorner(adornedElement, feedback, progress);
|
||||
}
|
||||
/// <summary>
|
||||
/// 结束加载:清除一个控件上方所有的加载遮罩层
|
||||
/// </summary>
|
||||
/// <param name="adornedElement">用标元素</param>
|
||||
public static void FinishLoading(UIElement adornedElement)
|
||||
{
|
||||
var adornerLayer = AdornerLayer.GetAdornerLayer(adornedElement);
|
||||
var adorners = adornerLayer?.GetAdorners(adornedElement);
|
||||
if (adorners == null) return;
|
||||
for (int i = adorners.Length - 1; i >= 0; i--)
|
||||
if (adorners[i] is LoadingAdorner)
|
||||
((LoadingAdorner)adorners[i]).Finish();
|
||||
}
|
||||
/// <summary>
|
||||
/// 进度反馈:用于向装饰器反馈当前进度
|
||||
/// </summary>
|
||||
/// <param name="feedback">信息:进度遮罩上显示的信息</param>
|
||||
/// <param name="progress">进度:0~1的小数,代表?%,其他数值无效</param>
|
||||
public void FeedbackProgress(string feedback = "", double progress = -1)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(feedback)) Feedback = feedback;
|
||||
if (progress >= 0 && progress <= 1) Progress = progress;
|
||||
}
|
||||
|
||||
private string _ProgressInfo = "请稍等...";
|
||||
/// <summary>
|
||||
/// 用于更新“进度信息”
|
||||
/// </summary>
|
||||
private void Refresh()
|
||||
{
|
||||
string prog = "-*-";
|
||||
if (0 <= Progress && Progress <= 1)
|
||||
prog = string.Format("{0:0%}", Progress).PadLeft(3);
|
||||
_ProgressInfo = $"[{prog}] : {Feedback.TrimEnd('.')} ... ";
|
||||
}
|
||||
/// <summary>
|
||||
/// 循环动画
|
||||
/// </summary>
|
||||
private void Animate()
|
||||
{
|
||||
string info = _Feedback.Text;
|
||||
if (!string.IsNullOrEmpty(info) && info.Length > 0)
|
||||
{
|
||||
char end = info[info.Length - 1];
|
||||
info = _ProgressInfo;
|
||||
|
||||
switch (end)
|
||||
{
|
||||
case '|': { info = info + '/'; } break;
|
||||
case '/': { info = info + '-'; } break;
|
||||
case '-': { info = info + '\\'; } break;
|
||||
case '\\': { info = info + '|'; } break;
|
||||
default: { info = info + '|'; } break;
|
||||
}
|
||||
_Feedback.Text = info;
|
||||
}
|
||||
else _Feedback.Text = _ProgressInfo + "|";
|
||||
}
|
||||
/// <summary>
|
||||
/// 结束装载
|
||||
/// </summary>
|
||||
public void Finish()
|
||||
{
|
||||
_UiTimer.Stop();
|
||||
|
||||
if (AdornedElement is FrameworkElement)
|
||||
{
|
||||
((FrameworkElement)AdornedElement).Cursor = _Cursor;
|
||||
}
|
||||
|
||||
_AdornerLayer?.Remove(this);
|
||||
}
|
||||
|
||||
protected override int VisualChildrenCount => _Visuals.Count;
|
||||
|
||||
protected override Visual GetVisualChild(int index) => _Visuals[index];
|
||||
|
||||
protected override Size ArrangeOverride(Size finalSize)
|
||||
{
|
||||
_Layout.Arrange(new Rect(new Point(0, 0), finalSize));
|
||||
return finalSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user