65.9K
CodeProject 正在变化。 阅读更多。
Home

.NET 3.0 WPF 工具与示例

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.65/5 (68投票s)

2006年12月15日

CPOL

21分钟阅读

viewsIcon

462038

downloadIcon

11649

一篇展示如何实现一些常见 XAML 概念的文章。

引言

eXtensible Application Markup Language(XAML,发音为 ZAMMEL)即将到来,你最好相信这一点。对于那些还没听说过 XAML 的人来说,它是微软新表示层 Windows Presentation Foundation(WPF,代号 Avalon)的编码方式。

XAML 是一种 XML 风格的标记语言;XAML 标记负责图形元素的呈现,与 HTML 标记非常相似。

XAML 代码可以使用多种工具进行开发,例如 Zam3D、.NET Framework 3.0 SDK 附带的 XAMLPad、Visual Studio 2005,以及新的 Expression Blend(前身为 Expression Interactive Designer)。

XAML 背后的主要理念之一(至少我是这么认为的)是,图形前端可以由具有艺术天赋的人开发,然后交给开发人员,开发人员可以导入这些艺术性代码(即 XAML),然后编写后端 .NET 代码来驱动界面。图形设计师和软件开发人员都应该能够使用同一种语言——XAML,自由地传递工作成果。

不管怎样,这只是个基本理念,但这并不是我想在本文中要传达的。在本文中,我想展示一些在 XAML 中可以实现的概念,以及可以用来创建 XAML 的工具有哪些,还有这些工具如何使用。我还会解释我是如何实现演示应用程序的所有不同元素的。

我不会讨论如何手写 XAML,我将纯粹专注于一些最流行(至少我认为是)的 XAML 创作工具。

如果你真的分不清 XAML 和骆驼(camel),我建议你看看 Marc Clifton 在 XAML 资源 上的文章,它应该能让你快速入门。

好了,让我们分解一下本文将涵盖的内容:

  1. Cider
  2. 简要讨论 CIDER Visual Studio 插件,它让 VS 用户能够像处理 .NET 2.0 项目一样,通过从工具箱拖放来创建 XAML 设计。

  3. Expression Blend(前身为 Expression Interactive Designer,代号 Sparkle)
  4. 简要介绍 Expression Blend 的界面。

  5. 使用 Expression Blend 创建演示应用程序(见附件)。
  6. 剖析演示应用程序,以及它如何与 Blend 配合使用。

  7. Visual Studio 2005 集成
  8. 将项目从 Blend(EID, Sparkle)导入 Visual Studio 2005。这些应该足够我们开始了,那么让我们继续前进吧。

  9. 代码
  10. 是的,技术部分,也就是代码部分。

文章代码说明

我大约两天前才开始认真研究 XAML(在此之前,我只是粗略地看了一眼,并没有深入)。

对于本文,我决定尝试使用现有的工具来创建一个应用程序;毕竟,XAML 现在已经可以由工具生成,那为什么不使用它们呢?我并不是说我们都不需要了解 XAML;我们会的,这是必然的,但在我坐下来阅读我的那本 Charles Petzold 的书《应用程序 = 代码 + 标记》(共 1002 页)之前,我只是想看看我能用这些工具实现什么,因为这很可能是大多数人在日常工作中会使用的方式。

所以,这篇文章可以看作是一个人进入未知领域的旅程。我对最终产品非常满意。事实上,我将简要描述我所设法实现的功能。那么,附件中的应用程序做了什么呢?嗯,它展示了以下 XAML 概念:

附加应用程序功能

  • 按钮控件的自定义模板
  • 滑块控件的自定义模板
  • 滑块与文本框之间的数据绑定
  • 文本框的 Alpha 透明度效果
  • 鼠标悬停时按钮的动画
  • 鼠标悬停时文本的动画
  • 播放用户选择的多媒体

我会让你偷偷看一眼应用程序运行时的样子,尽管从静态截图中不太能明显看出哪些是动画效果,哪些不是。稍后,我会更详细地描述每个应用程序功能点,并在需要时附上截图。

这可能对某些人来说看起来不太 впечатляюще,但我保证这里有很多很酷的东西;你需要亲自玩一下真正的应用程序才能看到动画效果以及它们是如何结合在一起的。你稍后可以下载这个应用;现在,让我们继续阅读,看看一些 XAML 的乐趣吧。

必备组件

在您继续阅读之前,如果您想运行附加的应用程序,您应确保至少拥有以下项目:

  • Microsoft .NET Framework 3.0
  • Visual Studio 2005
  • 一台配置高、内存充足的电脑(是的,很多,1GB 以上;我的有 1GB,也只是勉强够用)

如果您想看看 Cider,可以选择性地安装它,可在“Cider” - 适用于 WPF(“Avalon”)的 Visual Studio 设计器处获取。

1. Cider

我决定从简要介绍 Cider 开始本文的讨论,它是一个用于创建 WPF 应用程序的 Visual Studio 插件。我希望通过先介绍 Cider,能让您慢慢进入 WPF 的世界,并有足够的热情继续阅读本文其他更有趣的部分。

好了,一旦你安装了所有必需的软件,并且也安装了 Cider,你就可以在 Visual Studio 中选择创建一个新的 WPF 应用程序了。让我们来看看吧?

我们可以看到,启动 Visual Studio 时的项目选项之一现在是 WPF 项目,如下图所示:

如果我选择接受这个选项,我们将继续创建一个 WPF 应用程序。

我们可以看到,Visual Studio 加载后,在常规界面中出现了一些新的选项卡;我们现在有了一个 Design/XAML 选项卡,如下所示。

这个选项卡允许我们查看 XAML 代码或 GUI 设计(这里可能说的是显而易见的事,但就是这样)。

让我们来看看创建一个新的 WPF 应用程序为我们生成的样板代码。

Visual Studio / Cider 免费为我们提供了以下 XAML,名为 Window1.XAML

所以,这是描述用户界面的 XAML 标记,但难道不应该在某个地方有一些我们能看懂的代码吗?嗯,是的,有的,它是一个 .NET 代码文件(在我的例子中是 C#)。

它看起来像下面的代码片段 (Window1.XAML.cs)

这现在看起来不那么吓人了吧?事实上,任何做过 ASP.NET 的人都应该对代码隐藏文件(code-behind file)的概念相当熟悉。这非常相似,不是吗?基本上,所有的表示层组件及其标记都在一个文件(.XAML)中,而执行逻辑的代码在另一个代码文件(.XAML.CS,或者如果你使用 VB.NET 的话就是 .XAML.VB)中。

所以下一步就是实际向页面添加一些组件。我们该怎么做呢?

只要我们选择了“设计”选项卡,工具箱就会包含许多控件,这些控件都可以拖到窗体的工作区(我注意到有些人也称之为画板区域)。

这个例子显示我放置了一个 WrapPanel,当放置时,它会被创建成这样:

开始和结束元素都在同一行。这没什么用,因为 WrapPanel 是一个容器;那么我们如何让它包含其他控件呢?嗯,我选择了 XAML 标签(这会清空工具箱里的控件;担心,在设计标签视图下它们会回来的),然后把 WrapPanel 元素拆分开,让它的开始和结束部分在不同行。然后我把鼠标移到 WrapPanel 元素的开始和结束部分之间,切换到设计标签视图,并从工具箱里拖拽了一些控件(按钮)到 WrapPanel 里。瞧,WrapPanel 就包含了这些按钮,并且正确地将它们包裹起来了。

值得注意的是,使用 Cider 还允许我们像在 .NET 2.0 应用程序中一样,通过属性窗口点击控件并更改其属性。但请注意,这些属性并不相同,有些类甚至也不同;例如,MessageBox 现在需要新的参数,并返回一个新的 MessageBoxResult 对象。所以要小心这一点。

这显然是一个有点刻意设计的例子;其目的是对 Cider 做一个简要的介绍。你需要自己去尝试这些东西;这里只是告诉你,你可以在一个舒适、安全、熟悉的环境里做这些事情,也就是 Visual Studio(啊,我们的朋友)。

你是否仍然觉得勇敢,想要了解更多 XAML 概念,并想知道如何使用其他可用的 XAML 资源?那么,请继续阅读。

2. Expression Blend

不久前,我下载了 Expression Interactive Designer(代号 Sparkle,又名 Flash 杀手)的七月 CTP 版。该产品现已作为 BETA 版发布,新名称为 Expression Blend。

在我看来,Expression Blend 将是构建创意 XAML 项目的核心工具。Blend 赋能(不,微软没有付钱让我写这个)图形设计师和程序员共享同一种语言,有谁能猜到这可能是什么吗?你说骆驼(Camle),不,不完全是。是 XAML。

使用 Blend,图形设计师可以施展他们的魔法,然后将整个项目交给开发人员,开发人员可以接着为应用程序添加 .NET 代码,例如查询数据库、访问 Web 服务等。

当然,如果你自认为是一个有点艺术细胞的开发者,你也可以深入研究 Blend;我觉得它很有趣。我只用了两天,就觉得它相当容易上手。除了一个例外,就是绑定到外部 XML 数据源,这在静态视图中 100% 正常,但在运行时无法渲染。唉。不过没关系,除了那一点小抱怨,我认为一切都进展顺利。

这一部分将讨论 Blend 的基本布局(我最初发表这篇文章时使用的是 Expression Interactive Designer 七月 CTP 版的截图,有些人不喜欢,因为 Blend 提供了 30 天的免费下载试用,所以我为这些人以及新读者更新了文章的这一部分)。

那么,我们开始吧?

Blend 看起来是什么样子的?嗯,当你启动它时,它会像下图这样。微软似乎在遵循新的 Office 2007 的理念,即调色板是按类别组织的;例如,要改变某个东西的外观,我们会使用“外观”面板。而在普通的 Visual Studio 2005(.NET 2.0 项目)中,我们只是有一个包含所有属性的列表,然后找到我们想要的那个并进行修改。

可以看到,环境中包含了几个工作区和众多的面板;让我们简要讨论一下这些:

画板

这是主要区域,设计将在这里显示;你可以从“库”面板将 .NET 控件拖放到这个界面上,或者你可以使用 XAML 选项卡手动添加控件。

对象和时间线面板

记住 XAML 是一种 XML 类型的语言,它可以被看作是一棵树。这个面板显示了文档的层次结构,并允许通过双击文档树中的元素名称来快速导航到文档元素。在这个面板中,我们还可以使用时间线来创建动画。稍后会详细介绍。

工具面板

这个面板仅仅允许用户进行抓取、缩放、绘制、填充等操作。

项目面板

此面板仅显示所有项目文件和引用等。

库面板

此面板显示所有 .NET Framework 3.0 控件,可将其拖到工作区。通过点击工具面板底部的向下箭头即可使用。

画笔面板

此面板允许更改颜色和画笔类型/样式等。

外观面板

此面板允许更改所选项目的外观。

数据面板

此面板允许向项目添加外部数据源,例如 XML 数据源,或标准的 CLR 数据源,如 DataSet 等。一旦这些数据源被添加到项目中,它们就可以用于数据绑定。

布局面板

此面板允许对所选项目应用布局更改,例如大小边距,如上图所示。

通用属性面板

此面板允许修改诸如工具提示、启用状态、光标等项目。

文本面板

此面板允许更改所选文本的文本属性。

变换面板

此面板允许对当前对象进行操作。它提供缩放、旋转、倾斜、翻转等功能。

时间线触发器面板

这个面板允许我们根据一个触发器来控制一个时间线。这可能是我最喜欢的面板之一,因为它允许我们触发动画。稍后会详细介绍。

以上就是对基本面板的介绍。希望这对您来说是 Blend 的一个温和的入门。

是啊,太棒了,伙计,但我们怎么用它来做点有用的事呢,我听到你这么说。

在下一小节中,我将附上演示应用程序的截图,并讨论每个部分是如何实现的,最后,我将同时包含 XAML(由 Expression Blend 生成)和在 Visual Studio 2005 中修改过的 .XAML.cs C# 代码隐藏文件。

3. 使用 Expression Blend 创建演示应用程序(见附件)

回顾一下,在引言中我曾提到,所附演示应用程序的功能如下:

  • 按钮控件的自定义模板
  • 滑块控件的自定义模板
  • 滑块与文本框之间的数据绑定
  • 文本框的 Alpha 透明度效果
  • 鼠标悬停时按钮的动画
  • 鼠标悬停时文本的动画
  • 播放用户选择的多媒体

那么我是怎么做到的呢?让我们逐一来看。

按钮控件的自定义模板

XAML 的一个很棒的功能是能够有效地为任何标准的 .NET 3.0 Framework 控件更换皮肤。如果你不喜欢它在库里的样子,只需更改它的模板即可。演示应用程序正是这样做的。让我们来看看。

在这个例子中,我只是在工作区上放置了一个 .NET 3.0 Framework 的 Button 控件。然后我选择“编辑模板副本”。

这会导致为我们正在编辑的按钮模板显示一个新的层次结构树。

这个层级树实际上显示了构成默认按钮渲染(即它从工具箱(库面板)中出来时的样子)的对象。要改变我们想要的按钮外观,我们只需改变按钮模板树中包含的对象。这很容易实现;我们可以简单地清除当前的模板对象,或者重新设置已有的对象样式。

我选择了全新的对象。那我们来看看吧?

可以看到,我实际上引入了一个 Grid 对象,它有两个子元素:

  • 一个 ContentPresenter 对象,用于显示按钮的内容(这可以是文本、图片、视频等)。
  • 一个 Rectangle 对象,其应用了平滑的角来创建圆角按钮。

还可以看到有几种按钮状态,每种状态都可以对新按钮的模板对象产生不同的效果。例如,在 IsMouseOver 状态下,我可以设置一个蓝色背景,而在 IsPressed 状态下,我可以设置一个黄色背景。可以使用“对象和时间线”面板中的“添加属性触发器”按钮来添加新的状态。从那里,您需要选择哪个属性应该触发该触发器。有一个列表可供选择,如下所示。

我们来看一个例子。假设我们想在宽度等于 15 时创建一个触发器。那么,我们使用“添加属性触发器”按钮,找到宽度属性,然后在可用的框中输入 15。

从那里,你可以以任何你认为合适的方式变换所选对象。

所有这些折腾的结果是,我们现在有了一个如下图所示的按钮。它实际上是一个标准的 .NET Framework 按钮,但它只是看起来像我们想要的样子。这就是模板的意义所在。

在这种情况下,图像映射到按钮模板内的 ContentPresenter 对象,而曲线框是按钮模板内平滑的 Rectangle

滑块控件的自定义模板

这与按钮模板化的做法完全相同;新的滑块渲染如下所示:

滑块和文本框之间的数据绑定

.NET 3.0 / XAML 的一个很棒的功能是,你可以将一个控件的值绑定到另一个控件的属性上。在附加的演示应用程序中,我将滑块的值绑定到了一个文本框的字体大小。让我们看看如何做到这一点。

在附加的项目中,我将一个文本框的字体大小绑定到了一个滑块的值。所以要了解这是如何完成的,我们首先需要选中该文本框,然后找到包含 Fontsize 属性的面板(它在文本面板中)。然后我们右键点击字体大小,让数据绑定菜单出现。

选择数据绑定会加载一个界面,允许我们选择绑定提供程序及其字段。

就是这样;现在每当滑块的值改变时,文本框的字体大小也会改变。看这个实际效果:

文本框上的 Alpha 透明度效果

这其实不是关于文本框,而是关于 Alpha 透明度。我只是用一个 TextBox 是因为它很容易实现。要做到这一点,我们只需使用外观面板来改变不透明度值;100% 是完全可见,0% 是完全不可见。

这被用来在演示应用程序上产生这些漂亮的效果。

你可以看到“Welcome.wmv”的文字是半透明的,这很不错。

鼠标悬停时按钮的动画效果

啊,现在说到动画了,我相当喜欢。要做到这一点,我们需要考虑几件事:时间线、变换和时间线属性。

首先,让我从概念层面告诉你动画是什么以及它们是如何工作的。

动画可以是移动、调整大小、改变颜色、旋转等对一个对象进行的操作;这些变化随时间发生,并且需要被告知何时以及如何开始动画过程。

我们来进一步看看这个。

  1. 要在时间上创建一个动画序列,我们需要创建一个时间线
  2. 要改变对象(在这种情况下是按钮),我们需要以某种方式对其进行变换
  3. 要启动一个动画,我们需要以某种方式触发它

那么,在 Blend 中我们该如何做到这一点呢?

首先,我们创建一个新的时间线;例如,我为 Button 对象“btnPlay”创建了一个名为“tlBtnPlay”的新时间线,如下所示。我们所做的是使用“创建新时间线”按钮。你是否也看到高亮的时间线被标记为“tlBtnPlay”?这让我们知道我们正在编辑哪个时间线。

可以看到,这包含了 0-4 帧。第 2 帧和第 4 帧上有一些奇怪的点。这些被称为关键帧。在我的例子中,在第 2 帧,我垂直翻转了按钮对象(我使用变换面板进行了这个翻转操作)。

这意味着每当动画运行时,当它到达第 2 帧时,按钮对象就会被翻转。这都很酷。但我们如何触发动画呢?

嗯,我们使用“触发器”面板,并使用提供的按钮创建一个新的“事件触发器”。然后,我们可以选择控件的属性,比如 mouseDown 等。

这样就创建了一个触发器,但是我们如何让这个触发器运行某个动画(基本上是一个时间线)呢?嗯,我们使用“添加新值”按钮。

从这里,我们可以使用下拉列表来选择要播放的时间线(第一个下拉列表),以及它的状态(第二个下拉列表),其中状态是以下之一:BeginStopPauseSkipToFillResumeRemove。我使用了 Begin,来表示当触发器被引发时动画应该开始。

因此在运行时,如果我将鼠标悬停在按钮上,我们就会看到动画发生,如下所示。

可以看到显示了一个工具提示。这是因为它仍然只是一个 .NET 3.0 的 Button 控件,但它通过自定义模板进行了重新设计,并应用了动画。这不是很酷吗?我认为是。

鼠标悬停时文本的动画

我还对演示应用右下角的一些文本使用了一些动画(以完全相同的方式完成)。

播放用户选择的多媒体

在演示应用程序中,用户可以选择一些多媒体来播放,只要它是一个文件,我就让他们播放,如果文件不是太大,媒体就会被播放。这一切都是在一个按钮的点击事件中实现的。这在 Expression Interactive Designer 中曾是小菜一碟,但我无法在 Expression Blend 中找到这种连接控件事件的方法。

以前有一个事件面板(在 Expression Interactive Designer 中,我用它来创建这篇文章的初稿)可以将控件的事件绑定到一个方法名上。嗯,也许我遗漏了什么,但现在,我们还是继续看看如何处理多媒体项目吧。如果我找到了,或者有人告诉我关于事件的问题,我会再次修改这篇文章。

然后,要完成多媒体的工作,只需要 6 行代码。嗯,真简洁。

实现这个功能的代码基本上如下:

player = new MediaPlayer();
player.Open(new Uri(@mediaItem, UriKind.Relative));
VideoDrawing aVideoDrawing = new VideoDrawing();
aVideoDrawing.Rect = new Rect(60,60,imgMM.Height,imgMM.Width);
aVideoDrawing.Player = player;
player.Play();

4. Visual Studio 2005 集成

在 Visual Studio 中获得 C# 项目后,我添加了代码隐藏逻辑。虽然 Expression Blend 确实有一个代码编辑窗格,但它远不如在 Visual Studio 中使用起来反应灵敏/好用。我确实尝试过在 Expression Blend 中进行代码编辑,但没有找到调试的方法,而在 Visual Studio 中,我们知道可以简单地设置一个断点,然后像往常一样调试项目。

在 Expression Blend 中发生的另一件有趣的事情是,我想引用一些 .NET 2.0 的 DLL,但它不喜欢。我想这也很公平,因为 Expression Blend 主要是为 .NET 3.0 框架设计的。然而,这确实让我感到沮丧,因为我想在 Blend 中尝试一些想法,但由于它不允许我引用相关的 DLL,所以无法实现。正如我之前提到的,我使用的是 Blend 的一个 CTP 版本(之前叫做 Expression Interactive Designer),所以也许在 BETA/最终版本中这一切都已经改变了。

但愿如此。

5. 代码

好的,那么让我们看看所附演示应用程序的所有代码。

Scene1.Xaml

老实说,把所有的 XAML 代码都放上来根本不值得,因为它有成百上千行。查看它的最佳地方是在演示应用程序本身里面。

Scene1.Xaml.cs

using System;
using System.IO;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Navigation;
using System.Windows.Media.Imaging;
using System.Windows.Forms;


namespace XAML_MMedia
{
    public partial class Scene1
    {
        String mediaItem ="";
        String mediaItemShortName = "";
        String imgLogo="";
        String mediaType="";
        mediaChecker mc = new mediaChecker();
        double oldHeight = 0;
        double oldWidth = 0;
        bool fetchHeights = false;
        MediaPlayer player;

        public Scene1()
        {
            this.InitializeComponent();
        }

        private void getNewMediaItem(object sender, 
                System.Windows.RoutedEventArgs e)
        {
            try {
                System.Windows.Forms.OpenFileDialog ofd = 
                       new  System.Windows.Forms.OpenFileDialog();
                if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                {
                    if (!ofd.FileName.Equals(String.Empty)) {
                        FileInfo fi = new FileInfo(ofd.FileName);
                        mediaChecker.selFileType fileType = 
                                mc.getFileType(fi.Extension);
                        if (!fileType.Equals(
                             mediaChecker.selFileType.Neither))
                        {
                            double fSize = (double)fi.Length / 1024;
                            if (fSize < 10000)
                            {
                                mediaType = fileType.ToString();
                                if (fileType.Equals(
                                    mediaChecker.selFileType.Audio))
                                {
                                    imgLogo = "musicLogo.png";
                                }
                                else
                                {
                                    imgLogo = "videoLogo.png";
                                }
                                mediaItem = fi.FullName;
                                mediaItemShortName = fi.Name;
                            }
                            else
                            {
                                System.Windows.MessageBox.Show("The file" + 
                                    " you picked is too large\r\n" + 
                                    "The limit is 10 MBytes", "Error",
                                    System.Windows.MessageBoxButton.OK,
                                    System.Windows.MessageBoxImage.Error);
                            }
                        }
                        else
                        {
                            System.Windows.MessageBox.Show("You pick " + 
                                "an unsupported file", "Error", 
                                System.Windows.MessageBoxButton.OK,
                                System.Windows.MessageBoxImage.Error);
                        }
                    }
                    else {
                        System.Windows.MessageBox.Show("You need to" + 
                            " select a file", "Error", 
                            System.Windows.MessageBoxButton.OK, 
                            System.Windows.MessageBoxImage.Error);
                    }
                }
                else
                {
                    System.Windows.MessageBox.Show("You need to" + 
                        " select a file", "Error", 
                        System.Windows.MessageBoxButton.OK, 
                        System.Windows.MessageBoxImage.Error);
                }
            }
            catch (Exception ex) {
                System.Windows.MessageBox.Show(ex.Message, 
                   "An error occurred", 
                   System.Windows.MessageBoxButton.OK, 
                   System.Windows.MessageBoxImage.Error);
            }
        }


        private void playMedia(object sender, 
                System.Windows.RoutedEventArgs e)
        {
            try {
                if (mediaItem.Equals(String.Empty)) {
                    return;
                }
                else {
                    player = new MediaPlayer();
                    player.Open(new Uri(@mediaItem, UriKind.Relative));
                    VideoDrawing aVideoDrawing = new VideoDrawing();
                    aVideoDrawing.Rect = new Rect(60,60, 
                                  imgMM.Height,imgMM.Width);
                    aVideoDrawing.Player = player;
                    player.Play();
                    // create a drawing image to host the VideoDrawing
                    DrawingImage di = new DrawingImage(aVideoDrawing);
                    // freeze DrawingImage for performance
                    di.Freeze();
                    // assign DrawingImage as source of the image
                    imgMM.Source = di;
                    if (mediaType.ToLower().Equals("audio"))
                    {
                        if (!fetchHeights)
                        {
                            oldWidth = imgMM.Width;
                            oldHeight = imgMM.Height;
                            fetchHeights = true;
                            imgMM.Width = 0;
                            imgMM.Height = 0;
                        }
                    }
                    else if (mediaType.ToLower().Equals("video"))
                    {
                        if (fetchHeights)
                        {
                            imgMM.Width = oldWidth;
                            imgMM.Height = oldHeight;
                        }
                    }
                    Uri uri = new Uri(@imgLogo, UriKind.Relative);
                    BitmapImage bitmap = new BitmapImage(uri);
                    imgMediaType.Source = bitmap;
                            txtMediaType1.Text = mediaItemShortName;
                    txtMediaType2.Text = "Thats an " + mediaType + 
                                                 " media item";    
                }
            }
            catch (Exception ex) {
                 System.Windows.MessageBox.Show(ex.Message, 
                     "An error occurred", 
                     System.Windows.MessageBoxButton.OK, 
                     System.Windows.MessageBoxImage.Error);
            }
        }
    }
}

还有一个非常简单的辅助类叫做 mediaChecker,如下所示:

using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;

namespace XAML_MMedia
{
    public class mediaChecker
    {
        public enum selFileType  {  Audio,Video, Neither  }
        private List<string> allowedVideoExtensions = 
                                   new List<string>();
        private List<string> allowedAudioExtensions = 
                                   new List<string>();

        public mediaChecker()
        {
            allowedVideoExtensions.Add(".wmv");
            allowedAudioExtensions.Add(".wma");
            allowedAudioExtensions.Add(".mp3");
        }

        public selFileType getFileType(String extension)
        {
            if (allowedAudioExtensions.Contains(extension))
            {
                return selFileType.Audio;
            }
            else if (allowedVideoExtensions.Contains(extension))
            {
                return selFileType.Video;
            }
            return selFileType.Neither;

        }
    }
}

您觉得怎么样?

就是这样了。我只想请求一下,如果您喜欢这篇文章,请为它投票。

结论

现在我们已经完成了,我希望这对你有用;即使我没有向你展示如何从头开始编写 XAML,我希望我已经向你展示了如何使用一些工具,以及每个工具为我们提供了什么,并且你也学到了一些关键概念,以及你能用 XAML 实现什么。我当然觉得这很有趣,有时也令人沮丧,但总的来说,相当酷。

Bug

没有 bug,我不做 bug,我做的是“特性”,而且肯定有一个“特性”,如果有人持愤世嫉俗的态度,可能会被解读为“bug”;它如下所述:

在可下载的项目中,当用户选择并播放一个新的多媒体源时,当前选中的多媒体项目(如果有的话)也会继续播放直到完成。我尝试使用 player.stop(),但这会报错,说播放器被冻结了,无法停止一个冻结的对象。我试着研究这个问题,结果绕了一圈,有点放弃了,我不得不承认。

然而,这并不真正影响文章试图展示的内容,所以我希望大家不要对这一点过于苛刻。当然,你们可以对任何事情,甚至所有事情提出批评(如果你是那种人的话),只是不要针对这一点,因为我已经告诉过你们了,我承认这一点。

历史

  • v2.0 - 06年12月20日 - 改为使用 Expression Blend BETA 1 的截图。
  • v1.0 - 06年12月15日 - 初次发布。
© . All rights reserved.