许可优化
许可优化
产品
产品
解决方案
解决方案
服务支持
服务支持
关于
关于
软件库
当前位置:服务支持 >  软件文章 >  Windows 8开发初体验:C#版菜谱示例

Windows 8开发初体验:C#版菜谱示例

阅读数 8
点赞 0
article_banner

Windows 8的Release Preview版已经在2012年的儿童节正式发布了。虽然不如外界期望的那么成熟,Windows 8开始慢慢的学步了。作为开发者,我们面临的挑战要大于之前Windows的每一次升级。Windows 8对于开发者的挑战,可能仅次于当年从DOS升到Windows,别忘了,无数在DOS下非常成功的软件因为无法支持Windows而在一夜间烟消云散。

这次Windows 8的挑战主要来自于Metro UI,Metro UI是从Windows Phone衍生而来,适合移动设备多点触摸输入方式的UI Framework。而Metro UI的编程方式类似于Silverlight,结合了Windows Phone中的一些特点,但是Metro Style UI Framework却和两者都不相同。

Metro UI支持三种编程语言:.NET(C#,VB.NET)、C++和JavaScript。在这些编程语言的下面,是统一的WinRT Framework。

我们在这里就不多聊WinRT了,如果有兴趣的,可以去看微软的官方文档:

http://msdn.microsoft.com/library/windows/apps/

最近讨论C++和编程的比较多,反而是.NET编程有点冷清。所以,我在这里改写了一个例子,供大家参考。这个例子原本是JavaScript版的Contoso Cookbook,在Windows 8训练营时作为例子,应该很多人已JavaScript经拿到了。因为看不懂JavaScript,所以,我决定将其改写成C#版的。其中的图片的版权属于微软,如果有任何侵权问题,请通知我。我会进行更换。

好了,接下来,言归正传。

开发环境和创建工程

我们的开发环境是Windows 8 Release Preview和Visual Studio Ultimate 2012 RC版。如果没有Visual Studio Ultimate 2012 RC版的朋友,也可以下载Visual Studio 2012 Express RC for Windows 8版,来开发Windows 8 Metro style应用。下载地址如下:

http://msdn.microsoft.com/en-US/windows/apps/br229516.aspx

进入到Visual Studio 2012后,发现整个界面都很Metro,还能够切换黑背景和白背景,虽然图标变化较大,但是操作模式基本没有什么变化。所以,我们选择Visual C#下的Windows Metro style项目,其中包括了Grid App(XAML)选项,我们将工程名改为ContosoCookbook,点击OK。

初次创建Windows 8的应用,需要申请开发者许可。目前是免费的,不知道将来是否要收费。点击“我同意”后,输入Live ID的用户名和密码即可。

然后,我们就进入到了Visual Studio 2012的主界面。主界面变化不大,我们选择直接运行应用程序,会进入到全屏的Metro UI界面,如下图所示:

这个形式也是Metro style里使用较多的一种展现形式。好坏就不评价了,大家慢慢适应吧。

刚开始有一件郁闷的事情,不知道该怎么返回Visual Studio,在尝试了N多方法后,发现按Win键+D,可以直接返回Visual Studio。

除了本机调试外,我们还能够使用模拟器来进行调试,想必这就是Windows 8平板以后的调试方式了。在工具栏的运行按钮后边有一个下拉菜单,选择“Simulator”,点击运行,会打开一个模拟器,如图:

这个模拟器中的状态和本机是一致的,包括安装的应用程序,但我们可以使用一些附加功能,来调试平板上特有的功能,比如:旋转、定位、摄像头等。最逗的是,这个模拟器没有关闭按钮,你唯一的办法就是,在模拟器中找到关机界面,然后将其关闭。

修改应用名称和图标

接下来,我们修改应用程序的启动界面和图标。在Solution Explorer中,找到Assets目录,其中需要修改的图标文件有:Logo.png(150x150), SmallLogo.png(30x30)和StoreLogo.png(50x50),启动界面是SplashScreen.png(620x300)。右键选中Assets,选择添加已有项目“Add - Existing Item”,将准备好的图片添加进来,覆盖掉默认的图标即可。

接下来,双击Package.appxmanifest文件,打开的是一个编辑器,可以设置与应用程序相关的属性。修改其中的Display name和Description属性,

除此之外,还有很多属性可以设置,在这里就不一一介绍了。Packaging属性页里,有一个Guid的属性,估计后边还可能出现Windows Phone上几个应用用一个Guid的情况了。

修改完了Logo和显示名称之后,再次运行,可以看到新的界面。

加载数据和图片

接下来就到了重头戏,要加载数据和图片了。首先在Solution Explorer中创建两个文件夹:data和images。data文件夹中添加Recipes.txt文件,其中包括了一组Json数据,包含了世界各地的美食介绍;images文件夹中,要包含所有的图片文件,直接将图片文件拖拽进去即可。

然后,打开DataModel目录下的SampleDataSource.cs文件,在文件顶部添加引用:

using Windows.Storage; using Windows.ApplicationModel; using Windows.Data.Json;

然后在SampleDataSource类中增加一个新的方法来加载数据文件:

public static async System.Threading.Tasks.Task LoadFile() { StorageFolder folder = await Package.Current.InstalledLocation.GetFolderAsync("data"); ; StorageFile file = await folder.GetFileAsync("Recipes.txt"); string text = await FileIO.ReadTextAsync(file); }

Windows 8文件访问方式发生了很大的变化,我花了一上午时间才搞定,最后的代码却很简单。调用Package.Current.InstalledLocation属性,就可以找到程序当前运行的路径,该属性返回一个StorageFolder对象。因为Recipes.txt文件放在data目录中,所以还要调用GetFolderAsync方法,来获取data子文件夹。GetFolderAsync方法是一个异步调用方法,所以我们需要使用一个新的关键字:await来等方法调用结束返回结果。await关键字只能在异步调用的方法中被调用,所以LoadFile方法声明时,增加了async关键字,表示该方法是一个异步调用方法。关于await和async关键字,我们以后有机会详细来说。

获取了StorageFolder对象后,我们可以调用StorageFolder的GetFileAsync方法,来获取文件的StorageFile对象。然后再使用FileIO的ReadTextAsync方法,将文件读取到字符串中。

好了,与文件相关的操作就介绍到这里。接下来,我们看一下,如何分析JSON数据。

分析JSON数据

随着JSON数据格式的流行,Metro style Framework也增加了对于JSON数据的支持。我们先来看看数据大概是什么样的:

{"group":{"key":"Chinese","title":"Chinese","shortTitle":"Chinese","recipesCount":0,"description":"Lorem ipsum dolor sit amet","rank":"","backgroundImage":"images/Chinese/chinese_group_detail.png", "headerImage":"images/Chinese/chinese_group_header.png"}, "key":1000, "title":"Chinese Salad", "shortTitle" : "Chinese Salad",  "preptime":30, "favorite":false, "rating": 3 ,  "directions":"Preheat the broiler.", "backgroundImage":"images/Chinese/Chinese Salad.jpg", "ingredients":["1 head Napa or bok choy cabbage","1/4 cup sugar","1/4 teaspoon salt","3 tablespoons white vinegar","3 green onions","1 (3-ounce) package ramen noodles with seasoning pack","1 (6-ounce) package slivered almonds","1 tablespoon sesame seeds","1/2 cup vegetable oil"]},

每项数据分属不同的Group,而我们需要的Group数据有:ID、标题、子标题、描述和标题图片;数据项的数据包括:Key、标题、子标题、背景图片和菜谱。

所以,我们在LoadFile方法里增加下面的代码,代码略微有点长:

JsonArray parsedResponse = JsonArray.Parse(text); if (parsedResponse.Count > 1) { string groupid = ""; SampleDataGroup group1 = null; foreach (JsonValue value in parsedResponse) { var obj = value.GetObject(); var group = obj["group"].GetObject(); string id = group["key"].GetString(); if (id != groupid) { groupid = id; group1 = new SampleDataGroup( group["key"].GetString(), group["title"].GetString(), group["shortTitle"].GetString(), group["headerImage"].GetString(), group["description"].GetString() ); _sampleDataSource.AllGroups.Add(group1); } group1.Items.Add(new SampleDataItem( obj["key"].GetNumber().ToString(), obj["title"].GetString(), obj["shortTitle"].GetString(), obj["backgroundImage"].GetString(), obj["directions"].GetString(), ITEM_CONTENT,  group1) ); }

我们首先调用JsonArray.Parse方法来解析刚刚获取到的Json数据,返回一个JsonArray的数组对象。接下来,通过foreach来遍历JsonArray中的数据项,获取到的对象是JsonValue对象。因为获取到的数据是对象,所以,我们使用JsonValue的GetObject方法来获取一个对象,虽然代码里用的是var,实际的数据类型是JsonObject。然后用obj["group"].GetObject()方法来获取到Group信息的JsonObject,中括号中必须填写Key的名称。然后取出Group的Id值,该值是一个字符串,所以调用GetString方法来获取Id值。如果读取出的Id值与之前不同,则创建新的SampleDataGroup对象,对象中所需的数据则通过Group对象的GetString方法来获取;然后,将其添加到SampleDataSource 的AllGroups属性中。

接下来,就是创建SampleDataItem对象,这次要从obj对象里取到所需信息,如果JSON数据中是数字,则调用GetNumber方法。最后将创建好的SampleDataItem对象添加到SampleDataGroup的Items列表中。

到这里,我们关于JSON的代码就写完了。接下来,摆在我们面前的还有一个问题。

解决异步调用的问题

接下来的代码似乎顺理成章了。我们在SampleDataSource的构造函数中,将里边的示例代码全部删除,然后添加LoadFile方法,如下图:

public SampleDataSource() { LoadFile(); }

运行之后的效果却是如下:

Group的数据被加载了,但是其中的数据项未被加载。而我们点击Chinese项目时,则能够看到中国美食的情况,再退回主界面,所有的数据就能够显示出来了。这是典型的异步调用错误。原因也很简单,是因为SampleDataSource的构造函数是同步调用,不会等LoadFile结束后再返回,所以,当界面上显示数据时,显示的只是未加载完成的数据列表。

头疼的问题啊,我试了几种方案,最后采取的这种方案未必是最好的,但确实能够解决这个问题。也许大家有更好的解决方法,留一个悬疑吧。接下来,我说我的办法。

由于构造函数无法变成async调用方法,所以只能用另外的一个显式初始化函数来替代构造函数的作用,在数据显示之前,显式地调用该初始化函数。所以,我就直接将LoadFile作为这个初始化函数,为LoadFile增加public,static和async关键字。

然后,我们打开GroupItemsPage.xaml.cs文件,找到LoadState方法。该方法用来设置当前视图的数据源,所以,我们在LoadState方法的顶部显式调用SampleDataSource.LoadFile方法。当然,我们会得到一个编译错误,因为LoadState方法也是一个同步调用函数,简单地为LoadState方法增加一个async的关键字就可以解决这个问题。代码如下:

protected async override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState) { await SampleDataSource.LoadFile(); var sampleDataGroups = SampleDataSource.GetGroups((String)navigationParameter); this.DefaultViewModel["Groups"] = sampleDataGroups; }

好了,当我们终于做完这一切之后,我们就可以看到完整的用户界面了:

写在最后

看起来很简单的代码,却整整写了一天,期间试过的方法也很多,一言难尽。目前Windows 8的开发资料也比较少,我在开发过程中,找到了下面的例子“Windows 8 Release Preview Metro style app samples - C#, VB.NET, C++, JavaScript”,在其中找到很多有用的代码:

http://code.msdn.microsoft.com/windowsapps/Windows-8-Modern-Style-App-Samples

好了,这次的例子包括了数据绑定、JSON数据分析和文件读取,希望后边还有时间能够写更多的例子出来。


免责声明:本文系网络转载或改编,未找到原创作者,版权归原作者所有。如涉及版权,请联系删

相关文章
技术文档
QR Code
微信扫一扫,欢迎咨询~
customer

online

联系我们
武汉格发信息技术有限公司
湖北省武汉市经开区科技园西路6号103孵化器
电话:155-2731-8020 座机:027-59821821
邮件:tanzw@gofarlic.com
Copyright © 2023 Gofarsoft Co.,Ltd. 保留所有权利
遇到许可问题?该如何解决!?
评估许可证实际采购量? 
不清楚软件许可证使用数据? 
收到软件厂商律师函!?  
想要少购买点许可证,节省费用? 
收到软件厂商侵权通告!?  
有正版license,但许可证不够用,需要新购? 
联系方式 board-phone 155-2731-8020
close1
预留信息,一起解决您的问题
* 姓名:
* 手机:

* 公司名称:

姓名不为空

姓名不为空

姓名不为空
手机不正确

手机不正确

手机不正确
公司不为空

公司不为空

公司不为空