Skip to content

Commit

Permalink
Merge pull request #2523 from MahApps/2485-Flyout-improvement
Browse files Browse the repository at this point in the history
flyout improvement caused by #2485
  • Loading branch information
punker76 committed Jun 1, 2016
2 parents 105d9b7 + 692812e commit d60bd41
Show file tree
Hide file tree
Showing 11 changed files with 196 additions and 114 deletions.
44 changes: 44 additions & 0 deletions MahApps.Metro/Controls/CloseCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using System;
using System.Windows.Input;

namespace MahApps.Metro.Controls
{
internal class CloseCommand : ICommand
{
private readonly Func<object, bool> canExecute;
private readonly Action<object> executeAction;

public CloseCommand(Func<object, bool> canExecute, Action<object> executeAction)
{
this.canExecute = canExecute;
this.executeAction = executeAction;
}

/// <summary>
/// Defines the method that determines whether the command can execute in its current state.
/// </summary>
/// <returns>
/// true if this command can be executed; otherwise, false.
/// </returns>
/// <param name="parameter">Data used by the command. If the command does not require data to be passed, this object can be set to null.</param>
public bool CanExecute(object parameter)
{
return this.canExecute != null && this.canExecute(parameter);
}

/// <summary>
/// Defines the method to be called when the command is invoked.
/// </summary>
/// <param name="parameter">Data used by the command. If the command does not require data to be passed, this object can be set to null.</param>
public void Execute(object parameter)
{
this.executeAction?.Invoke(parameter);
}

public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
}
}
80 changes: 47 additions & 33 deletions MahApps.Metro/Controls/Flyout.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ namespace MahApps.Metro.Controls
[TemplatePart(Name = "PART_BackHeaderText", Type = typeof(TextBlock))]
[TemplatePart(Name = "PART_WindowTitleThumb", Type = typeof(Thumb))]
[TemplatePart(Name = "PART_Root", Type = typeof(Grid))]
[TemplatePart(Name = "PART_Header", Type = typeof(ContentPresenter))]
[TemplatePart(Name = "PART_Content", Type = typeof(ContentPresenter))]
[TemplatePart(Name = "PART_Header", Type = typeof(FrameworkElement))]
[TemplatePart(Name = "PART_Content", Type = typeof(FrameworkElement))]
public class Flyout : ContentControl
{
/// <summary>
Expand Down Expand Up @@ -59,6 +59,7 @@ public event RoutedEventHandler ClosingFinished

public static readonly DependencyProperty CloseCommandProperty = DependencyProperty.RegisterAttached("CloseCommand", typeof(ICommand), typeof(Flyout), new UIPropertyMetadata(null));
public static readonly DependencyProperty CloseCommandParameterProperty = DependencyProperty.Register("CloseCommandParameter", typeof(object), typeof(Flyout), new PropertyMetadata(null));
internal static readonly DependencyProperty InternalCloseCommandProperty = DependencyProperty.Register("InternalCloseCommand", typeof(ICommand), typeof(Flyout));

public static readonly DependencyProperty ThemeProperty = DependencyProperty.Register("Theme", typeof(FlyoutTheme), typeof(Flyout), new FrameworkPropertyMetadata(FlyoutTheme.Dark, ThemeChanged));
public static readonly DependencyProperty ExternalCloseButtonProperty = DependencyProperty.Register("ExternalCloseButton", typeof(MouseButton), typeof(Flyout), new PropertyMetadata(MouseButton.Left));
Expand Down Expand Up @@ -126,6 +127,15 @@ public object CloseCommandParameter
set { SetValue(CloseCommandParameterProperty, value); }
}

/// <summary>
/// Gets/sets a command which will be executed if the close button was clicked.
/// </summary>
internal ICommand InternalCloseCommand
{
get { return (ICommand)GetValue(InternalCloseCommandProperty); }
set { SetValue(InternalCloseCommandProperty, value); }
}

/// <summary>
/// A DataTemplate for the flyout's header.
/// </summary>
Expand Down Expand Up @@ -252,12 +262,43 @@ public bool AllowFocusElement
set { this.SetValue(AllowFocusElementProperty, value); }
}

static Flyout()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(Flyout), new FrameworkPropertyMetadata(typeof(Flyout)));
}

public Flyout()
{
this.InternalCloseCommand = new CloseCommand(InternalCloseCommandCanExecute, InternalCloseCommandExecuteAction);
this.Loaded += (sender, args) => this.UpdateFlyoutTheme();
this.InitializeAutoCloseTimer();
}

private void InternalCloseCommandExecuteAction(object o)
{
var closeCommand = this.CloseCommand;
// close the Flyout only if there is no command
if (closeCommand == null)
{
this.IsOpen = false;
}
else
{
var closeCommandParameter = this.CloseCommandParameter ?? this;
if (closeCommand.CanExecute(closeCommandParameter))
{
// force the command handler to run
closeCommand.Execute(closeCommandParameter);
}
}
}

private bool InternalCloseCommandCanExecute(object o)
{
var closeCommand = this.CloseCommand;
return closeCommand == null || closeCommand.CanExecute(this.CloseCommandParameter ?? this);
}

private void InitializeAutoCloseTimer()
{
this.StopAutoCloseTimer();
Expand Down Expand Up @@ -589,11 +630,6 @@ private static void PositionChanged(DependencyObject dependencyObject, Dependenc
}
}

static Flyout()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(Flyout), new FrameworkPropertyMetadata(typeof(Flyout)));
}

DispatcherTimer autoCloseTimer;
Grid flyoutRoot;
Storyboard hideStoryboard;
Expand All @@ -602,10 +638,9 @@ static Flyout()
SplineDoubleKeyFrame showFrame;
SplineDoubleKeyFrame showFrameY;
SplineDoubleKeyFrame fadeOutFrame;
ContentPresenter flyoutHeader;
ContentPresenter flyoutContent;
FrameworkElement flyoutHeader;
FrameworkElement flyoutContent;
Thumb windowTitleThumb;
Button backButton;

public override void OnApplyTemplate()
{
Expand All @@ -617,16 +652,9 @@ public override void OnApplyTemplate()
return;
}

this.flyoutHeader = this.GetTemplateChild("PART_Header") as ContentPresenter;
this.flyoutContent = this.GetTemplateChild("PART_Content") as ContentPresenter;

this.flyoutHeader = this.GetTemplateChild("PART_Header") as FrameworkElement;
this.flyoutHeader?.ApplyTemplate();
this.backButton = this.flyoutHeader?.FindChild<Button>("PART_BackButton");
if (this.backButton != null)
{
this.backButton.Click -= this.BackButtonClick;
this.backButton.Click += this.BackButtonClick;
}
this.flyoutContent = this.GetTemplateChild("PART_Content") as FrameworkElement;

this.windowTitleThumb = this.GetTemplateChild("PART_WindowTitleThumb") as Thumb;
if (this.windowTitleThumb != null)
Expand Down Expand Up @@ -659,10 +687,6 @@ public override void OnApplyTemplate()

protected internal void CleanUp(FlyoutsControl flyoutsControl)
{
if (this.backButton != null)
{
this.backButton.Click -= this.BackButtonClick;
}
if (this.windowTitleThumb != null)
{
this.windowTitleThumb.PreviewMouseLeftButtonUp -= this.WindowTitleThumbOnPreviewMouseLeftButtonUp;
Expand All @@ -673,16 +697,6 @@ protected internal void CleanUp(FlyoutsControl flyoutsControl)
this.parentWindow = null;
}

private void BackButtonClick(object sender, RoutedEventArgs e)
{
// close the Flyout only if there is no command
var closeCommand = this.CloseCommand;
if (closeCommand == null)
{
this.IsOpen = false;
}
}

private void WindowTitleThumbOnPreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
var window = this.ParentWindow;
Expand Down
19 changes: 19 additions & 0 deletions MahApps.Metro/Controls/Helper/ControlsHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ private static void HeaderFontSizePropertyChangedCallback(DependencyObject depen

[Category(AppName.MahApps)]
[AttachedPropertyBrowsableForType(typeof(HeaderedContentControl))]
[AttachedPropertyBrowsableForType(typeof(Flyout))]
public static double GetHeaderFontSize(UIElement element)
{
return (double)element.GetValue(HeaderFontSizeProperty);
Expand All @@ -121,6 +122,7 @@ public static void SetHeaderFontSize(UIElement element, double value)

[Category(AppName.MahApps)]
[AttachedPropertyBrowsableForType(typeof(HeaderedContentControl))]
[AttachedPropertyBrowsableForType(typeof(Flyout))]
public static FontStretch GetHeaderFontStretch(UIElement element)
{
return (FontStretch)element.GetValue(HeaderFontStretchProperty);
Expand All @@ -136,6 +138,7 @@ public static void SetHeaderFontStretch(UIElement element, FontStretch value)

[Category(AppName.MahApps)]
[AttachedPropertyBrowsableForType(typeof(HeaderedContentControl))]
[AttachedPropertyBrowsableForType(typeof(Flyout))]
public static FontWeight GetHeaderFontWeight(UIElement element)
{
return (FontWeight)element.GetValue(HeaderFontWeightProperty);
Expand All @@ -146,6 +149,22 @@ public static void SetHeaderFontWeight(UIElement element, FontWeight value)
element.SetValue(HeaderFontWeightProperty, value);
}

public static readonly DependencyProperty HeaderMarginProperty =
DependencyProperty.RegisterAttached("HeaderMargin", typeof(Thickness), typeof(ControlsHelper), new UIPropertyMetadata(new Thickness()));

[Category(AppName.MahApps)]
[AttachedPropertyBrowsableForType(typeof(HeaderedContentControl))]
[AttachedPropertyBrowsableForType(typeof(Flyout))]
public static Thickness GetHeaderMargin(UIElement element)
{
return (Thickness)element.GetValue(HeaderMarginProperty);
}

public static void SetHeaderMargin(UIElement element, Thickness value)
{
element.SetValue(HeaderMarginProperty, value);
}

/// <summary>
/// This property can be used to set the button width (PART_ClearText) of TextBox, PasswordBox, ComboBox, NumericUpDown
/// </summary>
Expand Down
44 changes: 2 additions & 42 deletions MahApps.Metro/Controls/MetroTabItem.cs
Original file line number Diff line number Diff line change
@@ -1,49 +1,9 @@
using System;
using System.Windows;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace MahApps.Metro.Controls
{
internal class MetroTabItemCloseCommand : ICommand
{
private readonly Func<object, bool> canExecute;
private readonly Action<object> executeAction;

public MetroTabItemCloseCommand(Func<object, bool> canExecute, Action<object> executeAction)
{
this.canExecute = canExecute;
this.executeAction = executeAction;
}

/// <summary>
/// Defines the method that determines whether the command can execute in its current state.
/// </summary>
/// <returns>
/// true if this command can be executed; otherwise, false.
/// </returns>
/// <param name="parameter">Data used by the command. If the command does not require data to be passed, this object can be set to null.</param>
public bool CanExecute(object parameter)
{
return this.canExecute != null && this.canExecute(parameter);
}

/// <summary>
/// Defines the method to be called when the command is invoked.
/// </summary>
/// <param name="parameter">Data used by the command. If the command does not require data to be passed, this object can be set to null.</param>
public void Execute(object parameter)
{
this.executeAction?.Invoke(parameter);
}

public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
}

/// <summary>
/// An extended TabItem with a metro style.
/// </summary>
Expand All @@ -52,7 +12,7 @@ public class MetroTabItem : TabItem
public MetroTabItem()
{
DefaultStyleKey = typeof(MetroTabItem);
this.InternalCloseTabCommand = new MetroTabItemCloseCommand(InternalCloseTabCommandCanExecute, InternalCloseTabCommandExecuteAction);
this.InternalCloseTabCommand = new CloseCommand(InternalCloseTabCommandCanExecute, InternalCloseTabCommandExecuteAction);
}

private void InternalCloseTabCommandExecuteAction(object o)
Expand Down
1 change: 1 addition & 0 deletions MahApps.Metro/MahApps.Metro.NET45.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@
<Compile Include="Behaviours\TabControlSelectFirstVisibleTabBehavior.cs" />
<Compile Include="Behaviours\WindowsSettingBehaviour.cs" />
<Compile Include="Controls\ButtonsAlignment.cs" />
<Compile Include="Controls\CloseCommand.cs" />
<Compile Include="Controls\ContentControlEx.cs" />
<Compile Include="Controls\Extensions.cs" />
<Compile Include="Controls\IconPacks\PackIconMaterial.cs" />
Expand Down
1 change: 1 addition & 0 deletions MahApps.Metro/MahApps.Metro.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@
<Compile Include="Actions\SetFlyoutOpenAction.cs" />
<Compile Include="Behaviours\BindableResourceBehavior.cs" />
<Compile Include="Behaviours\BorderlessWindowBehavior.cs" />
<Compile Include="Controls\CloseCommand.cs" />
<Compile Include="Controls\Extensions.cs" />
<Compile Include="Controls\Helper\AmPmComparer.cs" />
<Compile Include="Controls\ButtonsAlignment.cs" />
Expand Down
Loading

0 comments on commit d60bd41

Please sign in to comment.