UWP 快速的Master/Detail实现

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UWP 快速的Master/Detail实现相关的知识,希望对你有一定的参考价值。

最近在写快报(还没有写完)的过程中,一开始就遇到了这个Master/Detail如何实现的问题。

微软给出Demo并不符合要求,搜索后找到了今日头条开发者写的一篇 :实现Master/Detail布局

拜读之后感觉实现有些麻烦,所以呢这里给出一个更快速的实现。

 

好滴,下面直接进入正题。

为了实现Master/Detail我决定和今日头条开发者一样采用左右各一个Frame来托管页面

        <Grid.ColumnDefinitions>
            <ColumnDefinition x:Name="MasterColumn" Width="500" />
            <ColumnDefinition x:Name="DetailColumn" Width="*" />
        </Grid.ColumnDefinitions>

这里左侧给出的宽度为500作为新闻列表的宽度

然后添加两个Frame

        <Frame x:Name="MasterFrame" Grid.Column="0" x:FieldModifier="Public">

        </Frame>

        <Frame x:Name="DetailFrame" Grid.Column="1" x:FieldModifier="Public">

        </Frame>

然后呢我们为添加一个VisualState,并且添加CurrentStateChanged事件

        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="AdaptiveStates" CurrentStateChanged="AdaptiveStates_CurrentStateChanged">
                <VisualState x:Name="DefaultState">
                    <VisualState.StateTriggers>
                        <AdaptiveTrigger MinWindowWidth="720"></AdaptiveTrigger>
                    </VisualState.StateTriggers>
                </VisualState>
                <VisualState x:Name="NarrowState">
                    <VisualState.StateTriggers>
                        <AdaptiveTrigger MinWindowWidth="0"></AdaptiveTrigger>
                    </VisualState.StateTriggers>
                    <VisualState.Setters>
                        <Setter Target="MasterColumn.Width" Value="*" />
                        <Setter Target="DetailColumn.Width" Value="0" />
                        <Setter Target="DetailFrame.(Grid.Column)" Value="0"/>
                    </VisualState.Setters>
                </VisualState>
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>

看到这里想必各位已经知道了如何实现了,就是在NarrowState的时候主动把右侧的Column宽度设置为0,然后把DetailFrame从右侧移到左侧,此时DetailFrame会覆盖在MasterFrame之上。那么你肯定会问要是DetailFrame里没有内容呢?本应该显示MasterFrame的,但现在DetailFrame将其遮盖了。

其实这就是上面为什么要监听CurrenStateChanged事件的原因

在CurrentStateChanged事件里可以判断如果DetailFrame中内容为空,直接将其设置为不可见就可以了。

下面给出这个函数的代码

        private void AdaptiveStates_CurrentStateChanged(object sender, VisualStateChangedEventArgs e)
        {
            UpdateUI();
        }

        private void UpdateUI()
        {
            if (AdaptiveStates.CurrentState.Name == "NarrowState")
            {
                DetailFrame.Visibility = DetailFrame.CanGoBack ? Visibility.Visible : Visibility.Collapsed;
            }
            SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility = DetailFrame.CanGoBack || MasterFrame.CanGoBack ? AppViewBackButtonVisibility.Visible : AppViewBackButtonVisibility.Collapsed;
        }

为了能在实现在NarrowState的情况下从点击MasterFrame中的新闻之后可以让DetailFrame从不可见变为可见还需要订阅MasterFrame的Navigated事件

为了在按下后退键后DetailFrame被清空后可以返回MasterFrame同样还需要订阅DetailFrame的Navigated事件

所以呢在构造函数如下

        public MainPage()
        {
            this.InitializeComponent();
            this.NavigationCacheMode = NavigationCacheMode.Required;
            #region Event
            DetailFrame.Navigated += DetailFrame_Navigated;
            MasterFrame.Navigated += MasterFrame_Navigated;
            SystemNavigationManager.GetForCurrentView().BackRequested += View_BackRequested;
            #endregion
        }
        private void MasterFrame_Navigated(object sender, NavigationEventArgs e)
        {
            UpdateUI();
        }

        private void DetailFrame_Navigated(object sender, NavigationEventArgs e)
        {
            while (DetailFrame.BackStack.Count > 1)
            {
                DetailFrame.BackStack.RemoveAt(1);
            }
            UpdateUI();
        }

这里需要交代一下快报的情况,DetailFrame默认会有一个背景页面而且默认DetailFrame页面深度为2所以会主动清空上一次的详细页面,这就是RemoveAt(1)的原因。

同样的后退键事件处理函数如下:

        private void View_BackRequested(object sender, BackRequestedEventArgs e)
        {
            if (DetailFrame.CanGoBack)
            {
                DetailFrame.GoBack();
                e.Handled = true;
            }
            else if (MasterFrame.CanGoBack)
            {
                MasterFrame.GoBack();
                e.Handled = true;
            }
        }

大体的思路就是这样,具体的代码还是直接看源码吧!懒得粘贴了。源文件

最终实现的效果如图:

技术分享

技术分享

技术分享

 

以上是关于UWP 快速的Master/Detail实现的主要内容,如果未能解决你的问题,请参考以下文章

Win10 UWP开发系列:实现Master/Detail布局

UWP:ListView ItemClick 不起作用

UWP简单示例:快速开始你的MineCraft

在并行位片代码中实现快速计数器

uwp UI自动化测试(WinAppDriver)

Xamarin Forms Master Detail 将 Master 保留在左侧