From dec0d37b314b81e369f07feefe5954eac8216540 Mon Sep 17 00:00:00 2001 From: NaBian <836904362@qq.com> Date: Sun, 11 Nov 2018 15:07:55 +0800 Subject: [PATCH] improve stepbar --- HandyControl/Controls/StepBar/StepBar.cs | 157 +++++++++++++++++ HandyControl/Controls/StepBar/StepBarItem.cs | 42 +++++ HandyControl/Controls/Steps/StepBar.cs | 162 ------------------ HandyControl/Controls/Steps/StepItem.cs | 70 -------- .../Controls/TransitioningContentControl.cs | 8 +- HandyControl/Data/Enum/StepStatus.cs | 23 +++ HandyControl/HandyControl.csproj | 9 +- .../Properties/Langs/Lang.Designer.cs | 29 ++-- HandyControl/Properties/Langs/Lang.en.resx | 9 +- HandyControl/Properties/Langs/Lang.resx | 9 +- .../Themes/Styles/Base/StepBarBaseStyle.xaml | 134 +++++++++++++++ HandyControl/Themes/Styles/ProgressBar.xaml | 13 +- HandyControl/Themes/Styles/StepBar.xaml | 34 +--- .../Data/Model/StepBarDemoModel.cs | 9 + HandyControlDemo/HandyControlDemo.csproj | 2 + .../Properties/Langs/Lang.Designer.cs | 11 +- .../Properties/Langs/Lang.en.resx | 3 + HandyControlDemo/Properties/Langs/Lang.resx | 3 + HandyControlDemo/Service/DataService.cs | 33 +++- .../UserControl/Controls/StepBarDemoCtl.xaml | 58 +++++-- .../UserControl/Main/LeftMainContent.xaml | 6 +- .../ViewModel/StepBarDemoViewModel.cs | 60 +++++++ .../ViewModel/ViewModelLocator.cs | 3 + README.md | 12 +- Resources/Slider.png | Bin 0 -> 9614 bytes Resources/StepBar.gif | Bin 58026 -> 0 bytes Resources/StepBar.png | Bin 0 -> 31480 bytes 27 files changed, 591 insertions(+), 308 deletions(-) create mode 100644 HandyControl/Controls/StepBar/StepBar.cs create mode 100644 HandyControl/Controls/StepBar/StepBarItem.cs delete mode 100644 HandyControl/Controls/Steps/StepBar.cs delete mode 100644 HandyControl/Controls/Steps/StepItem.cs create mode 100644 HandyControl/Data/Enum/StepStatus.cs create mode 100644 HandyControl/Themes/Styles/Base/StepBarBaseStyle.xaml create mode 100644 HandyControlDemo/Data/Model/StepBarDemoModel.cs create mode 100644 HandyControlDemo/ViewModel/StepBarDemoViewModel.cs create mode 100644 Resources/Slider.png delete mode 100644 Resources/StepBar.gif create mode 100644 Resources/StepBar.png diff --git a/HandyControl/Controls/StepBar/StepBar.cs b/HandyControl/Controls/StepBar/StepBar.cs new file mode 100644 index 00000000..cdfcde62 --- /dev/null +++ b/HandyControl/Controls/StepBar/StepBar.cs @@ -0,0 +1,157 @@ +using System; +using System.ComponentModel; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using System.Windows.Input; +using System.Windows.Media; +using HandyControl.Data; +using HandyControl.Interactivity; +using HandyControl.Tools; + +namespace HandyControl.Controls +{ + [StyleTypedProperty(Property = "ItemContainerStyle", StyleTargetType = typeof(StepBarItem))] + [DefaultEvent("StepChanged")] + [TemplatePart(Name = ElementProgressBarBack, Type = typeof(ProgressBar))] + public class StepBar : ItemsControl + { + private ProgressBar _progressBarBack; + + #region Constants + + private const string ElementProgressBarBack = "PART_ProgressBarBack"; + + #endregion Constants + + public StepBar() + { + CommandBindings.Add(new CommandBinding(ControlCommands.Next, (s, e) => Next())); + CommandBindings.Add(new CommandBinding(ControlCommands.Prev, (s, e) => Prev())); + ItemContainerGenerator.StatusChanged += ItemContainerGenerator_StatusChanged; + } + + private void ItemContainerGenerator_StatusChanged(object sender, EventArgs e) + { + var count = Items.Count; + if (count > 0) + { + if (ItemContainerGenerator.ContainerFromIndex(0) is StepBarItem item) + { + item.Status = StepStatus.UnderWay; + } + + for (int i = 0; i < count; i++) + { + if (ItemContainerGenerator.ContainerFromIndex(i) is StepBarItem stepBarItem) + { + stepBarItem.Index = i + 1; + } + } + } + } + + protected override bool IsItemItsOwnContainerOverride(object item) => item is StepBarItem; + + protected override DependencyObject GetContainerForItemOverride() => new StepBarItem(); + + /// + /// 步骤改变事件 + /// + public static readonly RoutedEvent StepChangedEvent = + EventManager.RegisterRoutedEvent("StepChanged", RoutingStrategy.Bubble, + typeof(EventHandler>), typeof(StepBar)); + + /// + /// 步骤改变事件 + /// + [Category("Behavior")] + public event EventHandler> StepChanged + { + add => AddHandler(StepChangedEvent, value); + remove => RemoveHandler(StepChangedEvent, value); + } + + public static readonly DependencyProperty StepIndexProperty = DependencyProperty.Register( + "StepIndex", typeof(int), typeof(StepBar), new PropertyMetadata(default(int))); + + public int StepIndex + { + get => (int) GetValue(StepIndexProperty); + protected set => SetValue(StepIndexProperty, value); + } + + public static readonly DependencyProperty DockProperty = DependencyProperty.Register( + "Dock", typeof(Dock), typeof(StepBar), new PropertyMetadata(Dock.Top)); + + public Dock Dock + { + get => (Dock) GetValue(DockProperty); + set => SetValue(DockProperty, value); + } + + public override void OnApplyTemplate() + { + base.OnApplyTemplate(); + + _progressBarBack = GetTemplateChild(ElementProgressBarBack) as ProgressBar; + } + + protected override void OnRender(DrawingContext drawingContext) + { + base.OnRender(drawingContext); + + var colCount = Items.Count; + if (_progressBarBack == null || colCount <= 0) return; + _progressBarBack.Maximum = colCount - 1; + _progressBarBack.Value = StepIndex; + + if (Dock == Dock.Top || Dock == Dock.Bottom) + { + _progressBarBack.Width = (colCount - 1) * (ActualWidth / colCount); + } + else + { + _progressBarBack.Height = (colCount - 1) * (ActualHeight / colCount); + } + } + + public void Next() + { + StepIndex++; + if (StepIndex >= Items.Count) + { + StepIndex = Items.Count - 1; + return; + } + RaiseEvent(new FunctionEventArgs(StepChangedEvent, this) + { + Info = StepIndex + }); + if (ItemContainerGenerator.ContainerFromIndex(StepIndex - 1) is StepBarItem stepItemFinished) + stepItemFinished.Status = StepStatus.Complete; + if (ItemContainerGenerator.ContainerFromIndex(StepIndex) is StepBarItem stepItemSelected) + stepItemSelected.Status = StepStatus.UnderWay; + _progressBarBack?.BeginAnimation(RangeBase.ValueProperty, AnimationHelper.CreateAnimation(StepIndex)); + } + + public void Prev() + { + StepIndex--; + if (StepIndex < 0) + { + StepIndex = 0; + return; + } + RaiseEvent(new FunctionEventArgs(StepChangedEvent, this) + { + Info = StepIndex + }); + if (ItemContainerGenerator.ContainerFromIndex(StepIndex + 1) is StepBarItem stepItemWaiting) + stepItemWaiting.Status = StepStatus.Waiting; + if (ItemContainerGenerator.ContainerFromIndex(StepIndex) is StepBarItem stepItemSelected) + stepItemSelected.Status = StepStatus.UnderWay; + _progressBarBack?.BeginAnimation(RangeBase.ValueProperty, AnimationHelper.CreateAnimation(StepIndex)); + } + } +} \ No newline at end of file diff --git a/HandyControl/Controls/StepBar/StepBarItem.cs b/HandyControl/Controls/StepBar/StepBarItem.cs new file mode 100644 index 00000000..e69a6e6a --- /dev/null +++ b/HandyControl/Controls/StepBar/StepBarItem.cs @@ -0,0 +1,42 @@ +using System.Windows; +using System.Windows.Controls; +using HandyControl.Data; + +namespace HandyControl.Controls +{ + /// + /// 步骤条单元项 + /// + public class StepBarItem : ContentControl + { + /// + /// 步骤编号 + /// + public static readonly DependencyProperty IndexProperty = DependencyProperty.Register( + "Index", typeof(int), typeof(StepBarItem), new PropertyMetadata(-1)); + + /// + /// 步骤编号 + /// + public int Index + { + get => (int) GetValue(IndexProperty); + internal set => SetValue(IndexProperty, value); + } + + /// + /// 步骤状态 + /// + public static readonly DependencyProperty StatusProperty = DependencyProperty.Register( + "Status", typeof(StepStatus), typeof(StepBarItem), new PropertyMetadata(StepStatus.Waiting)); + + /// + /// 步骤状态 + /// + public StepStatus Status + { + get => (StepStatus) GetValue(StatusProperty); + internal set => SetValue(StatusProperty, value); + } + } +} \ No newline at end of file diff --git a/HandyControl/Controls/Steps/StepBar.cs b/HandyControl/Controls/Steps/StepBar.cs deleted file mode 100644 index 15654df5..00000000 --- a/HandyControl/Controls/Steps/StepBar.cs +++ /dev/null @@ -1,162 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Controls.Primitives; -using System.Windows.Input; -using System.Windows.Markup; -using System.Windows.Media; -using HandyControl.Data; -using HandyControl.Interactivity; -using HandyControl.Tools; - -// ReSharper disable once CheckNamespace -namespace HandyControl.Controls -{ - /// - /// 步骤条 - /// - [ContentProperty("Items")] - [TemplatePart(Name = ElementProgressBarBack, Type = typeof(ProgressBar))] - [TemplatePart(Name = ElementUniformGridMain, Type = typeof(Panel))] - public class StepBar : Control - { - private bool _isLoaded; - - private ProgressBar _progressBarBack; - - private Panel _panelMain; - - #region Constants - - private const string ElementProgressBarBack = "PART_ProgressBarBack"; - private const string ElementUniformGridMain = "PART_UniformGridMain"; - - #endregion Constants - - /// - /// 步骤改变事件 - /// - public static readonly RoutedEvent StepChangedEvent = - EventManager.RegisterRoutedEvent("StepChanged", RoutingStrategy.Bubble, - typeof(EventHandler>), typeof(StepBar)); - - /// - /// 步骤改变事件 - /// - public event EventHandler> StepChanged - { - add => AddHandler(StepChangedEvent, value); - remove => RemoveHandler(StepChangedEvent, value); - } - - public StepBar() - { - Loaded += (s1, e1) => - { - if (_isLoaded) return; - UpdateItems(Items); - - CommandBindings.Add(new CommandBinding(ControlCommands.Next, (s, e) => Next())); - CommandBindings.Add(new CommandBinding(ControlCommands.Prev, (s, e) => Prev())); - - _isLoaded = true; - }; - } - - public override void OnApplyTemplate() - { - _panelMain?.Children.Clear(); - base.OnApplyTemplate(); - - _progressBarBack = GetTemplateChild(ElementProgressBarBack) as ProgressBar; - _panelMain = GetTemplateChild(ElementUniformGridMain) as Panel; - - CheckNull(); - - if (_isLoaded) - { - UpdateItems(Items); - } - } - - private void CheckNull() - { - if (_panelMain == null || _progressBarBack == null) throw new Exception(); - } - - public int StepIndex { get; private set; } - - public List Items { get; set; } = new List(); - - private void UpdateItems(IReadOnlyCollection list) - { - if (list == null) return; - _panelMain.Children.Clear(); - - var index = 1; - foreach (var item in list) - { - item.Index = index; - item.IndexStr = $"{Properties.Langs.Lang.Step}{index}"; - _panelMain.Children.Add(item); - index++; - } - - if (list.FirstOrDefault() is StepItem stepItem) - { - stepItem.Status = false; - } - } - - protected override void OnRender(DrawingContext drawingContext) - { - base.OnRender(drawingContext); - - var colCount = _panelMain.Children.Count; - if (colCount <= 0) return; - _progressBarBack.Width = (colCount - 1) * (ActualWidth / colCount); - _progressBarBack.Value = 0; - _progressBarBack.Maximum = colCount - 1; - } - - public void Next() - { - StepIndex++; - if (StepIndex >= _panelMain.Children.Count) - { - StepIndex = _panelMain.Children.Count - 1; - return; - } - RaiseEvent(new FunctionEventArgs(StepChangedEvent, this) - { - Info = StepIndex - }); - if (_panelMain.Children[StepIndex - 1] is StepItem stepItemFinished) - stepItemFinished.Status = true; - if (_panelMain.Children[StepIndex] is StepItem stepItemSelected) - stepItemSelected.Status = false; - _progressBarBack.BeginAnimation(RangeBase.ValueProperty, AnimationHelper.CreateAnimation(StepIndex)); - } - - public void Prev() - { - StepIndex--; - if (StepIndex < 0) - { - StepIndex = 0; - return; - } - RaiseEvent(new FunctionEventArgs(StepChangedEvent, this) - { - Info = StepIndex - }); - if (_panelMain.Children[StepIndex + 1] is StepItem stepItemFinished) - stepItemFinished.Status = null; - if (_panelMain.Children[StepIndex] is StepItem stepItemSelected) - stepItemSelected.Status = false; - _progressBarBack.BeginAnimation(RangeBase.ValueProperty, AnimationHelper.CreateAnimation(StepIndex)); - } - } -} \ No newline at end of file diff --git a/HandyControl/Controls/Steps/StepItem.cs b/HandyControl/Controls/Steps/StepItem.cs deleted file mode 100644 index 86deb2fe..00000000 --- a/HandyControl/Controls/Steps/StepItem.cs +++ /dev/null @@ -1,70 +0,0 @@ -using System.Windows; -using System.Windows.Controls; -using System.Windows.Media; -using HandyControl.Data; -using HandyControl.Tools; - -// ReSharper disable once CheckNamespace -namespace HandyControl.Controls -{ - /// - /// 步骤条单元项 - /// - public class StepItem : Control - { - internal static readonly DependencyProperty IndexProperty = DependencyProperty.Register( - "Index", typeof(int), typeof(StepItem), new PropertyMetadata(-1)); - - internal int Index - { - get => (int)GetValue(IndexProperty); - set => SetValue(IndexProperty, value); - } - - internal static readonly DependencyProperty IndexStrProperty = DependencyProperty.Register( - "IndexStr", typeof(string), typeof(StepItem), new PropertyMetadata(default(string))); - - internal string IndexStr - { - get => (string)GetValue(IndexStrProperty); - set => SetValue(IndexStrProperty, value); - } - - public static readonly DependencyProperty TitleProperty = DependencyProperty.Register( - "Title", typeof(string), typeof(StepItem), new PropertyMetadata(default(string))); - - public string Title - { - get => (string)GetValue(TitleProperty); - set => SetValue(TitleProperty, value); - } - - private bool? _status; - - public bool? Status - { - get => _status; - set - { - _status = value; - UpdateStatus(); - } - } - - private void UpdateStatus() - { - if (Status == true) - { - Foreground = ResourceHelper.GetResource(ResourceToken.PrimaryTextBrush); - } - else if (Status == false) - { - Foreground = ResourceHelper.GetResource(ResourceToken.PrimaryBrush); - } - else - { - Foreground = ResourceHelper.GetResource(ResourceToken.ThirdlyTextBrush); - } - } - } -} \ No newline at end of file diff --git a/HandyControl/Controls/TransitioningContentControl.cs b/HandyControl/Controls/TransitioningContentControl.cs index 6a0e84f8..4712eb7a 100644 --- a/HandyControl/Controls/TransitioningContentControl.cs +++ b/HandyControl/Controls/TransitioningContentControl.cs @@ -1,4 +1,5 @@ using System; +using System.ComponentModel; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Windows; @@ -18,7 +19,10 @@ namespace HandyControl.Controls public TransitioningContentControl() { - DefaultStyleKey = typeof(TransitioningContentControl); + if (!DesignerProperties.GetIsInDesignMode(this)) + { + DefaultStyleKey = typeof(TransitioningContentControl); + } } private Storyboard CurrentTransition @@ -43,6 +47,8 @@ namespace HandyControl.Controls public override void OnApplyTemplate() { + if (DesignerProperties.GetIsInDesignMode(this)) return; + if (IsTransitioning) AbortTransition(); diff --git a/HandyControl/Data/Enum/StepStatus.cs b/HandyControl/Data/Enum/StepStatus.cs new file mode 100644 index 00000000..1c46c467 --- /dev/null +++ b/HandyControl/Data/Enum/StepStatus.cs @@ -0,0 +1,23 @@ +namespace HandyControl.Data +{ + /// + /// 步骤状态 + /// + public enum StepStatus + { + /// + /// 完成 + /// + Complete, + + /// + /// 进行中 + /// + UnderWay, + + /// + /// 等待中 + /// + Waiting + } +} \ No newline at end of file diff --git a/HandyControl/HandyControl.csproj b/HandyControl/HandyControl.csproj index 465401dc..a480ea86 100644 --- a/HandyControl/HandyControl.csproj +++ b/HandyControl/HandyControl.csproj @@ -65,9 +65,12 @@ + + + @@ -110,8 +113,6 @@ - - @@ -266,6 +267,10 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + Designer MSBuild:Compile diff --git a/HandyControl/Properties/Langs/Lang.Designer.cs b/HandyControl/Properties/Langs/Lang.Designer.cs index 9b13e3fc..e393484a 100644 --- a/HandyControl/Properties/Langs/Lang.Designer.cs +++ b/HandyControl/Properties/Langs/Lang.Designer.cs @@ -47,7 +47,7 @@ namespace HandyControl.Properties.Langs { } /// - /// 重写当前线程的 CurrentUICulture 属性 + /// 使用此强类型资源类,为所有资源查找 /// 重写当前线程的 CurrentUICulture 属性。 /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] @@ -78,6 +78,24 @@ namespace HandyControl.Properties.Langs { } } + /// + /// 查找类似 无法自注册复合命令 的本地化字符串。 + /// + public static string CannotRegisterCompositeCommandInItself { + get { + return ResourceManager.GetString("CannotRegisterCompositeCommandInItself", resourceCulture); + } + } + + /// + /// 查找类似 不能注册同一命令两次 的本地化字符串。 + /// + public static string CannotRegisterSameCommandTwice { + get { + return ResourceManager.GetString("CannotRegisterSameCommandTwice", resourceCulture); + } + } + /// /// 查找类似 清空 的本地化字符串。 /// @@ -249,15 +267,6 @@ namespace HandyControl.Properties.Langs { } } - /// - /// 查找类似 步骤 的本地化字符串。 - /// - public static string Step { - get { - return ResourceManager.GetString("Step", resourceCulture); - } - } - /// /// 查找类似 提示 的本地化字符串。 /// diff --git a/HandyControl/Properties/Langs/Lang.en.resx b/HandyControl/Properties/Langs/Lang.en.resx index b6ba11e5..162027ec 100644 --- a/HandyControl/Properties/Langs/Lang.en.resx +++ b/HandyControl/Properties/Langs/Lang.en.resx @@ -165,9 +165,6 @@ Clear - - Step - Close @@ -195,4 +192,10 @@ format error + + Cannot Register Composite Command In It self + + + Cannot Register Same Command Twice + \ No newline at end of file diff --git a/HandyControl/Properties/Langs/Lang.resx b/HandyControl/Properties/Langs/Lang.resx index 7c115a14..078dabdf 100644 --- a/HandyControl/Properties/Langs/Lang.resx +++ b/HandyControl/Properties/Langs/Lang.resx @@ -145,9 +145,6 @@ 清空 - - 步骤 - 关闭 @@ -175,4 +172,10 @@ 格式错误 + + 无法自注册复合命令 + + + 不能注册同一命令两次 + \ No newline at end of file diff --git a/HandyControl/Themes/Styles/Base/StepBarBaseStyle.xaml b/HandyControl/Themes/Styles/Base/StepBarBaseStyle.xaml new file mode 100644 index 00000000..06e48c1c --- /dev/null +++ b/HandyControl/Themes/Styles/Base/StepBarBaseStyle.xaml @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/HandyControl/Themes/Styles/ProgressBar.xaml b/HandyControl/Themes/Styles/ProgressBar.xaml index f6916e85..ce272123 100644 --- a/HandyControl/Themes/Styles/ProgressBar.xaml +++ b/HandyControl/Themes/Styles/ProgressBar.xaml @@ -206,11 +206,18 @@ - - - + + + + + + + + + + diff --git a/HandyControl/Themes/Styles/StepBar.xaml b/HandyControl/Themes/Styles/StepBar.xaml index 898f8e22..ad8946a0 100644 --- a/HandyControl/Themes/Styles/StepBar.xaml +++ b/HandyControl/Themes/Styles/StepBar.xaml @@ -2,39 +2,9 @@ xmlns:controls="clr-namespace:HandyControl.Controls"> - - + - - - +