added version check and connected remaining properties

This commit is contained in:
Nikola Metulev 2017-10-14 19:38:37 -07:00
Родитель 4db791ab21
Коммит c6d30abf35
9 изменённых файлов: 205 добавлений и 212 удалений

Просмотреть файл

@ -1046,7 +1046,7 @@
<VisualStudioVersion>14.0</VisualStudioVersion>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
<PropertyGroup>
<!--<PropertyGroup>
<_GenerateAppxManifestDependsOn>
ModifyAppXPackage;
$(_GenerateAppxManifestDependsOn)
@ -1061,5 +1061,5 @@
<TargetPath>docs/%(RecursiveDir)%(FileName)%(Extension)</TargetPath>
</AppxPackagePayload>
</ItemGroup>
</Target>
</Target>-->
</Project>

Просмотреть файл

@ -44,8 +44,10 @@
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" Margin="50" BorderThickness="1" BorderBrush="Black">
<controls:HamburgerMenu PaneBackground="@[PaneBackground:Brush:Black]" x:Name="HamburgerMenu"
Foreground="White"
<controls:HamburgerMenu x:Name="HamburgerMenu"
PaneBackground="@[PaneBackground:Brush:LightGray]"
PaneForeground="Black"
SelectedIndex="@[SelectedIndex:Slider:0:0-3]@"
ItemTemplate="{StaticResource HamburgerMenuImageItem}"
OptionsItemTemplate="{StaticResource HamburgerMenuItem}"
OpenPaneLength="@[OpenPaneLength:Slider:240:50-400]"
@ -53,7 +55,8 @@
CompactPaneLength="@[CompactPaneLength:Slider:48:10-80]"
HamburgerHeight="@[HamburgerHeight:Slider:48:10-80]"
HamburgerVisibility="@[HamburgerVisibility:Enum:Visibility.Visible]"
IsPaneOpen="@[IsPaneOpen:Bool:False]@">
IsPaneOpen="@[IsPaneOpen:Bool:False]@"
UseNavigationViewWhenPossible="@[UseNavigationViewWhenPossible:Bool:True]">
<!-- Items -->
<controls:HamburgerMenu.ItemsSource>
<controls:HamburgerMenuItemCollection>

Просмотреть файл

@ -65,7 +65,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
ItemInvoked?.Invoke(this, new HamburgetMenuItemInvokedEventArgs() { InvokedItem = e.ClickedItem, IsItemOptions = true });
}
private void NavView_ItemInvoked(NavigationView sender, NavigationViewItemInvokedEventArgs args)
private void NavigationViewItemInvoked(NavigationView sender, NavigationViewItemInvokedEventArgs args)
{
var options = OptionsItemsSource as IEnumerable<object>;
var isOption = options.Contains(args.InvokedItem);

Просмотреть файл

@ -44,12 +44,12 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
/// <summary>
/// Identifies the <see cref="SelectedOptionsItem"/> dependency property.
/// </summary>
public static readonly DependencyProperty SelectedOptionsItemProperty = DependencyProperty.Register(nameof(SelectedOptionsItem), typeof(object), typeof(HamburgerMenu), new PropertyMetadata(null));
public static readonly DependencyProperty SelectedOptionsItemProperty = DependencyProperty.Register(nameof(SelectedOptionsItem), typeof(object), typeof(HamburgerMenu), new PropertyMetadata(null, OnSelectedItemChanged));
/// <summary>
/// Identifies the <see cref="SelectedOptionsIndex"/> dependency property.
/// </summary>
public static readonly DependencyProperty SelectedOptionsIndexProperty = DependencyProperty.Register(nameof(SelectedOptionsIndex), typeof(int), typeof(HamburgerMenu), new PropertyMetadata(-1));
public static readonly DependencyProperty SelectedOptionsIndexProperty = DependencyProperty.Register(nameof(SelectedOptionsIndex), typeof(int), typeof(HamburgerMenu), new PropertyMetadata(-1, OnSelectedOptionsIndexChanged));
/// <summary>
/// Gets or sets an object source used to generate the content of the options.

Просмотреть файл

@ -63,8 +63,6 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
/// </summary>
public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register(nameof(ItemsSource), typeof(object), typeof(HamburgerMenu), new PropertyMetadata(null, OnItemsSourceChanged));
/// <summary>
/// Identifies the <see cref="ItemTemplate"/> dependency property.
/// </summary>
@ -78,12 +76,18 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
/// <summary>
/// Identifies the <see cref="SelectedItem"/> dependency property.
/// </summary>
public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register(nameof(SelectedItem), typeof(object), typeof(HamburgerMenu), new PropertyMetadata(null));
public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register(nameof(SelectedItem), typeof(object), typeof(HamburgerMenu), new PropertyMetadata(null, OnSelectedItemChanged));
/// <summary>
/// Identifies the <see cref="SelectedIndex"/> dependency property.
/// </summary>
public static readonly DependencyProperty SelectedIndexProperty = DependencyProperty.Register(nameof(SelectedIndex), typeof(int), typeof(HamburgerMenu), new PropertyMetadata(-1));
public static readonly DependencyProperty SelectedIndexProperty = DependencyProperty.Register(nameof(SelectedIndex), typeof(int), typeof(HamburgerMenu), new PropertyMetadata(-1, OnSelectedIndexChanged));
/// <summary>
/// Identifies the <see cref="UseNavigationViewWhenPossible"/> dependency property
/// </summary>
public static readonly DependencyProperty UseNavigationViewWhenPossibleProperty =
DependencyProperty.Register("UseNavigationViewWhenPossible", typeof(bool), typeof(HamburgerMenu), new PropertyMetadata(false, OnUseNavigationViewWhenPossibleChanged));
/// <summary>
/// Gets or sets the width of the pane when it's fully expanded.
@ -212,5 +216,15 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
get { return (int)GetValue(SelectedIndexProperty); }
set { SetValue(SelectedIndexProperty, value); }
}
/// <summary>
/// Gets or sets a value indicating whether the HamburgerMenu shoud use the NavigationView when possible (Fall Creators Update and above)
/// When set to true and the device supports NavigationView, the HamburgerMenu will use a template based on NavigationView
/// </summary>
public bool UseNavigationViewWhenPossible
{
get { return (bool)GetValue(UseNavigationViewWhenPossibleProperty); }
set { SetValue(UseNavigationViewWhenPossibleProperty, value); }
}
}
}

Просмотреть файл

@ -10,11 +10,13 @@
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using Microsoft.Toolkit.Uwp.UI.Extensions;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Toolkit.Uwp.UI.Extensions;
using Windows.Foundation.Metadata;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Data;
namespace Microsoft.Toolkit.Uwp.UI.Controls
{
@ -26,13 +28,32 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
[TemplatePart(Name = "OptionsListView", Type = typeof(Windows.UI.Xaml.Controls.ListViewBase))]
public partial class HamburgerMenu : ContentControl
{
private static bool? _isNavViewSupported;
private Button _hamburgerButton;
private Windows.UI.Xaml.Controls.ListViewBase _buttonsListView;
private Windows.UI.Xaml.Controls.ListViewBase _optionsListView;
private object _navigationView;
private Button _navViewHamburgerButton;
private bool temp = true; // TODO REPLACE ME WITH REAL CHECK
private ControlTemplate _previousTemplateUsed;
private NavigationView _navigationView;
/// <summary>
/// Gets the <see cref="NavigationView"/>. Returns null when device does not support
/// NavigationView or when <see cref="UseNavigationViewWhenPossible"/> is set to false
/// </summary>
public NavigationView NavigationView
{
get { return _navigationView; }
}
private bool UsingNavView => UseNavigationViewWhenPossible && IsNavViewSupported;
/// <summary>
/// Gets a value indicating whether <see cref="NavigationView"/> is supported
/// </summary>
public static bool IsNavViewSupported => (bool)(_isNavViewSupported ??
(_isNavViewSupported = ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 5)));
/// <summary>
/// Initializes a new instance of the <see cref="HamburgerMenu"/> class.
@ -47,7 +68,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
/// </summary>
protected override void OnApplyTemplate()
{
if (!temp && PaneForeground == null)
if (!UsingNavView && PaneForeground == null)
{
PaneForeground = Foreground;
}
@ -67,42 +88,29 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
_optionsListView.ItemClick -= OptionsListView_ItemClick;
}
if (_navigationView != null && temp)
if (UsingNavView && _navigationView != null)
{
if (_navigationView is NavigationView navView)
{
navView.ItemInvoked -= NavView_ItemInvoked;
}
_navigationView.ItemInvoked -= NavigationViewItemInvoked;
_navigationView.SelectionChanged -= NavigationViewSelectionChanged;
_navigationView.Loaded -= NavigationViewLoaded;
}
_hamburgerButton = (Button)GetTemplateChild("HamburgerButton");
_buttonsListView = (Windows.UI.Xaml.Controls.ListViewBase)GetTemplateChild("ButtonsListView");
_optionsListView = (Windows.UI.Xaml.Controls.ListViewBase)GetTemplateChild("OptionsListView");
if (temp)
if (UsingNavView)
{
_navigationView = (NavigationView)GetTemplateChild("NavView");
if (_navigationView is NavigationView navView)
if (_navigationView != null)
{
navView.ItemInvoked += NavView_ItemInvoked;
navView.MenuItemTemplateSelector = new HamburgerMenuNavViewItemTemplateSelector(this);
_navigationView.ItemInvoked += NavigationViewItemInvoked;
_navigationView.SelectionChanged += NavigationViewSelectionChanged;
_navigationView.Loaded += NavigationViewLoaded;
_navigationView.MenuItemTemplateSelector = new HamburgerMenuNavViewItemTemplateSelector(this);
OnItemsSourceChanged(this, null);
_navViewHamburgerButton = navView.FindChildByName("TogglePaneButton") as Button;
if (_navViewHamburgerButton != null)
{
// subscribe events
if (PaneForeground != null)
{
_navViewHamburgerButton.Foreground = PaneForeground;
}
if (HamburgerMenuTemplate != null)
{
_navViewHamburgerButton.ContentTemplate = HamburgerMenuTemplate;
}
}
}
}
@ -128,7 +136,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
{
var hm = d as HamburgerMenu;
if (hm.temp && hm._navigationView is NavigationView navView)
if (hm.UsingNavView && hm._navigationView != null)
{
var items = hm.ItemsSource as IEnumerable<object>;
var options = hm.OptionsItemsSource as IEnumerable<object>;
@ -156,7 +164,142 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
}
}
navView.MenuItemsSource = combined;
hm._navigationView.MenuItemsSource = combined;
}
}
private static void OnUseNavigationViewWhenPossibleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var menu = d as HamburgerMenu;
if (menu.UseNavigationViewWhenPossible && HamburgerMenu.IsNavViewSupported)
{
ResourceDictionary dict = new ResourceDictionary();
dict.Source = new System.Uri("ms-appx:///Microsoft.Toolkit.Uwp.UI.Controls/Themes/Generic.xaml");
menu._previousTemplateUsed = menu.Template;
menu.Template = dict["HamburgerMenuNavViewTemplate"] as ControlTemplate;
}
else if (!menu.UseNavigationViewWhenPossible &&
e.OldValue is bool oldValue &&
oldValue &&
menu._previousTemplateUsed != null)
{
menu.Template = menu._previousTemplateUsed;
}
}
private static void OnSelectedItemChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var menu = d as HamburgerMenu;
if (menu.UsingNavView)
{
menu._navigationView.SelectedItem = e.NewValue;
}
}
private static void OnSelectedIndexChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var menu = d as HamburgerMenu;
if (menu.UsingNavView)
{
var items = menu.ItemsSource as IEnumerable<object>;
if (items != null)
{
menu._navigationView.SelectedItem = (int)e.NewValue >= 0 ? items.ElementAt((int)e.NewValue) : null;
}
}
}
private static void OnSelectedOptionsIndexChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var menu = d as HamburgerMenu;
if (menu.UsingNavView)
{
var options = menu.ItemsSource as IEnumerable<object>;
if (options != null)
{
menu._navigationView.SelectedItem = (int)e.NewValue >= 0 ? options.ElementAt((int)e.NewValue) : null;
}
}
}
private void NavigationViewLoaded(object sender, RoutedEventArgs e)
{
_navigationView.Loaded -= NavigationViewLoaded;
var hamburgerButton = _navigationView.FindDescendantByName("TogglePaneButton") as Button;
if (hamburgerButton != null)
{
var templateBinding = new Binding()
{
Source = this,
Path = new PropertyPath(nameof(HamburgerMenuTemplate)),
Mode = BindingMode.OneWay
};
var heightBinding = new Binding()
{
Source = this,
Path = new PropertyPath(nameof(HamburgerHeight)),
Mode = BindingMode.OneWay
};
var widthBinding = new Binding()
{
Source = this,
Path = new PropertyPath(nameof(HamburgerWidth)),
Mode = BindingMode.OneWay
};
var marginBinding = new Binding()
{
Source = this,
Path = new PropertyPath(nameof(HamburgerMargin)),
Mode = BindingMode.OneWay
};
var foregroundMargin = new Binding()
{
Source = this,
Path = new PropertyPath(nameof(PaneForeground)),
Mode = BindingMode.OneWay
};
hamburgerButton.SetBinding(Button.ContentTemplateProperty, templateBinding);
hamburgerButton.SetBinding(Button.HeightProperty, heightBinding);
hamburgerButton.SetBinding(Button.WidthProperty, widthBinding);
hamburgerButton.SetBinding(Button.MarginProperty, marginBinding);
hamburgerButton.SetBinding(Button.ForegroundProperty, foregroundMargin);
}
}
private void NavigationViewSelectionChanged(NavigationView sender, NavigationViewSelectionChangedEventArgs args)
{
if (args.IsSettingsSelected)
{
SelectedItem = null;
SelectedIndex = -1;
SelectedOptionsItem = null;
SelectedOptionsIndex = -1;
}
else if (args.SelectedItem != null)
{
var items = ItemsSource as IEnumerable<object>;
var options = OptionsItemsSource as IEnumerable<object>;
if (items != null && items.Contains(args.SelectedItem))
{
SelectedItem = args.SelectedItem;
SelectedIndex = items.ToList().IndexOf(SelectedItem);
SelectedOptionsItem = null;
SelectedOptionsIndex = -1;
}
else if (options != null && options.Contains(args.SelectedItem))
{
SelectedItem = null;
SelectedIndex = -1;
SelectedOptionsItem = args.SelectedItem;
SelectedOptionsIndex = options.ToList().IndexOf(SelectedItem);
}
}
}
}

Просмотреть файл

@ -18,7 +18,7 @@
</Setter.Value>
</Setter>
<Setter Property="IsTabStop" Value="False" />
<Setter Property="Template" Value="{StaticResource HamburgerMenuNavViewTemplate}">
<Setter Property="Template" Value="{StaticResource HamburgerMenuTemplate}">
</Setter>
</Style>
</ResourceDictionary>

Просмотреть файл

@ -161,100 +161,11 @@
IsSettingsVisible="False"
IsPaneToggleButtonVisible="{Binding HamburgerVisibility, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource VisibilityToBoolConverter}}"
Header="{x:Null}">
<ContentPresenter x:Name="ContentPart"
AutomationProperties.Name="Content"
Content="{TemplateBinding Content}" />
</NavigationView>
</Grid>
<!--<Grid>
DisplayMode -> readonly
PanePlacement -> not available
PaneBackground -> not available
HamburgerHeight -> not available
HamburgerWidth -> not available
PaneForeground -> not avaialable
<SplitView x:Name="MainSplitView"
CompactPaneLength="{TemplateBinding CompactPaneLength}"
DisplayMode="{TemplateBinding DisplayMode}"
IsPaneOpen="{Binding IsPaneOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
IsTabStop="False"
OpenPaneLength="{TemplateBinding OpenPaneLength}"
PaneBackground="Red"
PanePlacement="{TemplateBinding PanePlacement}">
<SplitView.Pane>
<Grid x:Name="PaneGrid"
FlowDirection="LeftToRight">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid Grid.Row="0"
Height="{TemplateBinding HamburgerHeight}"
Margin="0,0,0,8" />
<ListView x:Name="ButtonsListView"
Grid.Row="1"
Width="{TemplateBinding OpenPaneLength}"
AutomationProperties.Name="Menu items"
IsItemClickEnabled="True"
ItemContainerStyle="{StaticResource HambugerMenuItemStyle}"
ItemTemplate="{TemplateBinding ItemTemplate}"
ItemTemplateSelector="{TemplateBinding ItemTemplateSelector}"
ItemsSource="{TemplateBinding ItemsSource}"
ScrollViewer.VerticalScrollBarVisibility="Auto"
SelectedIndex="{Binding SelectedIndex, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
SelectedItem="{Binding SelectedItem, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
SelectionMode="Single"
TabIndex="1">
</ListView>
<ListView x:Name="OptionsListView"
Grid.Row="2"
Width="{TemplateBinding OpenPaneLength}"
VerticalAlignment="Bottom"
AutomationProperties.Name="Option items"
IsItemClickEnabled="True"
ItemContainerStyle="{StaticResource HambugerMenuItemStyle}"
ItemTemplate="{TemplateBinding OptionsItemTemplate}"
ItemTemplateSelector="{TemplateBinding OptionsItemTemplateSelector}"
ItemsSource="{TemplateBinding OptionsItemsSource}"
ScrollViewer.VerticalScrollBarVisibility="Disabled"
SelectedIndex="{Binding SelectedOptionsIndex, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
SelectedItem="{Binding SelectedOptionsItem, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
SelectionMode="Single"
TabIndex="2"
Margin="0,20,0,8">
</ListView>
</Grid>
</SplitView.Pane>
<ContentPresenter x:Name="ContentPart"
AutomationProperties.Name="Content"
Content="{TemplateBinding Content}" />
</SplitView>
<Button x:Name="HamburgerButton"
Width="{TemplateBinding HamburgerWidth}"
Height="{TemplateBinding HamburgerHeight}"
Visibility="{TemplateBinding HamburgerVisibility}"
Margin="0,0,0,8"
Padding="0"
VerticalAlignment="Top"
AutomationProperties.Name="Main button"
Background="Transparent"
BorderThickness="0"
TabIndex="0">
<ContentControl Margin="{TemplateBinding HamburgerMargin}"
ContentTemplate="{TemplateBinding HamburgerMenuTemplate}"
Foreground="{TemplateBinding PaneForeground}"
IsTabStop="False" />
</Button>
</Grid>-->
</ControlTemplate>
</ResourceDictionary>

Просмотреть файл

@ -1,78 +0,0 @@
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Data;
namespace Microsoft.Toolkit.Uwp.UI.Converters
{
/// <summary>
/// This class converts a <see cref="SplitViewDisplayMode"/> enumeration to <see cref="NavigationViewDisplayMode"/> enumeration.
/// </summary>
public class SplitViewDisplayModeToNavViewDisplayMode : IValueConverter
{
/// <summary>
/// Convert a <see cref="SplitViewDisplayMode"/> to <see cref="NavigationViewDisplayMode"/>.
/// </summary>
/// <param name="value">The <see cref="SplitViewDisplayMode"/> value to convert.</param>
/// <param name="targetType">The type of the target property, as a type reference.</param>
/// <param name="parameter">Optional parameter. Not used.</param>
/// <param name="language">The language of the conversion. Not used</param>
/// <returns>The value to be passed to the target dependency property.</returns>
public object Convert(object value, Type targetType, object parameter, string language)
{
if (value is SplitViewDisplayMode svdm)
{
switch (svdm)
{
case SplitViewDisplayMode.CompactInline:
return NavigationViewDisplayMode.Compact;
case SplitViewDisplayMode.Inline:
return NavigationViewDisplayMode.Expanded;
case SplitViewDisplayMode.CompactOverlay:
case SplitViewDisplayMode.Overlay:
return NavigationViewDisplayMode.Minimal;
}
}
return NavigationViewDisplayMode.Compact;
}
/// <summary>
/// Convert back a boolean value to <see cref="Visibility"/>.
/// </summary>
/// <param name="value">The <see cref="Visibility"/> value to convert back.</param>
/// <param name="targetType">The type of the target property, as a type reference.</param>
/// <param name="parameter">Optional parameter. Not used.</param>
/// <param name="language">The language of the conversion. Not used</param>
/// <returns>The value to be passed to the target dependency property.</returns>
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
if (value is NavigationViewDisplayMode nvdm)
{
switch (nvdm)
{
case NavigationViewDisplayMode.Compact:
return SplitViewDisplayMode.CompactInline;
case NavigationViewDisplayMode.Expanded:
return SplitViewDisplayMode.Inline;
case NavigationViewDisplayMode.Minimal:
return SplitViewDisplayMode.CompactOverlay;
}
}
return SplitViewDisplayMode.CompactInline;
}
}
}