博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Windows Phone 自定义弹出框和 Toast 通知
阅读量:4553 次
发布时间:2019-06-08

本文共 9063 字,大约阅读时间需要 30 分钟。

   

 

注:这篇文章主要介绍在 应用全局所有页面使用的自定义弹出框,如果仅在 MainPage 页面询问用户是否

是否退出,可参考: 

 

1、 首先介绍如何自定义弹出框

    在 WP 中,系统默认的弹出框有几个问题,首先是背景比较简陋,而且样式的扩展性比较低,另一个问题就

是会阻碍 UI 线程。当在页面的调用下面的代码:

if(MessageBoxResult.OK != MessageBox.Show("确定要退出吗?", "温馨提示", MessageBoxButton.OKCancel))            {                e.Cancel = true;            }

当在 MainPage 页面点击 Back 键,会弹出:

 当在10秒钟的时候,如果用户没有回馈,那么应用就会被系统终结了。

        下面开始做一个自定义的弹出框:

1)自定义一个控件,定义在 MyDialog.xaml 文件中:

  相应的 C# 页面:

public MyDialog()        {            InitializeComponent();            gridDialog.Visibility = System.Windows.Visibility.Collapsed;            // 把第一个实例赋值给全局静态对象            if (_instance == null)                _instance = this;        }        #region “确定”弹出框        //用来控制异步线程中 弹出框 结果返回的时机        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;            }        }        // 用来控制当弹出框显示的时候,如果用户点击 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;                }            }        }        ///         /// 显示包含指定文本和“确定”按钮的消息框        ///         /// 要显示的消息        /// 
在所有情况下均为 System.Windows.MessageBoxResult.OK
public static Task
Show(string messageBoxText) { return Task
.Factory.StartNew(() => { Instance.Dispatcher.BeginInvoke(delegate { Instance.gridDialog.Visibility = Visibility.Visible; Instance.contentContainer.Content = messageBoxText; Instance.txtTitle.Text = ""; Instance.btnCancle.Visibility = Visibility.Collapsed; Instance.ShowMessageBoxSB.Stop(); Instance.ShowMessageBoxSB.Begin(); }); myResetEvent.WaitOne(); return messageBoxResult; }); } ///
/// 显示包含指定文本、标题栏标题和响应按钮的消息框 /// ///
要显示的消息 ///
消息框的标题 ///
一个值,用于指示要显示哪个按钮或哪些按钮 ///
一个值,用于指示用户对消息的响应
public static Task
Show(string messageBoxText, string caption, MessageBoxButton button) { return Task
.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(); } #endregion

     另一个问题就是,让这个自定义控件变成全局的,也就是所有工程里的页面,共享

      这一个实例。思路就是,因为 App 类中的一个 RootFrame 对象,它是 PhoneApplicationFrame 类型的

,它是用来显示工程内所有页面的对象,并且控制各个页面的导航等功能的,它有一个 Template 属性,只要在

默认的框架上,加入自定义的控件,那么这个控件就可以在所有页面中显示了,相应的样式(在 App.xaml 中定义):

在 App 的构造函数中,重新设置 RootFrame 的样式,为上面定义的样式:

RootFrame.Style = App.Current.Resources["MyPhoneApplicationFrameStyle"] as Style;

 

在 App 的 InitializePhoneApplication() 方法中,注册 Navigating 事件:

RootFrame.Navigating += RootFrame_Navigating;

相应的函数:

void RootFrame_Navigating(object sender, NavigatingCancelEventArgs e)        {            // 如果自定义弹出框在显示,则隐藏它,并且取消导航            if (MyDialog.DialogIsOpen && e.NavigationMode == NavigationMode.Back)            {                e.Cancel = true;            }        }

 

 

在页面中调用弹出框的方法:

private async void Button_Click_OkAndCancel(object sender, RoutedEventArgs e)        {            if (MessageBoxResult.OK == await MyDialog.Show("Hello 北京天安门", "提示", MessageBoxButton.OKCancel))            {                txtTile.Text = "点击了OK";            }            else            {                txtTile.Text = "点击了Cancle";            }        }

显示结果:

 

当用户在 MainPage 页面,点击 Back 物理按键时,因为此时不会触发 RootFrame.Navigating 的导航事件,所以

需要在 MainPage 中判断一下是否有其它的弹出框,判断如果没有其它的弹出框,则弹出询问用户

是否关闭当前应用的弹出框:

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);        }

显示效果:

因为本工程中自定义弹出框和 自定义Toast 通知都为系统级别的,所以所有的页面共享这个

单一实例。如果页面只有在推出时,询问用户 “是否退出应用” 则只需要参考自定义控件,把它

简化后,添加到 MainPage 中使用即可,不需要放到 PhoneApplicationFrame 的 Template

属性中。

 

2) 自定义一个 Toast 通知,目的是增加对消息样式的控制,并且可以增加消息弹出的动画等。

      自定义的 Toast 显示框已经在 上面的 MyDialog.xaml 文件中定义了,下面定义 C# 页面:

#region 自定义 Toast 消息框        const string myToast = @" 
"; // 把上面动画字符串转换成相应的 XAML 动画对象 Storyboard StoryBoardToast = System.Windows.Markup.XamlReader.Load(myToast) as Storyboard; // 显示自定义 Toast 消息 public static void ShowToastMessage(string message) { Instance.StoryBoardToast.Stop(); Instance.txtToast.Text = message; foreach (var t in Instance.StoryBoardToast.Children) Storyboard.SetTarget(t, Instance.borderToast); Instance.StoryBoardToast.Begin(); } #endregion

在任何一个 Page 页面中调用:

private void Button_Click_Toast(object sender, RoutedEventArgs e)        {            MyDialog.ShowToastMessage("收到 10 条新消息");        }

 

则,显示结果:

 

 

 

转载于:https://www.cnblogs.com/hebeiDGL/archive/2013/05/26/3099861.html

你可能感兴趣的文章
django request bug
查看>>
二叉树_非递归先中后序_递归非递归求深度
查看>>
20181227 新的目标
查看>>
HDFS写流程
查看>>
生产环境服务器环境搭建+ 项目发布
查看>>
js按条件分类json数组,并合计同组数据(一维转换为二维)
查看>>
Exp6 信息搜集与漏洞扫描
查看>>
redis4安装
查看>>
使用命令wsimport构建WebService客户端[转]
查看>>
第八遍:链接详解
查看>>
Qt5.5 使用smtp发邮件的各种坑
查看>>
js奇葩错误 字符串传递问题
查看>>
人之初,性本恶
查看>>
springboot 端口号
查看>>
使用AChartEngine画动态曲线图
查看>>
安卓项目五子棋代码详解(四)
查看>>
urllib 学习一
查看>>
bzoj4196 [Noi2015]软件包管理器——树链剖分
查看>>
kafka源码阅读环境搭建
查看>>
UI设计
查看>>