• 背水一战 Windows 10 (4)


    [源码下载]


    背水一战 Windows 10 (4) - UI: 多窗口



    作者:webabcd


    介绍
    背水一战 Windows 10 之 UI

    • 多窗口



    示例
    1、自定义帮助类,用于简化 SecondaryView 的管理
    UI/MultipleViews/SecondaryViewHelper.cs

    /*
     * SecondaryViewHelper - 自定义的一个帮助类,用于简化 SecondaryView 的管理
     */
    
    using System;
    using System.ComponentModel;
    using Windows.UI.Core;
    using Windows.UI.ViewManagement;
    
    namespace Windows10.UI.MultipleViews
    {
        public class SecondaryViewHelper : INotifyPropertyChanged
        {
            // for INotifyPropertyChanged
            public event PropertyChangedEventHandler PropertyChanged;
    
            // 当前 SecondaryView 的 CoreDispatcher
            private CoreDispatcher _dispatcher;
            // 当前 SecondaryView 的 ApplicationView
            private ApplicationView _applicationView;
    
            // 当前 SecondaryView 的标题
            private string _title;
            // 当前 SecondaryView 的窗口标识
            private int _viewId;
    
            // 当前 SecondaryView 被引用的次数
            private int _refCount = 0;
            // 当前 SecondaryView 是否已经被释放
            private bool _released = false;
    
            // 禁止通过 new 实例化
            private SecondaryViewHelper(CoreWindow newWindow)
            {
                _dispatcher = newWindow.Dispatcher;
                _viewId = ApplicationView.GetApplicationViewIdForWindow(newWindow);
    
                _applicationView = ApplicationView.GetForCurrentView();
    
                RegisterForEvents();
            }
    
            // 实例化 SecondaryViewHelper
            public static SecondaryViewHelper CreateForCurrentView()
            {
                /*
                 * CoreWindow.GetForCurrentThread() - 获取当前窗口的 CoreWindow
                 */
                return new SecondaryViewHelper(CoreWindow.GetForCurrentThread());
            }
            private void RegisterForEvents()
            {
                /*
                 * ApplicationView.GetForCurrentView() - 获取当前窗口的 ApplicationView
                 * ApplicationView.Consolidated - 当前 app 存活着两个或两个以上的窗口时,此窗口关闭后触发的事件
                 */
                ApplicationView.GetForCurrentView().Consolidated += SecondaryViewHelper_Consolidated;
            }
    
            private void UnregisterForEvents()
            {
                ApplicationView.GetForCurrentView().Consolidated -= SecondaryViewHelper_Consolidated;
            }
    
            private void SecondaryViewHelper_Consolidated(ApplicationView sender, ApplicationViewConsolidatedEventArgs args)
            {
                StopViewInUse();
            }
    
            // 当前 SecondaryView 开始使用了(与 StopViewInUse() 成对)
            // 因为每一个窗口都可以被同 app 的别的窗口调用,而每一个窗口又都是一个独立的线程,所以要做好线程处理
            public int StartViewInUse()
            {
                bool releasedCopy = false;
                int refCountCopy = 0;
    
                lock (this)
                {
                    releasedCopy =_released;
                    if (!_released)
                    {
                        refCountCopy = ++_refCount;
                    }
                }
    
                if (releasedCopy)
                {
                    throw new InvalidOperationException("this view is being disposed");
                }
    
                return refCountCopy;
            }
    
            // 当前 SecondaryView 结束使用了(与 StartViewInUse() 成对)
            // 因为每一个窗口都可以被同 app 的别的窗口调用,而每一个窗口又都是一个独立的线程,所以要做好线程处理
            public int StopViewInUse()
            {
                int refCountCopy = 0;
                bool releasedCopy = false;
    
                lock (this)
                {
                    releasedCopy = _released;
                    if (!_released)
                    {
                        refCountCopy = --_refCount;
                        if (refCountCopy == 0)
                        {
                            // 当前 SecondaryView 不再被任何人需要了,清理之
                            var task = _dispatcher.RunAsync(CoreDispatcherPriority.Low, FinalizeRelease);
                        }
                    }
                }
    
                if (releasedCopy)
                {
                    throw new InvalidOperationException("this view is being disposed");
                }
    
                return refCountCopy;
            }
    
            // 清理当前 SecondaryView
            private void FinalizeRelease()
            {
                bool justReleased = false;
                lock (this)
                {
                    if (_refCount == 0)
                    {
                        justReleased = true;
                        _released = true;
                    }
                }
    
                if (justReleased)
                {
                    UnregisterForEvents();
    
                    // 触发 Released 事件
                    OnReleased(EventArgs.Empty);
                }
            }
    
            // 定义 Released 事件
            public event EventHandler<EventArgs> Released;
            protected virtual void OnReleased(EventArgs e)
            {
                EventHandler<EventArgs> handler = Released;
                if (handler != null)
                    handler(this, e);
            }
    
            public int Id
            {
                get
                {
                    return _viewId;
                }
            }
    
            public string Title
            {
                get
                {
                    return _title;
                }
                set
                {
                    if (_title != value)
                    {
                        _title = value;
    
                        if (PropertyChanged != null)
                        {
                            PropertyChanged(this, new PropertyChangedEventArgs(nameof(Title)));
                        }
                    }
                }
            }
    
            public bool IsReleased
            {
                get
                {
                    return _released;
                }
            }
    
            public ApplicationView ApplicationView
            {
                get
                {
                    return _applicationView;
                }
            }
        }
    }


    2、扩展 Application 对象,定义一些需要用到的全局变量
    UI/MultipleViews/AppPartial.cs

    /*
     * 扩展 Application 对象,定义一些需要用到的全局变量
     */
    
    using Windows.ApplicationModel.Activation;
    using Windows.UI.Core;
    using Windows.UI.ViewManagement;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    
    namespace Windows10
    {
        public partial class App
        {
            // PrimaryView 的 CoreDispatcher
            private CoreDispatcher _mainDispatcher;
            // PrimaryView 的窗口标识
            private int _mainViewId;
    
            // partial method,实现了 App.xaml.cs 中的声明
            partial void OnLaunched_MultipleViews(LaunchActivatedEventArgs args)
            {
                _mainDispatcher = Window.Current.Dispatcher;
                _mainViewId = ApplicationView.GetForCurrentView().Id;
            }
            
            public CoreDispatcher MainDispatcher
            {
                get
                {
                    return _mainDispatcher;
                }
            }
            
            public int MainViewId
            {
                get
                {
                    return _mainViewId;
                }
            }
        }
    }


    3、用于演示 SecondaryView 的示例
    UI/MultipleViews/SecondaryViewPage.xaml

    <Page
        x:Class="Windows10.UI.MultipleViews.SecondaryViewPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:Windows10.UI.MultipleViews"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
    
        <Grid Background="Transparent">
            <StackPanel Margin="10 0 10 10">
    
                <TextBlock Name="lblMsg" Margin="0 10 0 0" />
    
                <Button Name="btnGoToMain" Content="切换到主窗口" Click="btnGoToMain_Click" Margin="0 10 0 0" />
    
                <Button Name="btnGoToMainAndHideThisView" Content="切换到主窗口,并关闭此窗口" Click="btnGoToMainAndHideThisView_Click" Margin="0 10 0 0" />
    
            </StackPanel>
        </Grid>
    </Page>

    UI/MultipleViews/SecondaryViewPage.xaml.cs

    /*
     * 演示“多窗口”相关知识点。本页是 SecondaryView
     */
    
    using System;
    using System.ComponentModel;
    using Windows.ApplicationModel.Core;
    using Windows.UI.Core;
    using Windows.UI.ViewManagement;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    using Windows.UI.Xaml.Navigation;
    
    namespace Windows10.UI.MultipleViews
    {
        public sealed partial class SecondaryViewPage : Page
        {
            private SecondaryViewHelper _secondaryViewHelper;
    
            public SecondaryViewPage()
            {
                this.InitializeComponent();
            }
    
            protected override void OnNavigatedTo(NavigationEventArgs e)
            {
                _secondaryViewHelper = (SecondaryViewHelper)e.Parameter;
                _secondaryViewHelper.Released += _secondaryViewHelper_Released;
    
                // 设置当前窗口的 Title
                ApplicationView.GetForCurrentView().Title = _secondaryViewHelper.Title;
                _secondaryViewHelper.PropertyChanged += _secondaryViewHelper_PropertyChanged;
            }
    
            private void _secondaryViewHelper_PropertyChanged(object sender, PropertyChangedEventArgs e)
            {
                if (e.PropertyName == nameof(_secondaryViewHelper.Title))
                {
                    _secondaryViewHelper.ApplicationView.Title = _secondaryViewHelper.Title;
                }
            }
    
            private async void _secondaryViewHelper_Released(object sender, EventArgs e)
            {
                ((SecondaryViewHelper)sender).Released -= _secondaryViewHelper_Released;
    
                await ((App)App.Current).MainDispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
                {
                    // 调用主窗口线程,执行逻辑
                });
    
                Window.Current.Close();
            }
    
            private async void btnGoToMain_Click(object sender, RoutedEventArgs e)
            {
                _secondaryViewHelper.StartViewInUse();
    
                /*
                 * ApplicationViewSwitcher.SwitchAsync() - 切换到指定的窗口
                 */
                await ApplicationViewSwitcher.SwitchAsync
                (
                    ((App)App.Current).MainViewId // 准备显示的窗口的 id
                );
    
                _secondaryViewHelper.StopViewInUse();
            }
    
            private async void btnGoToMainAndHideThisView_Click(object sender, RoutedEventArgs e)
            {
                _secondaryViewHelper.StartViewInUse();
    
                /*
                 * ApplicationViewSwitcher.SwitchAsync() - 切换到指定的窗口
                 */
                await ApplicationViewSwitcher.SwitchAsync
                (
                    ((App)App.Current).MainViewId, // 准备显示的窗口的 id
                    ApplicationView.GetForCurrentView().Id, // 调用者的窗口 id
                    ApplicationViewSwitchingOptions.ConsolidateViews // 切换行为选项(Default - 标准动画切换; SkipAnimation - 不使用动画切换; ConsolidateViews - 切换后关闭调用者窗口)
                );
    
                _secondaryViewHelper.StopViewInUse();
            }
        }
    }


    4、用于演示 PrimaryView 的示例
    UI/MultipleViews/Demo.xaml

    <Page
        x:Class="Windows10.UI.MultipleViews.Demo"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:Windows10.UI.MultipleViews"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
    
        <Grid Background="Transparent">
            <StackPanel Margin="10 0 10 10">
    
                <TextBlock Name="lblMsg" Margin="0 10 0 0" />
    
                <Button Name="btnShow" Content="创建并显示一个新的窗口" Click="btnShow_Click" Margin="0 10 0 0" />
    
                <Button Name="btnChangeLastSecondaryViewTitle" Content="修改最近一个被我打开的 SecondaryView 的 Title" Click="btnChangeLastSecondaryViewTitle_Click" Margin="0 10 0 0" />
    
            </StackPanel>
        </Grid>
    </Page>

    UI/MultipleViews/Demo.xaml.cs

    /*
     * 演示“多窗口”相关知识点。本页是 PrimaryView
     *
     *
     * 解释一下本例中用于说明的几个名词:PrimaryView - 主窗口; SecondaryView - 新开窗口
     */
    
    using System;
    using Windows.ApplicationModel.Core;
    using Windows.UI.Core;
    using Windows.UI.ViewManagement;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    
    namespace Windows10.UI.MultipleViews
    {
        public sealed partial class Demo : Page
        {
            // 自定义的用于简化 SecondaryView 管理的帮助类
            SecondaryViewHelper _secondaryViewHelper = null;
    
            public Demo()
            {
                this.InitializeComponent();
    
                this.Loaded += Demo_Loaded;
            }
    
            private void Demo_Loaded(object sender, RoutedEventArgs e)
            {
                ApplicationView.PreferredLaunchWindowingMode = ApplicationViewWindowingMode.Auto;
            }
    
            private async void btnShow_Click(object sender, RoutedEventArgs e)
            {
                /*
                 * CoreApplication.CreateNewView() - 创建一个新的 SecondaryView(只是新建一个 SecondaryView 实例,并不会显示出来)
                 */
                await CoreApplication.CreateNewView().Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
                {
                    _secondaryViewHelper = SecondaryViewHelper.CreateForCurrentView();
                    _secondaryViewHelper.Title = "i am secondary view";
    
                    _secondaryViewHelper.StartViewInUse();
    
                    var frame = new Frame();
                    frame.Navigate(typeof(SecondaryViewPage), _secondaryViewHelper);
                    Window.Current.Content = frame;
                    Window.Current.Activate();
    
                    // 这里通过 ApplicationView.GetForCurrentView() 获取到的是新开窗口的 ApplicationView 对象
                    ApplicationView secondaryView = ApplicationView.GetForCurrentView();
                });
    
                try
                {
                    _secondaryViewHelper.StartViewInUse();
    
                    /*
                     * ApplicationViewSwitcher.TryShowAsStandaloneAsync() - 在当前窗口的相邻位置显示另一个窗口
                     */
                    ApplicationViewSwitcher.DisableShowingMainViewOnActivation();
                    var viewShown = await ApplicationViewSwitcher.TryShowAsStandaloneAsync
                    (
                        _secondaryViewHelper.Id, // 需要显示的 SecondaryView 的窗口 id
                        ViewSizePreference.Default, // 需要显示的 SecondaryView 的尺寸首选项(经测试,此参数无效)
                        ApplicationView.GetForCurrentView().Id, // 调用者的窗口 id
                        ViewSizePreference.Default // 调用者的尺寸首选项(经测试,此参数无效)
                    );
    
                    if (!viewShown)
                    {
                        lblMsg.Text = "显示 SecondaryView 失败";
                    }
    
                    _secondaryViewHelper.StopViewInUse();
                }
                catch (Exception ex)
                {
                    lblMsg.Text = ex.ToString();
                }
            }
    
            // 修改最近一个被我打开的 SecondaryView 的 Title
            private void btnChangeLastSecondaryViewTitle_Click(object sender, RoutedEventArgs e)
            {
                if (_secondaryViewHelper != null && !_secondaryViewHelper.IsReleased)
                    _secondaryViewHelper.Title = new Random().Next().ToString();
            }
        }
    }



    OK
    [源码下载]

  • 相关阅读:
    《团队名称》第八次团队作业:Alpha冲刺
    《代码敲不队》第八次团队作业:Alpha冲刺 第四天
    《代码敲不队》第八次团队作业:Alpha冲刺 第三天
    《代码敲不队》第八次团队作业:Alpha冲刺 第二天
    《代码敲不队》第八次团队作业:Alpha冲刺 第一天
    【Beta】Scrum meeting 3
    【Beta】Scrum meeting 2
    《队长说得队》第九次团队作业:Beta冲刺与验收准备
    【Beta】Scrum meeting 1
    《队长说得队》【Alpha】Scrum meeting 5
  • 原文地址:https://www.cnblogs.com/webabcd/p/5318129.html
Copyright © 2020-2023  润新知