简化版“询问用户是否退出”

   这篇是 Windows Phone 自定义弹出框和 Toast 通知 的简化版,区别就是之前的自定义 MessageBox

控件是整个 app 中所有页面共享的,下面的简化版 MessageBox 只是应用于 MainPage 页面中,“询问

用户是否退出”的自定义弹出框。

 

     在应用或游戏程序中,经常的一个场景就是在用户点击 Back 键时,应用询问用户是否退出,通常是重写

Page 页面的事件:

 protected override async void OnBackKeyPress(System.ComponentModel.CancelEventArgs e)

 

但是,当弹出 MessageBox 10秒钟用户没有响应,应用则会退出,其实并不是 MessageBox 的 Bug,只要阻塞

OnBackKeyPress() 方法超过 10秒 ,应用都会退出的,如果先调用 e.Cancle = true 取消导航,再询问用户

是否退出,就不会出现这个问题。如果用户点击“确定”,则调用   App.Current.Terminate(); 结束当前应用进程。

 

 一种简单的方式是:

        protected override void OnBackKeyPress(System.ComponentModel.CancelEventArgs e)

        {

            e.Cancel = true;



            this.Dispatcher.BeginInvoke(delegate 

            {

                if (MessageBox.Show("确定退出?", "提示", MessageBoxButton.OKCancel) == MessageBoxResult.OK)

                {

                    App.Current.Terminate();

                }

            });



            base.OnBackKeyPress(e);

        }

 

 

另一种方式:

   为了解决这个问题,方式之一就是自定义一个 MessageBox 控件:

   页面的交互如下图:

简化版“询问用户是否退出”

 

第一步:自定义一个名为 MyDialog 的用户控件,页面的主要 xaml:

        <Grid  x:Name="gridDialog" Background="#33000000">

            <Grid Height="280" x:Name="gridBox" VerticalAlignment="Top" Background="#ff1ba0e1">

                <Grid.Projection>

                    <PlaneProjection/>

                </Grid.Projection>

                <Grid.RowDefinitions>

                    <RowDefinition Height="60"/>

                    <RowDefinition Height="150"/>

                    <RowDefinition Height="70"/>

                </Grid.RowDefinitions>

                <TextBlock Text="提示信息" x:Name="txtTitle" FontSize="25" Margin="25,10, 0, 0"/>

                <!--该控件的 Content 属性的内容值可以是字符串或者其它 UIElement-->

                <ContentControl HorizontalAlignment="Left" FontSize="30" Margin="40, 0, 0, 0" 
Content
="文本内容文本" Grid.Row="1" x:Name="contentContainer"/>
<StackPanel Grid.Row="2" Orientation="Horizontal"> <Button x:Name="btnOk" Content="OK" Width="200" Click="btnOk_Click"/> <Button x:Name="btnCancle" Content="Cancel" Width="200" Click="btnCancle_Click"/> </StackPanel> </Grid> </Grid>


自定义弹出框相应的 C# :

   public partial class MyDialog : UserControl

    {

        public MyDialog()

        {

            InitializeComponent();



            gridDialog.Visibility = System.Windows.Visibility.Collapsed;



            // 把第一个实例赋值给全局静态对象

            if (_instance == null)

                _instance = this;

        }



        //用来控制异步线程中 弹出框 结果返回的时机

        private static AutoResetEvent myResetEvent = new AutoResetEvent(false);



        static MessageBoxResult messageBoxResult;



        //用一个单一实例,使得应用中的所有页面使用同一个实例

        static MyDialog _instance;

        static MyDialog Instance

        {

            get

            {

                //if (_instance == null)

                //    _instance = new MyDialog();



                return _instance;

            }

        }



        /// <summary>

        /// 显示包含指定文本、标题栏标题和响应按钮的消息框

        /// </summary>

        /// <param name="messageBoxText">要显示的消息</param>

        /// <param name="caption">消息框的标题</param>

        /// <param name="button">一个值,用于指示要显示哪个按钮或哪些按钮</param>

        /// <returns>一个值,用于指示用户对消息的响应</returns>

        public static Task<MessageBoxResult> Show(string messageBoxText, string caption, MessageBoxButton button)

        {

            return Task<MessageBoxResult>.Factory.StartNew(() =>

            {

                Instance.Dispatcher.BeginInvoke(delegate

                {



                    Instance.gridDialog.Visibility = Visibility.Visible;



                    Instance.contentContainer.Content = messageBoxText;



                    Instance.txtTitle.Text = caption;



                    if (button == MessageBoxButton.OKCancel)

                    {

                        Instance.btnCancle.Visibility = Visibility.Visible;

                    }

                    else

                    {

                        Instance.btnCancle.Visibility = Visibility.Collapsed;

                    }



                    //Instance.UpdateLayout();



                    Instance.ShowMessageBoxSB.Stop();

                    Instance.ShowMessageBoxSB.Begin();

                });





                myResetEvent.WaitOne();



                return messageBoxResult;

            });

        }



        private void btnOk_Click(object sender, RoutedEventArgs e)

        {

            txtTitle.Text = "";

            contentContainer.Content = null;



            gridDialog.Visibility = System.Windows.Visibility.Collapsed;



            messageBoxResult = MessageBoxResult.OK;



            // 使异步线程的 Show() 方法继续执行

            myResetEvent.Set();

        }



        private void btnCancle_Click(object sender, RoutedEventArgs e)

        {

            txtTitle.Text = "";

            contentContainer.Content = null;



            gridDialog.Visibility = System.Windows.Visibility.Collapsed;



            messageBoxResult = MessageBoxResult.Cancel;



            myResetEvent.Set();

        }







        // 用来控制当弹出框显示的时候,如果用户点击 Back 按键,则隐藏弹出框,

        // 在 App.xaml.cs 中的 RootFrame_Navigating 事件中调用

        public static bool DialogIsOpen

        {

            get

            {

                if (Instance != null && Instance.gridDialog.Visibility == Visibility.Visible)

                {

                    Instance.btnCancle_Click(null, null);



                    return true;

                }

                else

                {

                    return false;

                }

            }

        }

    }

 

第二步:在 MainPage.xaml 页面中,添加如下代码:

 <local:MyDialog Grid.RowSpan="2"  xmlns:local="clr-namespace:SimpleDialogDemo"/>


在相应的 C# 页面,重写 OnBackKeyPress 方法:

      protected override async void OnBackKeyPress(System.ComponentModel.CancelEventArgs e)

      {

          // 首先取消默认 Back 键关闭应用

          e.Cancel = true;



          // 如果 MainPage 页面中,弹出了其它的弹出框,关闭它,

          // 在 DialogIsOpen 属性中实现

          if (MyDialog.DialogIsOpen)

          {

              //可以做其它事情

          }

          else

          {

              if (MessageBoxResult.OK == await MyDialog.Show("确定要退出吗?", "温馨提示:", MessageBoxButton.OKCancel))

              {

                  //  终止当前应用程序。该方法是在 WP8 中加入的,WP7 中木有

                  App.Current.Terminate();

              }

          }



          base.OnBackKeyPress(e);

      }

 

代码工程下载

你可能感兴趣的:(用户)