Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix WindowCommandsItem visibility #2175

Merged
merged 2 commits into from
Oct 23, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 88 additions & 38 deletions MahApps.Metro/Controls/WindowCommands.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
using System.Collections.Specialized;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;

Expand Down Expand Up @@ -157,13 +161,60 @@ protected override bool IsItemItsOwnContainerOverride(object item)
protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
{
base.PrepareContainerForItemOverride(element, item);

this.AttachVisibilityHandler(element as WindowCommandsItem, item as UIElement);
if ((Items.Count > 0) && (ReferenceEquals(item, Items[Items.Count - 1])))
{
ResetSeparators(false);
}
}

protected override void ClearContainerForItemOverride(DependencyObject element, object item)
{
base.ClearContainerForItemOverride(element, item);
this.DetachVisibilityHandler(element as WindowCommandsItem);
ResetSeparators(false);
}

private void AttachVisibilityHandler(WindowCommandsItem container, UIElement item)
{
if (container != null)
{
// hide the container, if there is no UIElement
if (null == item)
{
container.Visibility = Visibility.Collapsed;
return;
}

container.Visibility = item.Visibility;
var isVisibilityNotifier = new PropertyChangeNotifier(item, UIElement.VisibilityProperty);
isVisibilityNotifier.ValueChanged += VisibilityPropertyChanged;
container.VisibilityPropertyChangeNotifier = isVisibilityNotifier;
}
}

private void DetachVisibilityHandler(WindowCommandsItem container)
{
if (container != null)
{
container.VisibilityPropertyChangeNotifier = null;
}
}

private void VisibilityPropertyChanged(object sender, EventArgs e)
{
var item = sender as UIElement;
if (item != null)
{
var container = GetWindowCommandsItem(item);
if (container != null)
{
container.Visibility = item.Visibility;
ResetSeparators();
}
}
}

protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e)
{
base.OnItemsChanged(e);
Expand All @@ -172,25 +223,43 @@ protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e)

private void ResetSeparators(bool reset = true)
{
if (Items.Count == 0)
{
return;
}

var windowCommandsItems = this.GetWindowCommandsItems().ToList();

if (reset)
{
for (var i = 0; i < Items.Count - 1; i++)
foreach (var windowCommandsItem in windowCommandsItems)
{
var container = ItemContainerGenerator.ContainerFromIndex(i) as WindowCommandsItem;
if (container != null)
{
container.IsSeparatorVisible = ShowSeparators;
}
windowCommandsItem.IsSeparatorVisible = ShowSeparators;
}
}

var lastContainer = ItemContainerGenerator.ContainerFromIndex(Items.Count - 1) as WindowCommandsItem;
var lastContainer = windowCommandsItems.LastOrDefault(i => i.IsVisible);
if (lastContainer != null)
{
lastContainer.IsSeparatorVisible = ShowSeparators && ShowLastSeparator;
}
}

private WindowCommandsItem GetWindowCommandsItem(object item)
{
var windowCommandsItem = item as WindowCommandsItem;
if (windowCommandsItem != null)
{
return windowCommandsItem;
}
return (WindowCommandsItem)this.ItemContainerGenerator.ContainerFromItem(item);
}

private IEnumerable<WindowCommandsItem> GetWindowCommandsItems()
{
return (from object item in (IEnumerable)this.Items select this.GetWindowCommandsItem(item)).Where(i => i != null);
}

private void WindowCommands_Loaded(object sender, RoutedEventArgs e)
{
this.Loaded -= WindowCommands_Loaded;
Expand Down Expand Up @@ -233,38 +302,19 @@ public class WindowCommandsItem : ContentControl
private const string PART_ContentPresenter = "PART_ContentPresenter";
private const string PART_Separator = "PART_Separator";

private UIElement separator;
private bool isSeparatorVisible = true;

public bool IsSeparatorVisible
{
get { return isSeparatorVisible; }
set
{
if (isSeparatorVisible == value)
{
return;
}

isSeparatorVisible = value;
SetSeparatorVisibility();
}
}
internal PropertyChangeNotifier VisibilityPropertyChangeNotifier { get; set; }

private void SetSeparatorVisibility()
{
if (separator != null)
{
separator.Visibility = IsSeparatorVisible ? Visibility.Visible : Visibility.Hidden;
}
}
public static readonly DependencyProperty IsSeparatorVisibleProperty =
DependencyProperty.Register("IsSeparatorVisible", typeof(bool), typeof(WindowCommandsItem),
new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.Inherits|FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender));

public override void OnApplyTemplate()
/// <summary>
/// Gets or sets the value indicating whether to show the separator.
/// </summary>
public bool IsSeparatorVisible
{
base.OnApplyTemplate();

separator = Template.FindName(PART_Separator, this) as UIElement;
SetSeparatorVisibility();
get { return (bool)GetValue(IsSeparatorVisibleProperty); }
set { SetValue(IsSeparatorVisibleProperty, value); }
}
}
}
9 changes: 9 additions & 0 deletions MahApps.Metro/Themes/WindowCommands.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -211,8 +211,17 @@
Fill="{Binding Foreground, Mode=OneWay, RelativeSource={RelativeSource AncestorType={x:Type Controls:WindowCommands}}}"
IsHitTestVisible="False"
SnapsToDevicePixels="True"
UseLayoutRounding="True"
Opacity="0.25" />
</StackPanel>
<ControlTemplate.Triggers>
<Trigger Property="IsSeparatorVisible"
Value="False">
<Setter TargetName="PART_Separator"
Property="Visibility"
Value="Collapsed" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
Expand Down
6 changes: 6 additions & 0 deletions samples/MetroDemo/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,12 @@
<MenuItem Header="Window with a Border" Click="MenuWindowWithBorderOnClick" />
<MenuItem Header="Window with a Glow" Click="MenuWindowWithGlowOnClick" />
<MenuItem Header="Window with drop shadow" Click="MenuWindowWithShadowOnClick" />
<Separator />
<MenuItem IsCheckable="True" Header="ShowSeparators (RightWindowCommands)" x:Name="ShowSeparatorsMI"
IsChecked="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Controls:MetroWindow}}, Path=RightWindowCommands.ShowSeparators}" />
<MenuItem IsCheckable="True" Header="ShowLastSeparator in (RightWindowCommands)"
IsEnabled="{Binding ElementName=ShowSeparatorsMI, Path=IsChecked, Mode=OneWay}"
IsChecked="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Controls:MetroWindow}}, Path=RightWindowCommands.ShowLastSeparator}" />
</MenuItem>
</Menu>

Expand Down