diff --git a/docs/release-notes/1.5.0.md b/docs/release-notes/1.5.0.md index 3c47770376..5edb81f527 100644 --- a/docs/release-notes/1.5.0.md +++ b/docs/release-notes/1.5.0.md @@ -17,7 +17,28 @@ - New `Badged` control. Thx to @ButchersBoy ![image](https://cloud.githubusercontent.com/assets/658431/23340345/d7dc4c86-fc34-11e6-838b-1ebee9381c7d.png) - The `ControlsHelper.CornerRadius` can now used for `SplitButton` and `DropDownButton`. - +- New underline types for `TabControl` and `MetroTabControl` [#2902](https://github.com/MahApps/MahApps.Metro/pull/2902) + + Adds a new `Underlined` attached property to `TabControlHelper` which controls the type of the underline type. The old `IsUnderlined` property is now obsolete. + ``` + /// + /// Specifies the underline position of a TabControl. + /// + public enum UnderlinedType + { + None, // nothing + TabItems, // the old behavior with `IsUnderlined="True"` + SelectedTabItem, // selected TabItem underlined + underline hover effect for unselected items + TabPanel // underlined TabPanel and selected/hovered TabItem + } + ``` + + Add also new `Brush` attached properties to enable easy changing the underline brushes. + ``` + TabControlHelper.UnderlineBrush + TabControlHelper.UnderlineSelectedBrush + TabControlHelper.UnderlineMouseOverBrush + TabControlHelper.UnderlineMouseOverSelectedBrush + ``` + ![mahapps_newunderline4](https://cloud.githubusercontent.com/assets/658431/24204520/0e6f3cbc-0f19-11e7-8a2b-f40752918a96.gif) ## Closed Issues @@ -33,3 +54,4 @@ - [#2792](https://github.com/MahApps/MahApps.Metro/issues/2792) Win32Exception on closing window - [#2886](https://github.com/MahApps/MahApps.Metro/issues/2886) NumericUpDown: HasDecimals=False & using a bound StringFormat allows to enter a decimal point [@davericardo](https://github.com/davericardo) - [#2885](https://github.com/MahApps/MahApps.Metro/issues/2885) [Bug] Badged Control Causes Window Loading to Hang +- [#2895](https://github.com/MahApps/MahApps.Metro/issues/2895) [RFC] [Enhancement] Proposed TabControlHelper.IsUnderlined Change diff --git a/src/MahApps.Metro.Samples/MahApps.Metro.Demo/MahApps.Metro.Demo.Shared/ExampleViews/TabControlExamples.xaml b/src/MahApps.Metro.Samples/MahApps.Metro.Demo/MahApps.Metro.Demo.Shared/ExampleViews/TabControlExamples.xaml index 8fba7583e8..4292167335 100644 --- a/src/MahApps.Metro.Samples/MahApps.Metro.Demo/MahApps.Metro.Demo.Shared/ExampleViews/TabControlExamples.xaml +++ b/src/MahApps.Metro.Samples/MahApps.Metro.Demo/MahApps.Metro.Demo.Shared/ExampleViews/TabControlExamples.xaml @@ -10,12 +10,49 @@ d:DesignWidth="800" d:DataContext="{d:DesignInstance MetroDemo:MainWindowViewModel}"> + + + + + + + + + + + + + - + - - + + + diff --git a/src/MahApps.Metro/MahApps.Metro.Shared/Controls/Helper/TabControlHelper.cs b/src/MahApps.Metro/MahApps.Metro.Shared/Controls/Helper/TabControlHelper.cs index e99ac86aae..40f225ba38 100644 --- a/src/MahApps.Metro/MahApps.Metro.Shared/Controls/Helper/TabControlHelper.cs +++ b/src/MahApps.Metro/MahApps.Metro.Shared/Controls/Helper/TabControlHelper.cs @@ -1,36 +1,169 @@ -using System.Windows; +using System; +using System.ComponentModel; +using System.Windows; using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using System.Windows.Media; namespace MahApps.Metro.Controls { - using System.ComponentModel; + /// + /// Specifies the underline position of a TabControl. + /// + public enum UnderlinedType + { + None, + TabItems, + SelectedTabItem, + TabPanel + } public static class TabControlHelper { /// - /// Defines whether the underline below the is shown or not. + /// Defines whether the underline below the is shown or not. /// + [Obsolete(@"This property will be deleted in the next release. You should now use the Underlined attached property.")] public static readonly DependencyProperty IsUnderlinedProperty = - DependencyProperty.RegisterAttached("IsUnderlined", typeof(bool), typeof(TabControlHelper), new PropertyMetadata(false)); + DependencyProperty.RegisterAttached("IsUnderlined", + typeof(bool), + typeof(TabControlHelper), + new PropertyMetadata(false, + (o, e) => + { + var element = o as UIElement; + if (element != null && e.OldValue != e.NewValue && e.NewValue is bool) + { + TabControlHelper.SetUnderlined(element, (bool)e.NewValue ? UnderlinedType.TabItems : UnderlinedType.None); + } + })); [Category(AppName.MahApps)] [AttachedPropertyBrowsableForType(typeof(TabControl))] - [AttachedPropertyBrowsableForType(typeof(TabItem))] + [Obsolete(@"This property will be deleted in the next release. You should now use the Underlined attached property.")] public static bool GetIsUnderlined(UIElement element) { return (bool)element.GetValue(IsUnderlinedProperty); } + [Obsolete(@"This property will be deleted in the next release. You should now use the Underlined attached property.")] public static void SetIsUnderlined(UIElement element, bool value) { element.SetValue(IsUnderlinedProperty, value); } + /// + /// Defines whether the underline below the or is shown or not. + /// + public static readonly DependencyProperty UnderlinedProperty = + DependencyProperty.RegisterAttached("Underlined", + typeof(UnderlinedType), + typeof(TabControlHelper), + new PropertyMetadata(UnderlinedType.None)); + + [Category(AppName.MahApps)] + [AttachedPropertyBrowsableForType(typeof(TabControl))] + public static UnderlinedType GetUnderlined(UIElement element) + { + return (UnderlinedType)element.GetValue(UnderlinedProperty); + } + + public static void SetUnderlined(UIElement element, UnderlinedType value) + { + element.SetValue(UnderlinedProperty, value); + } + + /// + /// Defines the underline brush below the or . + /// + public static readonly DependencyProperty UnderlineBrushProperty = + DependencyProperty.RegisterAttached("UnderlineBrush", + typeof(Brush), + typeof(TabControlHelper), + new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.SubPropertiesDoNotAffectRender)); + + [Category(AppName.MahApps)] + [AttachedPropertyBrowsableForType(typeof(TabControl))] + public static Brush GetUnderlineBrush(UIElement element) + { + return (Brush)element.GetValue(UnderlineBrushProperty); + } + + public static void SetUnderlineBrush(UIElement element, Brush value) + { + element.SetValue(UnderlineBrushProperty, value); + } + + /// + /// Defines the underline brush below the or of an selected item. + /// + public static readonly DependencyProperty UnderlineSelectedBrushProperty = + DependencyProperty.RegisterAttached("UnderlineSelectedBrush", + typeof(Brush), + typeof(TabControlHelper), + new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.SubPropertiesDoNotAffectRender)); + + [Category(AppName.MahApps)] + [AttachedPropertyBrowsableForType(typeof(TabControl))] + public static Brush GetUnderlineSelectedBrush(UIElement element) + { + return (Brush)element.GetValue(UnderlineSelectedBrushProperty); + } + + public static void SetUnderlineSelectedBrush(UIElement element, Brush value) + { + element.SetValue(UnderlineSelectedBrushProperty, value); + } + + /// + /// Defines the underline brush below the or if the mouse is over an item. + /// + public static readonly DependencyProperty UnderlineMouseOverBrushProperty = + DependencyProperty.RegisterAttached("UnderlineMouseOverBrush", + typeof(Brush), + typeof(TabControlHelper), + new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.SubPropertiesDoNotAffectRender)); + + [Category(AppName.MahApps)] + [AttachedPropertyBrowsableForType(typeof(TabControl))] + public static Brush GetUnderlineMouseOverBrush(UIElement element) + { + return (Brush)element.GetValue(UnderlineMouseOverBrushProperty); + } + + public static void SetUnderlineMouseOverBrush(UIElement element, Brush value) + { + element.SetValue(UnderlineMouseOverBrushProperty, value); + } + + /// + /// Defines the underline brush below the or if the mouse is over a selected item. + /// + public static readonly DependencyProperty UnderlineMouseOverSelectedBrushProperty = + DependencyProperty.RegisterAttached("UnderlineMouseOverSelectedBrush", + typeof(Brush), + typeof(TabControlHelper), + new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.SubPropertiesDoNotAffectRender)); + + [Category(AppName.MahApps)] + [AttachedPropertyBrowsableForType(typeof(TabControl))] + public static Brush GetUnderlineMouseOverSelectedBrush(UIElement element) + { + return (Brush)element.GetValue(UnderlineMouseOverSelectedBrushProperty); + } + + public static void SetUnderlineMouseOverSelectedBrush(UIElement element, Brush value) + { + element.SetValue(UnderlineMouseOverSelectedBrushProperty, value); + } + /// /// This property can be used to set the Transition for animated TabControls /// public static readonly DependencyProperty TransitionProperty = - DependencyProperty.RegisterAttached("Transition", typeof(TransitionType), typeof(TabControlHelper), + DependencyProperty.RegisterAttached("Transition", + typeof(TransitionType), + typeof(TabControlHelper), new FrameworkPropertyMetadata(TransitionType.Default, FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.Inherits)); [Category(AppName.MahApps)] diff --git a/src/MahApps.Metro/MahApps.Metro.Shared/Controls/Underline.cs b/src/MahApps.Metro/MahApps.Metro.Shared/Controls/Underline.cs new file mode 100644 index 0000000000..0b9d1c3e76 --- /dev/null +++ b/src/MahApps.Metro/MahApps.Metro.Shared/Controls/Underline.cs @@ -0,0 +1,96 @@ +using System; +using System.Windows; +using System.Windows.Controls; + +namespace MahApps.Metro.Controls +{ + [TemplatePart(Name = UnderlineBorderPartName, Type = typeof(Border))] + public class Underline : ContentControl + { + public const string UnderlineBorderPartName = "PART_UnderlineBorder"; + private Border _underlineBorder; + + public static readonly DependencyProperty PlacementProperty = + DependencyProperty.Register(nameof(Placement), + typeof(Dock), + typeof(Underline), + new PropertyMetadata(default(Dock), (o, e) => { (o as Underline)?.ApplyBorderProperties(); })); + + public Dock Placement + { + get { return (Dock)this.GetValue(PlacementProperty); } + set { this.SetValue(PlacementProperty, value); } + } + + public static readonly DependencyProperty LineThicknessProperty = + DependencyProperty.Register(nameof(LineThickness), + typeof(double), + typeof(Underline), + new PropertyMetadata(1d, (o, e) => { (o as Underline)?.ApplyBorderProperties(); })); + + public double LineThickness + { + get { return (double)this.GetValue(LineThicknessProperty); } + set { this.SetValue(LineThicknessProperty, value); } + } + + public static readonly DependencyProperty LineExtentProperty = + DependencyProperty.Register(nameof(LineExtent), + typeof(double), + typeof(Underline), + new PropertyMetadata(Double.NaN, (o, e) => { (o as Underline)?.ApplyBorderProperties(); })); + + public double LineExtent + { + get { return (double)this.GetValue(LineExtentProperty); } + set { this.SetValue(LineExtentProperty, value); } + } + + static Underline() + { + DefaultStyleKeyProperty.OverrideMetadata(typeof(Underline), new FrameworkPropertyMetadata(typeof(Underline))); + } + + public override void OnApplyTemplate() + { + base.OnApplyTemplate(); + + this._underlineBorder = this.GetTemplateChild(UnderlineBorderPartName) as Border; + this.ApplyBorderProperties(); + } + + private void ApplyBorderProperties() + { + if (this._underlineBorder == null) + { + return; + } + + this._underlineBorder.Height = Double.NaN; + this._underlineBorder.Width = Double.NaN; + this._underlineBorder.BorderThickness = new Thickness(); + switch (this.Placement) + { + case Dock.Left: + this._underlineBorder.Width = this.LineExtent; + this._underlineBorder.BorderThickness = new Thickness(this.LineThickness, 0d, 0d, 0d); + break; + case Dock.Top: + this._underlineBorder.Height = this.LineExtent; + this._underlineBorder.BorderThickness = new Thickness(0d, this.LineThickness, 0d, 0d); + break; + case Dock.Right: + this._underlineBorder.Width = this.LineExtent; + this._underlineBorder.BorderThickness = new Thickness(0d, 0d, this.LineThickness, 0d); + break; + case Dock.Bottom: + this._underlineBorder.Height = this.LineExtent; + this._underlineBorder.BorderThickness = new Thickness(0d, 0d, 0d, this.LineThickness); + break; + default: + throw new ArgumentOutOfRangeException(); + } + this.InvalidateVisual(); + } + } +} \ No newline at end of file diff --git a/src/MahApps.Metro/MahApps.Metro.Shared/MahApps.Metro.Shared.projitems b/src/MahApps.Metro/MahApps.Metro.Shared/MahApps.Metro.Shared.projitems index 74abb43b7a..3347a1cc4e 100644 --- a/src/MahApps.Metro/MahApps.Metro.Shared/MahApps.Metro.Shared.projitems +++ b/src/MahApps.Metro/MahApps.Metro.Shared/MahApps.Metro.Shared.projitems @@ -131,6 +131,7 @@ + diff --git a/src/MahApps.Metro/MahApps.Metro/MahApps.Metro.NET40.csproj b/src/MahApps.Metro/MahApps.Metro/MahApps.Metro.NET40.csproj index 7143eeabcf..932b9090a6 100644 --- a/src/MahApps.Metro/MahApps.Metro/MahApps.Metro.NET40.csproj +++ b/src/MahApps.Metro/MahApps.Metro/MahApps.Metro.NET40.csproj @@ -536,6 +536,10 @@ MSBuild:Compile Designer + + MSBuild:Compile + Designer + MSBuild:Compile Designer diff --git a/src/MahApps.Metro/MahApps.Metro/MahApps.Metro.NET45.csproj b/src/MahApps.Metro/MahApps.Metro/MahApps.Metro.NET45.csproj index eaa1bb456f..3898758e78 100644 --- a/src/MahApps.Metro/MahApps.Metro/MahApps.Metro.NET45.csproj +++ b/src/MahApps.Metro/MahApps.Metro/MahApps.Metro.NET45.csproj @@ -536,6 +536,10 @@ MSBuild:Compile Designer + + Designer + MSBuild:Compile + MSBuild:Compile Designer diff --git a/src/MahApps.Metro/MahApps.Metro/Styles/Controls.TabControl.xaml b/src/MahApps.Metro/MahApps.Metro/Styles/Controls.TabControl.xaml index c7712af857..c3a20523af 100644 --- a/src/MahApps.Metro/MahApps.Metro/Styles/Controls.TabControl.xaml +++ b/src/MahApps.Metro/MahApps.Metro/Styles/Controls.TabControl.xaml @@ -5,7 +5,11 @@ + + \ No newline at end of file