diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.Layout.Design/Controls/ListDetailsView.Metadata.cs b/Microsoft.Toolkit.Uwp.UI.Controls.Layout.Design/Controls/ListDetailsView.Metadata.cs
index 3013c7fdd2b..45bba363e2f 100644
--- a/Microsoft.Toolkit.Uwp.UI.Controls.Layout.Design/Controls/ListDetailsView.Metadata.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Controls.Layout.Design/Controls/ListDetailsView.Metadata.cs
@@ -2,12 +2,10 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System.ComponentModel;
-
using Microsoft.Toolkit.Uwp.UI.Controls.Design.Properties;
-
using Microsoft.VisualStudio.DesignTools.Extensibility;
using Microsoft.VisualStudio.DesignTools.Extensibility.Metadata;
+using System.ComponentModel;
namespace Microsoft.Toolkit.Uwp.UI.Controls.Design
{
@@ -25,6 +23,7 @@ public ListDetailsViewMetadata()
new EditorBrowsableAttribute(EditorBrowsableState.Advanced)
);
b.AddCustomAttributes(nameof(ListDetailsView.ListPaneBackground), new CategoryAttribute(Resources.CategoryBrush));
+ b.AddCustomAttributes(nameof(ListDetailsView.DetailsPaneBackground), new CategoryAttribute(Resources.CategoryBrush));
b.AddCustomAttributes(nameof(ListDetailsView.ListHeader), new CategoryAttribute(Resources.CategoryCommon));
b.AddCustomAttributes(nameof(ListDetailsView.ListHeaderTemplate),
new CategoryAttribute(Resources.CategoryAppearance),
@@ -36,6 +35,11 @@ public ListDetailsViewMetadata()
new CategoryAttribute(Resources.CategoryCommon),
new EditorBrowsableAttribute(EditorBrowsableState.Advanced)
);
+ AddCustomAttributes(nameof(ListDetailsView.ListPaneNoItemsContent), new CategoryAttribute(Resources.CategoryCommon));
+ b.AddCustomAttributes(nameof(ListDetailsView.ListPaneNoItemsContentTemplate),
+ new CategoryAttribute(Resources.CategoryCommon),
+ new EditorBrowsableAttribute(EditorBrowsableState.Advanced)
+ );
b.AddCustomAttributes(nameof(ListDetailsView.ViewState), new CategoryAttribute(Resources.CategoryCommon));
b.AddCustomAttributes(nameof(ListDetailsView.ListCommandBar), new CategoryAttribute(Resources.CategoryCommon));
b.AddCustomAttributes(nameof(ListDetailsView.DetailsCommandBar), new CategoryAttribute(Resources.CategoryCommon));
@@ -44,4 +48,4 @@ public ListDetailsViewMetadata()
);
}
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.Layout.Design/Controls/ListDetailsView.Typedata.cs b/Microsoft.Toolkit.Uwp.UI.Controls.Layout.Design/Controls/ListDetailsView.Typedata.cs
index 15c2bcb7d65..d2472467486 100644
--- a/Microsoft.Toolkit.Uwp.UI.Controls.Layout.Design/Controls/ListDetailsView.Typedata.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Controls.Layout.Design/Controls/ListDetailsView.Typedata.cs
@@ -2,8 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System;
-
namespace Microsoft.Toolkit.Uwp.UI.Controls.Design
{
internal static partial class ControlTypes
@@ -15,6 +13,11 @@ internal static class ListDetailsView
{
internal const string DetailsCommandBar = nameof(DetailsCommandBar);
internal const string DetailsTemplate = nameof(DetailsTemplate);
+ internal const string DetailsPaneBackground = nameof(DetailsPaneBackground);
+ internal const string DetailsContentTemplateSelector = nameof(DetailsContentTemplateSelector);
+ internal const string ListPaneItemTemplateSelector = nameof(ListPaneItemTemplateSelector);
+ internal const string ListPaneNoItemsContentTemplate = nameof(ListPaneNoItemsContentTemplate);
+ internal const string ListPaneNoItemsContent = nameof(ListPaneNoItemsContent);
internal const string ListCommandBar = nameof(ListCommandBar);
internal const string ListHeader = nameof(ListHeader);
internal const string ListHeaderTemplate = nameof(ListHeaderTemplate);
@@ -25,4 +28,4 @@ internal static class ListDetailsView
internal const string SelectedItem = nameof(SelectedItem);
internal const string ViewState = nameof(ViewState);
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.Layout/ListDetailsView/BackButtonBehavior.cs b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/ListDetailsView/BackButtonBehavior.cs
index d3c8093d7d2..9fa9ee80ce4 100644
--- a/Microsoft.Toolkit.Uwp.UI.Controls.Layout/ListDetailsView/BackButtonBehavior.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/ListDetailsView/BackButtonBehavior.cs
@@ -14,7 +14,7 @@ public enum BackButtonBehavior
///
///
/// If the back button controlled by is already visible, the will hook into that button.
- /// If the new NavigationView provided by the Windows UI nuget package is used, the will enable and show that button.
+ /// If the new NavigationView provided by the Windows UI NuGet package is used, the will enable and show that button.
/// Otherwise the inline button is used.
///
Automatic,
@@ -34,4 +34,4 @@ public enum BackButtonBehavior
///
Manual,
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.Layout/ListDetailsView/ListDetailsView.BackButton.cs b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/ListDetailsView/ListDetailsView.BackButton.cs
new file mode 100644
index 00000000000..ff046c6781b
--- /dev/null
+++ b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/ListDetailsView/ListDetailsView.BackButton.cs
@@ -0,0 +1,166 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Reflection;
+using Windows.ApplicationModel;
+using Windows.UI.Core;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Navigation;
+
+namespace Microsoft.Toolkit.Uwp.UI.Controls
+{
+ ///
+ /// Panel that allows for a List/Details pattern.
+ ///
+ ///
+ public partial class ListDetailsView
+ {
+ private AppViewBackButtonVisibility? _previousSystemBackButtonVisibility;
+ private bool _previousNavigationViewBackEnabled;
+
+ // Int used because the underlying type is an enum, but we don't have access to the enum
+ private int _previousNavigationViewBackVisibilty;
+ private Button _inlineBackButton;
+ private object _navigationView;
+ private Frame _frame;
+
+ ///
+ /// Sets the back button visibility based on the current visual state and selected item
+ ///
+ private void SetBackButtonVisibility(ListDetailsViewState? previousState = null)
+ {
+ const int backButtonVisible = 1;
+
+ if (DesignMode.DesignModeEnabled)
+ {
+ return;
+ }
+
+ if (ViewState == ListDetailsViewState.Details)
+ {
+ if ((BackButtonBehavior == BackButtonBehavior.Inline) && (_inlineBackButton != null))
+ {
+ _inlineBackButton.Visibility = Visibility.Visible;
+ }
+ else if (BackButtonBehavior == BackButtonBehavior.Automatic)
+ {
+ // Continue to support the system back button if it is being used
+ SystemNavigationManager navigationManager = SystemNavigationManager.GetForCurrentView();
+ if (navigationManager.AppViewBackButtonVisibility == AppViewBackButtonVisibility.Visible)
+ {
+ // Setting this indicates that the system back button is being used
+ _previousSystemBackButtonVisibility = navigationManager.AppViewBackButtonVisibility;
+ }
+ else if ((_inlineBackButton != null) && ((_navigationView == null) || (_frame == null)))
+ {
+ // We can only use the new NavigationView if we also have a Frame
+ // If there is no frame we have to use the inline button
+ _inlineBackButton.Visibility = Visibility.Visible;
+ }
+ else
+ {
+ SetNavigationViewBackButtonState(backButtonVisible, true);
+ }
+ }
+ else if (BackButtonBehavior != BackButtonBehavior.Manual)
+ {
+ SystemNavigationManager navigationManager = SystemNavigationManager.GetForCurrentView();
+ _previousSystemBackButtonVisibility = navigationManager.AppViewBackButtonVisibility;
+
+ navigationManager.AppViewBackButtonVisibility = AppViewBackButtonVisibility.Visible;
+ }
+ }
+ else if (previousState == ListDetailsViewState.Details)
+ {
+ if ((BackButtonBehavior == BackButtonBehavior.Inline) && (_inlineBackButton != null))
+ {
+ _inlineBackButton.Visibility = Visibility.Collapsed;
+ }
+ else if (BackButtonBehavior == BackButtonBehavior.Automatic)
+ {
+ if (!_previousSystemBackButtonVisibility.HasValue)
+ {
+ if ((_inlineBackButton != null) && ((_navigationView == null) || (_frame == null)))
+ {
+ _inlineBackButton.Visibility = Visibility.Collapsed;
+ }
+ else
+ {
+ SetNavigationViewBackButtonState(_previousNavigationViewBackVisibilty, _previousNavigationViewBackEnabled);
+ }
+ }
+ }
+
+ if (_previousSystemBackButtonVisibility.HasValue)
+ {
+ // Make sure we show the back button if the stack can navigate back
+ SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility = _previousSystemBackButtonVisibility.Value;
+ _previousSystemBackButtonVisibility = null;
+ }
+ }
+ }
+
+ private void SetNavigationViewBackButtonState(int visible, bool enabled)
+ {
+ if (_navigationView == null)
+ {
+ return;
+ }
+
+ System.Type navType = _navigationView.GetType();
+ PropertyInfo visibleProperty = navType.GetProperty("IsBackButtonVisible");
+ if (visibleProperty != null)
+ {
+ _previousNavigationViewBackVisibilty = (int)visibleProperty.GetValue(_navigationView);
+ visibleProperty.SetValue(_navigationView, visible);
+ }
+
+ PropertyInfo enabledProperty = navType.GetProperty("IsBackEnabled");
+ if (enabledProperty != null)
+ {
+ _previousNavigationViewBackEnabled = (bool)enabledProperty.GetValue(_navigationView);
+ enabledProperty.SetValue(_navigationView, enabled);
+ }
+ }
+
+ ///
+ /// Closes the details pane if we are in narrow state
+ ///
+ /// The sender
+ /// The event args
+ private void OnFrameNavigating(object sender, NavigatingCancelEventArgs args)
+ {
+ if ((args.NavigationMode == NavigationMode.Back) && (ViewState == ListDetailsViewState.Details))
+ {
+ ClearSelectedItem();
+ args.Cancel = true;
+ }
+ }
+
+ ///
+ /// Closes the details pane if we are in narrow state
+ ///
+ /// The sender
+ /// The event args
+ private void OnBackRequested(object sender, BackRequestedEventArgs args)
+ {
+ if (ViewState == ListDetailsViewState.Details)
+ {
+ // let the OnFrameNavigating method handle it if
+ if (_frame == null || !_frame.CanGoBack)
+ {
+ ClearSelectedItem();
+ }
+
+ args.Handled = true;
+ }
+ }
+
+ private void OnInlineBackButtonClicked(object sender, RoutedEventArgs e)
+ {
+ ClearSelectedItem();
+ }
+ }
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.Layout/ListDetailsView/ListDetailsView.Events.cs b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/ListDetailsView/ListDetailsView.Events.cs
index ed3009f2ac5..d4ebd8a67cf 100644
--- a/Microsoft.Toolkit.Uwp.UI.Controls.Layout/ListDetailsView/ListDetailsView.Events.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/ListDetailsView/ListDetailsView.Events.cs
@@ -10,7 +10,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
///
/// Panel that allows for a List/Details pattern.
///
- ///
+ ///
public partial class ListDetailsView
{
///
@@ -19,7 +19,7 @@ public partial class ListDetailsView
public event SelectionChangedEventHandler SelectionChanged;
///
- /// Occurs when the view state changes
+ /// Occurs when the view state changes.
///
public event EventHandler ViewStateChanged;
@@ -28,4 +28,4 @@ private void OnSelectionChanged(SelectionChangedEventArgs e)
SelectionChanged?.Invoke(this, e);
}
}
-}
\ No newline at end of file
+}
diff --git a/Microsoft.Toolkit.Uwp.UI.Controls.Layout/ListDetailsView/ListDetailsView.Properties.cs b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/ListDetailsView/ListDetailsView.Properties.cs
index 1cd9caa3c09..d9c5df75e5d 100644
--- a/Microsoft.Toolkit.Uwp.UI.Controls.Layout/ListDetailsView/ListDetailsView.Properties.cs
+++ b/Microsoft.Toolkit.Uwp.UI.Controls.Layout/ListDetailsView/ListDetailsView.Properties.cs
@@ -45,6 +45,36 @@ public partial class ListDetailsView
typeof(ListDetailsView),
new PropertyMetadata(null));
+ ///
+ /// Identifies the dependency property.
+ ///
+ /// The identifier for the dependency property.
+ public static readonly DependencyProperty DetailsContentTemplateSelectorProperty = DependencyProperty.Register(
+ nameof(DetailsContentTemplateSelector),
+ typeof(DataTemplateSelector),
+ typeof(ListDetailsView),
+ new PropertyMetadata(null));
+
+ ///
+ /// Identifies the dependency property.
+ ///
+ /// The identifier for the dependency property.
+ public static readonly DependencyProperty ListPaneItemTemplateSelectorProperty = DependencyProperty.Register(
+ nameof(ListPaneItemTemplateSelector),
+ typeof(DataTemplateSelector),
+ typeof(ListDetailsView),
+ new PropertyMetadata(null));
+
+ ///
+ /// Identifies the dependency property.
+ ///
+ /// The identifier for the dependency property.
+ public static readonly DependencyProperty DetailsPaneBackgroundProperty = DependencyProperty.Register(
+ nameof(DetailsPaneBackground),
+ typeof(Brush),
+ typeof(ListDetailsView),
+ new PropertyMetadata(null));
+
///
/// Identifies the dependency property.
///
@@ -75,6 +105,26 @@ public partial class ListDetailsView
typeof(ListDetailsView),
new PropertyMetadata(null));
+ ///
+ /// Identifies the dependency property.
+ ///
+ /// The identifier for the dependency property.
+ public static readonly DependencyProperty ListPaneNoItemsContentProperty = DependencyProperty.Register(
+ nameof(ListPaneNoItemsContent),
+ typeof(object),
+ typeof(ListDetailsView),
+ new PropertyMetadata(null));
+
+ ///
+ /// Identifies the dependency property.
+ ///
+ /// The identifier for the dependency property.
+ public static readonly DependencyProperty ListPaneNoItemsContentTemplateProperty = DependencyProperty.Register(
+ nameof(ListPaneNoItemsContentTemplate),
+ typeof(DataTemplate),
+ typeof(ListDetailsView),
+ new PropertyMetadata(null));
+
///
/// Identifies the dependency property.
///
@@ -103,7 +153,7 @@ public partial class ListDetailsView
nameof(ListPaneWidth),
typeof(double),
typeof(ListDetailsView),
- new PropertyMetadata(320d));
+ new PropertyMetadata(320d, OnListPaneWidthChanged));
///
/// Identifies the dependency property.
@@ -162,7 +212,7 @@ public partial class ListDetailsView
nameof(CompactModeThresholdWidth),
typeof(double),
typeof(ListDetailsView),
- new PropertyMetadata(720d, OnCompactModeThresholdWidthChanged));
+ new PropertyMetadata(640d));
///
/// Identifies the dependency property
@@ -202,6 +252,35 @@ public DataTemplate DetailsTemplate
set { SetValue(DetailsTemplateProperty, value); }
}
+ ///
+ /// Gets or sets the for the details presenter.
+ ///
+ public DataTemplateSelector DetailsContentTemplateSelector
+ {
+ get { return (DataTemplateSelector)GetValue(DetailsContentTemplateSelectorProperty); }
+ set { SetValue(DetailsContentTemplateSelectorProperty, value); }
+ }
+
+ ///
+ /// Gets or sets the for the list pane items.
+ ///
+ public DataTemplateSelector ListPaneItemTemplateSelector
+ {
+ get { return (DataTemplateSelector)GetValue(ListPaneItemTemplateSelectorProperty); }
+ set { SetValue(ListPaneItemTemplateSelectorProperty, value); }
+ }
+
+ ///
+ /// Gets or sets the content for the list pane's header
+ /// Gets or sets the Brush to apply to the background of the details area of the control.
+ ///
+ /// The Brush to apply to the background of the details area of the control.
+ public Brush DetailsPaneBackground
+ {
+ get { return (Brush)GetValue(DetailsPaneBackgroundProperty); }
+ set { SetValue(DetailsPaneBackgroundProperty, value); }
+ }
+
///
/// Gets or sets the Brush to apply to the background of the list area of the control.
///
@@ -236,6 +315,30 @@ public DataTemplate ListHeaderTemplate
set { SetValue(ListHeaderTemplateProperty, value); }
}
+ ///
+ /// Gets or sets the content for the list pane's no items presenter.
+ ///
+ ///
+ /// The content of the list pane's header. The default is null.
+ ///
+ public object ListPaneNoItemsContent
+ {
+ get { return GetValue(ListPaneNoItemsContentProperty); }
+ set { SetValue(ListPaneNoItemsContentProperty, value); }
+ }
+
+ ///
+ /// Gets or sets the DataTemplate used to display the list pane's no items presenter.
+ ///
+ ///
+ /// The template that specifies the visualization of the list pane no items object. The default is null.
+ ///
+ public DataTemplate ListPaneNoItemsContentTemplate
+ {
+ get { return (DataTemplate)GetValue(ListPaneNoItemsContentTemplateProperty); }
+ set { SetValue(ListPaneNoItemsContentTemplateProperty, value); }
+ }
+
///
/// Gets or sets the content for the details pane's header
///
@@ -346,5 +449,81 @@ public BackButtonBehavior BackButtonBehavior
/// This new model will be the DataContext of the Details area.
///
public Func