惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Vercel News
Vercel News
Microsoft Azure Blog
Microsoft Azure Blog
Stack Overflow Blog
Stack Overflow Blog
Martin Fowler
Martin Fowler
Hacker News - Newest:
Hacker News - Newest: "LLM"
Cyberwarzone
Cyberwarzone
Recorded Future
Recorded Future
H
Hackread – Cybersecurity News, Data Breaches, AI and More
T
Threat Research - Cisco Blogs
Know Your Adversary
Know Your Adversary
Recent Announcements
Recent Announcements
L
LINUX DO - 热门话题
D
DataBreaches.Net
K
Kaspersky official blog
T
Threatpost
F
Full Disclosure
T
The Exploit Database - CXSecurity.com
C
CERT Recently Published Vulnerability Notes
S
Securelist
I
Intezer
有赞技术团队
有赞技术团队
罗磊的独立博客
爱范儿
爱范儿
S
Schneier on Security
P
Privacy & Cybersecurity Law Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Cisco Talos Blog
Cisco Talos Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
L
LangChain Blog
美团技术团队
G
Google Developers Blog
T
Tor Project blog
Project Zero
Project Zero
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
The Hacker News
The Hacker News
W
WeLiveSecurity
Engineering at Meta
Engineering at Meta
Apple Machine Learning Research
Apple Machine Learning Research
aimingoo的专栏
aimingoo的专栏
PCI Perspectives
PCI Perspectives
L
LINUX DO - 最新话题
MyScale Blog
MyScale Blog
阮一峰的网络日志
阮一峰的网络日志
酷 壳 – CoolShell
酷 壳 – CoolShell
V
V2EX
Hugging Face - Blog
Hugging Face - Blog
P
Proofpoint News Feed
Webroot Blog
Webroot Blog
T
Troy Hunt's Blog

博客园 - Allen Lee

用R处理一组数据的三种方式 遇见C++ AMP:GPU的线程模型和内存模型 遇见C++ AMP:在GPU上做并行计算 遇见C++ PPL:C++ 的并行和异步 遇见C++ Lambda WP7有约(七):实现铃声设置的播放图标的效果 WP7有约(六):AppBarUtils使用指南 WP7有约:一个应用的破蛋过程 WP7有约(五):回到主页 WP7有约(四):课程全景 WP7有约(三):课堂重点 WP7有约(二):课后作业 WP7有约(一):课程安排 Ruby 101:行为驱动 Ruby 101:动态编程 Ruby 101:方法对象 Ruby 101:对象和方法 Ruby 101:重用、隐藏和多态 - Allen Lee Ruby 101:类和对象
WP7有约(八):在ListPicker控件的选择页面上播放铃声
Allen Lee · 2011-12-10 · via 博客园 - Allen Lee

WP7有约(八):在ListPicker控件的选择页面上播放铃声

Written by Allen Lee

      上节课我们在ListPicker控件的选择页面上实现了播放图标的效果,随后sjcxyf同学又发现了新的问题:

我在项目里面添加了一个MP3文件,然后我在页面加了一个MediaElement控件,我在Image_Tap事件里面添加了播放音乐的代码,但是表现出来的结果是当选择页面弹出来之后点击播放图标不能播放音乐,我试图尝试在选择模板里面加入MediaElement控件来实现,但是最后结果还是一样。

      在Silverlight for Windows Phone里,MediaElement有一个很特别的限制,你必须把它添加到可视化树,否则它不会播放。假设我们在铃声设置页面上添加一个播放按钮,如图1所示,接着在这个按钮的Click事件处理程序里创建MediaElement对象,然后通过它播放预先添加的铃声(这个铃声文件的Build Action属性的值是Content),如代码1所示。

图 1 铃声设置页面

代码 1 通过MediaElement对象播放铃声

private void Button_Click(object sender, RoutedEventArgs e)
{
var media = new MediaElement();
media.Volume = 1;
media.Source = new Uri(“Windows Logon Sound.wav”, UriKind.Relative);
}

      运行这个应用程序,然后单击播放按钮,你会发现什么声音也没有。但如果我们在创建MediaElement对象之后把它添加到LayoutRoot里,如代码2所示,那么单击播放按钮就能听到声音了,因为此时MediaElement对象已在可视化树上了。

代码 2 把MediaElement对象添加到LayoutRoot

private void Button_Click(object sender, RoutedEventArgs e)
{
var media = new MediaElement();
LayoutRoot.Children.Add(media);
media.Volume = 1;
media.Source = new Uri("Windows Logon Sound.wav", UriKind.Relative);
}

      这正是为什么我们经常看到别人在XAML里创建MediaElement对象,然后在代码隐藏里调用它的Play方法播放音频。不过,如果你试图把代码2照搬到Image控件的Tap事件处理程序里,你会发现还是听不到声音,为什么呢?

      当我们单击ListPicker控件时,它会打开一个新的选择页面,此时,由于铃声设置页面不再可见,不用渲染,Silverlight for Windows Phone会把它从可视化树上摘除,因此,我们在Image控件的Tap事件处理程序里把MediaElement对象添加到铃声设置页面的LayoutRoot里就失去意义了。

      那么,如果我们在选择页面的项目模板里创建MediaElement对象又会怎样呢?毫无疑问,这会导致同一个页面存在多个MediaElement对象,而Silverlight for Windows Phone并不支持这种用法,因此这条路是行不通的。

      从上面的分析不难看出,MediaElement的最大问题在于它对可视化树的依赖,那么,有没有不依赖于可视化树的解决方案?有的,我们可以借用XNA的SoundEffect:

      1) 添加Microsoft.Xna.Framework库的引用,如图2所示。

图 2添加Microsoft.Xna.Framework库的引用

      2) 添加XNA命名空间的引用,如代码3所示。

代码 3 XNA命名空间

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;

      3) 把Image控件的Tap事件处理程序改为代码4所示的那样。

代码 4 通过XNA的SoundEffect播放铃声

private void Image_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
using (var stream = TitleContainer.OpenStream("Windows Logon Sound.wav"))
{
var audio = SoundEffect.FromStream(stream);
FrameworkDispatcher.Update();
audio.Play();
}

e.Handled = true;
}

      代码4所做的事情很简单,它以流的形式打开铃声文件,然后用这个流对象创建SoundEffect对象,并更新XNA的组件状态,最后播放铃声。

      一般情况下,当我们提到Windows Phone应用程序的存储区域时,很多人会第一时间想到独立存储区,不过,Windows Phone应用程序还有另外一个存储区域,这个区域就是应用程序的安装文件夹,和独立存储区不同的是,安装文件夹里面的内容是只读的。当我们在Visual Studio的属性窗口里把内容文件的Build Action属性的值设为Content时,比如前面那个铃声文件,安装程序会把它们部署到安装文件夹里。事实上,Windows Phone SDK 7.1的LINQ to SQL就通过"appdata"和"isostore"在连接字符串里区分这两种区域。

      XNA提供的TitleContainer.OpenStream方法可以用来读取安装文件夹里的内容,如果你的应用是从网上下载铃声的,那么这些铃声将会保存在独立存储区里,这意味着代码4里打开文件流的代码应该换成对应的独立存储访问代码。