Skip to content

Commit 10e7668

Browse files
Merge pull request #4197 from COM8/feature/two_pane_view
ListDetailsView now uses the Two-Pane View
2 parents f9a80ec + a867fad commit 10e7668

File tree

10 files changed

+734
-420
lines changed

10 files changed

+734
-420
lines changed

Microsoft.Toolkit.Uwp.UI.Controls.Layout.Design/Controls/ListDetailsView.Metadata.cs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,10 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33
// See the LICENSE file in the project root for more information.
44

5-
using System.ComponentModel;
6-
75
using Microsoft.Toolkit.Uwp.UI.Controls.Design.Properties;
8-
96
using Microsoft.VisualStudio.DesignTools.Extensibility;
107
using Microsoft.VisualStudio.DesignTools.Extensibility.Metadata;
8+
using System.ComponentModel;
119

1210
namespace Microsoft.Toolkit.Uwp.UI.Controls.Design
1311
{
@@ -25,6 +23,7 @@ public ListDetailsViewMetadata()
2523
new EditorBrowsableAttribute(EditorBrowsableState.Advanced)
2624
);
2725
b.AddCustomAttributes(nameof(ListDetailsView.ListPaneBackground), new CategoryAttribute(Resources.CategoryBrush));
26+
b.AddCustomAttributes(nameof(ListDetailsView.DetailsPaneBackground), new CategoryAttribute(Resources.CategoryBrush));
2827
b.AddCustomAttributes(nameof(ListDetailsView.ListHeader), new CategoryAttribute(Resources.CategoryCommon));
2928
b.AddCustomAttributes(nameof(ListDetailsView.ListHeaderTemplate),
3029
new CategoryAttribute(Resources.CategoryAppearance),
@@ -36,6 +35,11 @@ public ListDetailsViewMetadata()
3635
new CategoryAttribute(Resources.CategoryCommon),
3736
new EditorBrowsableAttribute(EditorBrowsableState.Advanced)
3837
);
38+
AddCustomAttributes(nameof(ListDetailsView.ListPaneNoItemsContent), new CategoryAttribute(Resources.CategoryCommon));
39+
b.AddCustomAttributes(nameof(ListDetailsView.ListPaneNoItemsContentTemplate),
40+
new CategoryAttribute(Resources.CategoryCommon),
41+
new EditorBrowsableAttribute(EditorBrowsableState.Advanced)
42+
);
3943
b.AddCustomAttributes(nameof(ListDetailsView.ViewState), new CategoryAttribute(Resources.CategoryCommon));
4044
b.AddCustomAttributes(nameof(ListDetailsView.ListCommandBar), new CategoryAttribute(Resources.CategoryCommon));
4145
b.AddCustomAttributes(nameof(ListDetailsView.DetailsCommandBar), new CategoryAttribute(Resources.CategoryCommon));
@@ -44,4 +48,4 @@ public ListDetailsViewMetadata()
4448
);
4549
}
4650
}
47-
}
51+
}

Microsoft.Toolkit.Uwp.UI.Controls.Layout.Design/Controls/ListDetailsView.Typedata.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33
// See the LICENSE file in the project root for more information.
44

5-
using System;
6-
75
namespace Microsoft.Toolkit.Uwp.UI.Controls.Design
86
{
97
internal static partial class ControlTypes
@@ -15,6 +13,11 @@ internal static class ListDetailsView
1513
{
1614
internal const string DetailsCommandBar = nameof(DetailsCommandBar);
1715
internal const string DetailsTemplate = nameof(DetailsTemplate);
16+
internal const string DetailsPaneBackground = nameof(DetailsPaneBackground);
17+
internal const string DetailsContentTemplateSelector = nameof(DetailsContentTemplateSelector);
18+
internal const string ListPaneItemTemplateSelector = nameof(ListPaneItemTemplateSelector);
19+
internal const string ListPaneNoItemsContentTemplate = nameof(ListPaneNoItemsContentTemplate);
20+
internal const string ListPaneNoItemsContent = nameof(ListPaneNoItemsContent);
1821
internal const string ListCommandBar = nameof(ListCommandBar);
1922
internal const string ListHeader = nameof(ListHeader);
2023
internal const string ListHeaderTemplate = nameof(ListHeaderTemplate);
@@ -25,4 +28,4 @@ internal static class ListDetailsView
2528
internal const string SelectedItem = nameof(SelectedItem);
2629
internal const string ViewState = nameof(ViewState);
2730
}
28-
}
31+
}

Microsoft.Toolkit.Uwp.UI.Controls.Layout/ListDetailsView/BackButtonBehavior.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public enum BackButtonBehavior
1414
/// </summary>
1515
/// <remarks>
1616
/// If the back button controlled by <see cref="Windows.UI.Core.SystemNavigationManager"/> is already visible, the <see cref="ListDetailsView"/> will hook into that button.
17-
/// If the new NavigationView provided by the Windows UI nuget package is used, the <see cref="ListDetailsView"/> will enable and show that button.
17+
/// If the new NavigationView provided by the Windows UI NuGet package is used, the <see cref="ListDetailsView"/> will enable and show that button.
1818
/// Otherwise the inline button is used.
1919
/// </remarks>
2020
Automatic,
@@ -34,4 +34,4 @@ public enum BackButtonBehavior
3434
/// </summary>
3535
Manual,
3636
}
37-
}
37+
}
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System.Reflection;
6+
using Windows.ApplicationModel;
7+
using Windows.UI.Core;
8+
using Windows.UI.Xaml;
9+
using Windows.UI.Xaml.Controls;
10+
using Windows.UI.Xaml.Navigation;
11+
12+
namespace Microsoft.Toolkit.Uwp.UI.Controls
13+
{
14+
/// <summary>
15+
/// Panel that allows for a List/Details pattern.
16+
/// </summary>
17+
/// <seealso cref="ItemsControl" />
18+
public partial class ListDetailsView
19+
{
20+
private AppViewBackButtonVisibility? _previousSystemBackButtonVisibility;
21+
private bool _previousNavigationViewBackEnabled;
22+
23+
// Int used because the underlying type is an enum, but we don't have access to the enum
24+
private int _previousNavigationViewBackVisibilty;
25+
private Button _inlineBackButton;
26+
private object _navigationView;
27+
private Frame _frame;
28+
29+
/// <summary>
30+
/// Sets the back button visibility based on the current visual state and selected item
31+
/// </summary>
32+
private void SetBackButtonVisibility(ListDetailsViewState? previousState = null)
33+
{
34+
const int backButtonVisible = 1;
35+
36+
if (DesignMode.DesignModeEnabled)
37+
{
38+
return;
39+
}
40+
41+
if (ViewState == ListDetailsViewState.Details)
42+
{
43+
if (BackButtonBehavior == BackButtonBehavior.Inline && _inlineBackButton != null)
44+
{
45+
_inlineBackButton.Visibility = Visibility.Visible;
46+
}
47+
else if (BackButtonBehavior == BackButtonBehavior.Automatic)
48+
{
49+
// Continue to support the system back button if it is being used
50+
SystemNavigationManager navigationManager = SystemNavigationManager.GetForCurrentView();
51+
if (navigationManager.AppViewBackButtonVisibility == AppViewBackButtonVisibility.Visible)
52+
{
53+
// Setting this indicates that the system back button is being used
54+
_previousSystemBackButtonVisibility = navigationManager.AppViewBackButtonVisibility;
55+
}
56+
else if (_inlineBackButton != null && (_navigationView == null || _frame == null))
57+
{
58+
// We can only use the new NavigationView if we also have a Frame
59+
// If there is no frame we have to use the inline button
60+
_inlineBackButton.Visibility = Visibility.Visible;
61+
}
62+
else
63+
{
64+
SetNavigationViewBackButtonState(backButtonVisible, true);
65+
}
66+
}
67+
else if (BackButtonBehavior != BackButtonBehavior.Manual)
68+
{
69+
SystemNavigationManager navigationManager = SystemNavigationManager.GetForCurrentView();
70+
_previousSystemBackButtonVisibility = navigationManager.AppViewBackButtonVisibility;
71+
72+
navigationManager.AppViewBackButtonVisibility = AppViewBackButtonVisibility.Visible;
73+
}
74+
}
75+
else if (previousState == ListDetailsViewState.Details)
76+
{
77+
if (BackButtonBehavior == BackButtonBehavior.Inline && _inlineBackButton != null)
78+
{
79+
_inlineBackButton.Visibility = Visibility.Collapsed;
80+
}
81+
else if (BackButtonBehavior == BackButtonBehavior.Automatic)
82+
{
83+
if (!_previousSystemBackButtonVisibility.HasValue)
84+
{
85+
if (_inlineBackButton != null && (_navigationView == null || _frame == null))
86+
{
87+
_inlineBackButton.Visibility = Visibility.Collapsed;
88+
}
89+
else
90+
{
91+
SetNavigationViewBackButtonState(_previousNavigationViewBackVisibilty, _previousNavigationViewBackEnabled);
92+
}
93+
}
94+
}
95+
96+
if (_previousSystemBackButtonVisibility.HasValue)
97+
{
98+
// Make sure we show the back button if the stack can navigate back
99+
SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility = _previousSystemBackButtonVisibility.Value;
100+
_previousSystemBackButtonVisibility = null;
101+
}
102+
}
103+
}
104+
105+
private void SetNavigationViewBackButtonState(int visible, bool enabled)
106+
{
107+
if (_navigationView == null)
108+
{
109+
return;
110+
}
111+
112+
System.Type navType = _navigationView.GetType();
113+
PropertyInfo visibleProperty = navType.GetProperty("IsBackButtonVisible");
114+
if (visibleProperty != null)
115+
{
116+
_previousNavigationViewBackVisibilty = (int)visibleProperty.GetValue(_navigationView);
117+
visibleProperty.SetValue(_navigationView, visible);
118+
}
119+
120+
PropertyInfo enabledProperty = navType.GetProperty("IsBackEnabled");
121+
if (enabledProperty != null)
122+
{
123+
_previousNavigationViewBackEnabled = (bool)enabledProperty.GetValue(_navigationView);
124+
enabledProperty.SetValue(_navigationView, enabled);
125+
}
126+
}
127+
128+
/// <summary>
129+
/// Closes the details pane if we are in narrow state
130+
/// </summary>
131+
/// <param name="sender">The sender</param>
132+
/// <param name="args">The event args</param>
133+
private void OnFrameNavigating(object sender, NavigatingCancelEventArgs args)
134+
{
135+
if (args.NavigationMode == NavigationMode.Back && ViewState == ListDetailsViewState.Details)
136+
{
137+
ClearSelectedItem();
138+
args.Cancel = true;
139+
}
140+
}
141+
142+
/// <summary>
143+
/// Closes the details pane if we are in narrow state
144+
/// </summary>
145+
/// <param name="sender">The sender</param>
146+
/// <param name="args">The event args</param>
147+
private void OnBackRequested(object sender, BackRequestedEventArgs args)
148+
{
149+
if (ViewState == ListDetailsViewState.Details)
150+
{
151+
// let the OnFrameNavigating method handle it if
152+
if (_frame == null || !_frame.CanGoBack)
153+
{
154+
ClearSelectedItem();
155+
}
156+
157+
args.Handled = true;
158+
}
159+
}
160+
161+
private void OnInlineBackButtonClicked(object sender, RoutedEventArgs e)
162+
{
163+
ClearSelectedItem();
164+
}
165+
}
166+
}

Microsoft.Toolkit.Uwp.UI.Controls.Layout/ListDetailsView/ListDetailsView.Events.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
1010
/// <summary>
1111
/// Panel that allows for a List/Details pattern.
1212
/// </summary>
13-
/// <seealso cref="Windows.UI.Xaml.Controls.ItemsControl" />
13+
/// <seealso cref="ItemsControl" />
1414
public partial class ListDetailsView
1515
{
1616
/// <summary>
@@ -19,7 +19,7 @@ public partial class ListDetailsView
1919
public event SelectionChangedEventHandler SelectionChanged;
2020

2121
/// <summary>
22-
/// Occurs when the view state changes
22+
/// Occurs when the view state changes.
2323
/// </summary>
2424
public event EventHandler<ListDetailsViewState> ViewStateChanged;
2525

@@ -28,4 +28,4 @@ private void OnSelectionChanged(SelectionChangedEventArgs e)
2828
SelectionChanged?.Invoke(this, e);
2929
}
3030
}
31-
}
31+
}

0 commit comments

Comments
 (0)