Due to DisplayMode by default is set to CompactInLine the adaptive triggers do not fire if the app is launched on a phone emulator. The proper DisplayMode for a phone should be set to Overlay.
I've noticed the same issue (on a real device). I think the OnStateChanged()-Event should be somehow fired on inital launch.
Is this in dev nightly or production?
I'm facing this in production
Quick workaround
If using Code Behind
In ShellPage.xaml.cs
Change the Initialize method to be like this:
private void Initialize()
{
NavigationService.Frame = shellFrame;
NavigationService.Frame.Navigated += NavigationService_Navigated;
PopulateNavItems();
if (Window.Current.Bounds.Width < 640)
{
GoToState(NarrowStateName);
}
}
Add the method GoToState
private void GoToState(string stateName)
{
switch (stateName)
{
case PanoramicStateName:
DisplayMode = SplitViewDisplayMode.CompactInline;
break;
case WideStateName:
DisplayMode = SplitViewDisplayMode.CompactInline;
IsPaneOpen = false;
break;
case NarrowStateName:
DisplayMode = SplitViewDisplayMode.Overlay;
IsPaneOpen = false;
break;
default:
break;
}
}
Change WindowStates_CurrentStateChanged to be
private void WindowStates_CurrentStateChanged(object sender, VisualStateChangedEventArgs e)
{
GoToState(e.NewState.Name);
}
If using MVVMBasic or MVVM Light
In ShellViewModel.
Add GoToState as above.
Change the following methods to be as below.
public void Initialize(Frame frame)
{
NavigationService.Frame = frame;
NavigationService.Frame.Navigated += NavigationService_Navigated;
PopulateNavItems();
if (Window.Current.Bounds.Width < 640)
{
GoToState(NarrowStateName);
}
}
private void OnStateChanged(VisualStateChangedEventArgs args)
{
GoToState(args.NewState.Name);
}
Hopefully, the above workaround unblocks anyone affected by this.
Now to discuss the best solution.
There are two issues here.
Issue 1
In the past, I've always ended up with a bit of code behind to query the screen bounds for this kind of thing. I don't think there's a pure XAML way to address this.
However, I do think we could move a some of the current CS code into XAML using VisualState Setters.
We could also do with a review and guidance on which pages (beyond NavPanel) should include their own adaptive triggers for with changes. At the moment it's not all and it would be good to remove the inconsistencies or document why they're there.
Open to input from anyone with input and expertise in this area and how they may have addressed this issue in the past.
Issue 2
Would be good to get input from some more people before submitting a PR with the workaround.
@mrlacey your fix is working for me (MVVM Light), thanks!
Fixed on the following PR
馃槥 My hacky workaround was not an elegant way of solving this issue and it's disappointing to see that's what's been implemented. There was a reason I didn't implement this as a fix when looking at the original bug.
Would be good to get input from some more people before submitting a PR with the workaround.
I have the following issues with the solution as implemented:
@mrlacey you have 100% valid questions. We implement this way as a "quick and dirty" workarround, but maybe we should consider review it and give a deep reflection.
Thanks for pointing.
I think we're ok with quick and dirt inside the engine, for templates, the bar is much higher.
This code is in the templates.
If doing something a quick fix an issue needs to be raised at the same time to go back and address the issue in more detail at a later time otherwise it will be forgotten and not get done.
There are a few possibilities.
Setting changes from XAML is more clean but it is less flexible.
``` xaml
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="WindowStates">
<i:Interaction.Behaviors>
<ic:EventTriggerBehavior EventName="CurrentStateChanged">
<ic:InvokeCommandAction Command="{x:Bind ViewModel.StateChangedCommand}"/>
</ic:EventTriggerBehavior>
</i:Interaction.Behaviors>
<VisualState x:Name="PanoramicState">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="1024"/>
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="NavigationMenu.DisplayMode" Value="CompactInline"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="WideState">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="640"/>
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="NavigationMenu.DisplayMode" Value="CompactInline"/>
<Setter Target="NavigationMenu.IsPaneOpen" Value="False"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="NarrowState">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="0"/>
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="NavigationMenu.DisplayMode" Value="Overlay"/>
<Setter Target="NavigationMenu.IsPaneOpen" Value="False"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
We have also a difficult way to close the menu on item clicked, making some things in Xaml and others in view model CS.
I propose to improve the workaround:
```CSharp
private const string PanoramicStateName = "PanoramicState";
private const string WideStateName = "WideState";
private const string NarrowStateName = "NarrowState";
private const double WideStateMinWindowWidth = 640;
private const double PanoramicStateMinWindowWidth = 1024;
public void Initialize(Frame frame)
{
NavigationService.Frame = frame;
NavigationService.Frame.Navigated += NavigationService_Navigated;
PopulateNavItems();
InitializeState(Window.Current.Bounds.Width);
}
private void InitializeState(double windowWith)
{
if (windowWith < WideStateMinWindowWidth)
{
GoToState(NarrowStateName);
}
else if (windowWith < PanoramicStateMinWindowWidth)
{
GoToState(WideStateName);
}
else
{
GoToState(PanoramicStateName);
}
}
private void GoToState(string stateName)
{
switch (stateName)
{
case PanoramicStateName:
DisplayMode = SplitViewDisplayMode.CompactInline;
break;
case WideStateName:
DisplayMode = SplitViewDisplayMode.CompactInline;
IsPaneOpen = false;
break;
case NarrowStateName:
DisplayMode = SplitViewDisplayMode.Overlay;
IsPaneOpen = false;
break;
default:
break;
}
}
What do you think @mrlacey ?
Added in PR
Also add chart page to title trigger composition template (new bug found testing on Lumia Phone)
Has this been resolved yet? Shouldn't most of this code live inside the actual navpane control itself?
There's a workaround in but it's not perfect. The underlying issue is there's nothing in the SDK that will trigger the event to set the appropriate state on launch purely from XAML. While we could change it so that the default state was the small/narrow/phone one this still wouldn't be a 100% solution and we'd still have to resort to something from code behind.
I think we can close this out as the real issue is a limitation of the SplitView control.
I think we can close out this.
let me ask around if there isn't something magical we are missing. if not we can close this out