Windows 8 开发系列 拆分页关键问题分析

近日,在处理拆分页面时,snap_detail始终无法正常返回snap,经过一番摸索,总结如下:

页面状态管理主要有四种页面状态,全屏横向,竖屏,缩屏,满屏。然后拆分页面只是为了设计给缩屏和竖屏视图,让他们可以展示下一级页面状态,当点击列表时,会展示详细页面。

其实就是一个物理页面,在里面展示两个逻辑页面:一个列表,一个详细信息。

比如:

1.拉到缩屏时,进入

 protected override string DetermineVisualState(ApplicationViewState viewState)
        {
            // Update the back button's enabled state when the view state changes
            var logicalPageBack = this.UsingLogicalPageNavigation(viewState) && this.itemListView.SelectedItem != null;
            var physicalPageBack = this.Frame != null && this.Frame.CanGoBack;
            this.DefaultViewModel["CanGoBack"] = logicalPageBack || physicalPageBack;

            // Determine visual states for landscape layouts based not on the view state, but
            // on the width of the window.  This page has one layout that is appropriate for
            // 1366 virtual pixels or wider, and another for narrower displays or when a snapped
            // application reduces the horizontal space available to less than 1366.
            if (viewState == ApplicationViewState.Filled ||
                viewState == ApplicationViewState.FullScreenLandscape)
            {
                var windowWidth = Window.Current.Bounds.Width;
                if (windowWidth >= 1366) return "FullScreenLandscapeOrWide";
                return "FilledOrNarrow";
            }

            // When in portrait or snapped start with the default visual state name, then add a
            // suffix when viewing details instead of the list
            var defaultStateName = base.DetermineVisualState(viewState);
            return logicalPageBack ? defaultStateName + "_Detail" : defaultStateName;
        }

然后进入,判断页面当前的状态

   private bool UsingLogicalPageNavigation(ApplicationViewState? viewState = null)
        {
            if (viewState == null) viewState = ApplicationView.Value;
            return viewState == ApplicationViewState.FullScreenPortrait ||
                viewState == ApplicationViewState.Snapped;
        }

由上可以判断出当的snap,但是这里重写后,判断后返回的字串是:snap_detail

然后回到layoutware.cs,从这里,可以看到视图管理器会定位到页面前端的视图设置,进行隐藏控件等

    private void WindowSizeChanged(object sender, WindowSizeChangedEventArgs e)
        {
            this.InvalidateVisualState();
        }
 public void InvalidateVisualState()
        {
            if (this._layoutAwareControls != null)
            {
                string visualState = DetermineVisualState(ApplicationView.Value);
                foreach (var layoutAwareControl in this._layoutAwareControls)
                {
                    VisualStateManager.GoToState(layoutAwareControl, visualState, false);
                }
            }
        }

当从snap_detail点击返回时,进入代码:

 /// <summary>
        /// Invoked when the page's back button is pressed.
        /// </summary>
        /// <param name="sender">The back button instance.</param>
        /// <param name="e">Event data that describes how the back button was clicked.</param>
        protected override void GoBack(object sender, RoutedEventArgs e)
        {
            if (this.UsingLogicalPageNavigation() && itemListView.SelectedItem != null)
            {
                // When logical page navigation is in effect and there's a selected item that
                // item's details are currently displayed.  Clearing the selection will return to
                // the item list.  From the user's point of view this is a logical backward
                // navigation.
                this.itemListView.SelectedItem = null;
            }
            else
            {
                // When logical page navigation is not in effect, or when there is no selected
                // item, use the default back button behavior.
                base.GoBack(sender, e);
            }
        }
    void ItemListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (this.UsingLogicalPageNavigation()) this.InvalidateVisualState();
        }

进入InvalidateVisualState()再去判断当前状态,此时: string visualState = DetermineVisualState(ApplicationView.Value);

当listview.selectitem=null时,导致logicalPageBack=false,说明不再是逻辑页面的返回了,而是物理返回前一个页面,所以关键在这,对选中的item的判断,会直接左右是否逻辑返回。

而我当时由于缺少下面这个方法,所以无法实现逻辑返回

     void ItemListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (this.UsingLogicalPageNavigation()) this.InvalidateVisualState();
        }
 protected override void GoBack(object sender, RoutedEventArgs e)
        {
            if (this.UsingLogicalPageNavigation() && itemListView.SelectedItem != null)
            {
                // When logical page navigation is in effect and there's a selected item that
                // item's details are currently displayed.  Clearing the selection will return to
                // the item list.  From the user's point of view this is a logical backward
                // navigation.
                this.itemListView.SelectedItem = null;
            }
            else
            {
                // When logical page navigation is not in effect, or when there is no selected
                // item, use the default back button behavior.
                base.GoBack(sender, e);
            }
        }

所以在Goback方法中只对this.itemListView.SelectedItem = null;

没有changed事件再去判断整个页面的状态去到何处,所以也出现了点Goback没反应的情况了。

当点击数下时,此时selectitem=null,就会直接去到返回方法,真正返回到前一页面


if (this.UsingLogicalPageNavigation() && itemListView.SelectedItem != null)

        base.GoBack(sender, e);


作者:johnny 出处:http://www.cnblogs.com/sunjunlin 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
原文地址:https://www.cnblogs.com/sunjunlin/p/2804642.html