声明

以下内容取材于 Bob Tabor 的课程《Windows Phone 8.1 Development for Absolute Beginners》,链接地址为:http://www.microsoftvirtualacademy.com/training-courses/windows-phone-8-1-development-for-absolute-beginners

前言

Universal App是一种跨平台的应用开发,目前主要面向Windows和Windows Phone设备。这里,我们会设计并完成一个Universal的Tip Calculator应用程序,该应用程序可以部署到Windows Phone手机上或者是Windows设备中。

1. 应用背景

Tip Calculator,这个应用程序的灵感来自于外出就餐,老外一般有给服务员付小费的习惯,而小费该付多少一般是根据服务员的服务质量来的。本应用程序设计的小费规则是这样的,服务一般付10%,服务较好18%,服务完美25%。

2. 项目创建

首先,我们需要创建一个应用程序,选择Templates > Visual C# > Store Apps > Universal Apps,选择Blank App (Universal Apps),命名为TipCalculatorUniversal,点击确定。

工程创建完成以后,我们查看解决方案浏览器,发现以工程名称为开头的三个项目:Windows、Windows Phone和Shared。

Windows和Windows Phone的工程在XAML布局上有所不同,原因是部分控件在不同的平台上有所差异。如果是两个平台上都能够用到的类和方法,我们可以放到Share项目中。在本应用中,把Tip.cs文件放到Shared项目中,在Windows和Windows Phone的工程中引用它。

3. Shared项目设计

我们在Shared项目中,点击右键,添加新的文件:

在对话框中,选择类,命名为Tip.cs,点击添加。

在Tip.cs文件中加入以下代码,要注意两点,首先,设置Tip类为公共的。其次,创建三个属性,BillAmount, TipAmount 和 TotalAmount

public class Tip

{

public string BillAmount { get; set; }

public string TipAmount { get; set; }

public string TotalAmount { get; set; }

}

接下来,设置构造函数,将每个属性值初始化为空字符串。

public Tip()

{

this.BillAmount = String.Empty;

this.TipAmount = String.Empty;

this.TotalAmount = String.Empty;

}

接下来,创建一个计算小费的方法:

public void CalculateTip(string originalAmount, double tipPercentage)

{

double billAmount = 0.0;

double tipAmount = 0.0;

double totalAmount = 0.0;

if (double.TryParse(originalAmount.Replace('$', ' '), out billAmount))

{

tipAmount = billAmount * tipPercentage;

totalAmount = billAmount + tipAmount;

}

this.BillAmount = String.Format("{0:C}", billAmount);

this.TipAmount = String.Format("{0:C}", tipAmount);

this.TotalAmount = String.Format("{0:C}", totalAmount);

}

在这个方法中,originalAmount和tipPercentage这两个关键的内容作为传入参数,在计算得到小费和总价以后,存入类的公共属性中。注意,我们这里使用了double.TryParse()方法,如果用户输入了非数字的值,就会返回异常。

4. Windows Phone 项目设计

现在,我们来看看Windows Phone的项目,在MainPage.xaml文件的Gird中加入以下行定义:

<Grid.RowDefinitions>

<RowDefinition Height="50" />

<RowDefinition Height="100" />

<RowDefinition Height="*" />

</Grid.RowDefinitions>

第一行和第二行分别用来显示应用程序名称和应用提示,如:

<TextBlock Margin="20, 0, 20, 0"

Grid.Row="0"

Style="{StaticResource TitleTextBlockStyle}">

Tip Calculator

</TextBlock>

<TextBlock Margin="20, 0, 20, 0"

Grid.Row="1"

Style="{StaticResource TitleTextBlockStyle}"

FontSize="48">

Enter the Bill Amount

</TextBlock>

接下来,我们在第三个行中添加一个StackPanel,占据整个剩余的空间。往StackPanel中添加控件如下:

<StackPanel Name="myStackPanel" Grid.Row="2" Margin="20, 0, 20, 0">

<TextBlock HorizontalAlignment="Left"

TextWrapping="Wrap"

Text="Bill Amount"

FontSize="24"/>

<TextBox Name="billAmountTextBox"

Text="$0.00"

TextAlignment="Right"

HorizontalAlignment="Left"

TextWrapping="Wrap"

VerticalAlignment="Top"

InputScope="Number"

Width="100"

FontSize="24"

LostFocus="amountTextBox_LostFocus"

TextChanged="billAmountTextBox_TextChanged"

GotFocus="amountTextBox_GotFocus" />

</StackPanel>

在上面的代码中,billAmountTextBox允许用户输入账单上的总价,它是计算小费的基础。接下来,添加一个TextBlock和一系列RadioButtons,可以让用户选择服务的质量,以计算小费:

<TextBlock HorizontalAlignment="Left"

TextWrapping="Wrap"

Text="Percent To Tip:"

VerticalAlignment="Top"

FontSize="24"

Margin="0,20,0,0"/>

<RadioButton Content="10% - Horrible Service"

Tag="0.1"

GroupName="percentRadio"

Click="RadioButton_Click" />

<RadioButton Content="18% - Acceptable Service"

Tag="0.18"

GroupName="percentRadio"

IsChecked="True"

Click="RadioButton_Click" />

<RadioButton Content="25% - Great Service"

Tag="0.25"

GroupName="percentRadio"

Click="RadioButton_Click" />

注意,我使用了RadioButton的Tag属性,用来表示计算小费的百分比。这样的话,我可以不使用Switch语句,而直接获取Tag属性,计算小费。0.1表示10%,0.18表示18%,0.25表示25%。

接下来,我们需要显示计算小费的结果,加入如下两个Textblock:

<TextBlock HorizontalAlignment="Left"

TextWrapping="Wrap"

Text="Amount to Tip:"

FontSize="24"

Margin="0,20,0,0" />

<TextBlock Name="amountToTipTextBlock"

HorizontalAlignment="Left"

TextWrapping="Wrap"

VerticalAlignment="Top"

Text="$0.00"

FontSize="36" />

最后,显示包含了小费和账单的总价,这个是我用信用卡付费的最后价格:

<TextBlock HorizontalAlignment="Left"

TextWrapping="Wrap"

VerticalAlignment="Top"

Text="Total Bill:"

FontSize="24"

Margin="0,20,0,0" />

<TextBlock x:Name="totalTextBlock"

HorizontalAlignment="Left"

TextWrapping="Wrap"

VerticalAlignment="Top"

Text="$0.00"

FontSize="36" />

billAmountTextBox和RadioButton控件包含了一系列我们需要处理的事件。例如,当用户点击billAmountTextBox来输入账单时,我们需要首先清空已有的内容。在用户编辑数字以后,我们需要计算小费和总价。在用户的焦点移出billAmountTextBox时,我们给数字添加必要的美元符。接着,我们通过在XAML编辑器中相应的事件上点击右键,选择go to definition,创建对应的事件处理函数。

在对应的cs文件中,创建的事件处理函数如下

在后台代码中,我们创建一个Tip类的对象,并且在MainPage的构造函数中创建这个对象的实例:

另外,我们在performCalculation()方法中,调用Tip类的CalculateTip方法计算所需要的小费和总帐单。

private void performCalculation()

{

var selectedRadio = myStackPanel.Children.OfType<RadioButton>().FirstOrDefault(r => r.IsChecked == true);

tip.CalculateTip(billAmountTextBox.Text, double.Parse(selectedRadio.Tag.ToString()));

amountToTipTextBlock.Text = tip.TipAmount;

totalTextBlock.Text = tip.TotalAmount;

}

该方法的第一行是使用了LINQ语句检查用户选择的RadioButton;这种方法的优点在于,加入一个新的RadioButton控件,我们不需要增加新的代码去完成这个判断,但如果使用Switch语句就不一样了。

在获得了用户选择的RadioButton后,就可以调用Tip类的CalculateTip方法进行计算。最后将计算所得的结果赋值给相应的控件显示就可以了。

另外,什么时候需要执行这个performCalculation函数呢?首先,当用户输入新的账单时,即在(billAmountTextBox_TextChanged)这个事件被触发时;其次是用户选择不同的小费比例时,即在(RadioButton_Click)事件被触发时。

private void billAmountTextBox_TextChanged(object sender, TextChangedEventArgs e)

{

performCalculation();

}

private void RadioButton_Click(object sender, RoutedEventArgs e)

{

performCalculation();

}

这样,我们就可以调试应用程序了。但是仍存在一些不便之处。如,当我点击Bill Amount TextBox控件输入内容时,该控件就应该自动清空上次我输入的内容,而不应该由我自己手动清除。

其次,在输入完毕内容以后,我希望在前面加上美元符。

为了实现这两个功能,我们可以通过下面的方式来做。

首先,在amount TextBox获得焦点时,我们来清空其内容:

private void amountTextBox_GotFocus(object sender, RoutedEventArgs e)

{

billAmountTextBox.Text = "";

}

现在,再一次调试程序,你会发现,点击该TextBox时,会自从清空。

第二,为了使得输入的内容后加上美元符,我在它失去焦点时,调用Tip类的CalculateTip()方法,

private void amountTextBox_LostFocus(object sender, RoutedEventArgs e)

{

billAmountTextBox.Text = tip.BillAmount;

}

其调试结果如下:

注意,默认是Windows项目作为Start Up项目,我们要把它修改成Windows Phone的项目作为启动项目,可以在Windows Phone项目上点击右键,选择"Set as Start Up Project". 这样就可以了。

5. Windows 项目设计

为了测试方便,我又重新把Windows项目设置为Start Up Project,方法和上面的一样,接下来,打开Windows项目的MainPage.xaml文件,预览如下:

下面我们来看一下,在已有的Phone的界面设计的基础上,完成Windows的项目是多么容易。那么,首先我把Phone当中的MainPage.xaml中的页面布局代码拷贝过来,可以看到如下的效果:

虽然我们的界面上还有很多的空余空间,但是大家可以发现,我们在Phone中的xaml控件,在这里同样可以使用。

除了xaml代码,后台代码同样需要修改,主要是相关的事件处理程序。注意,后台代码的处理和上面的例子完全一样。

完成以后,我们点击Simulator,开始调试。应用程序界面如下:

因此,通过这次项目的内容我们发现,在这个Universal App中,使用了完全相同的XAML页面布局代码,使用了一个Tip类。当然,如果为了美观,我们当然可以拉伸Windows版本控件,以更加适合屏幕。因此,创建应用程序时,我建议把共同的逻辑、规则、数据获取和处理等内容放在Shared项目中,然后就可以在Windows和Windows Phone程序中引用它。这样我们就可以使得应用程序在多个不同的平台上使用。

参考链接:

•Windows Phone 8.1 Development for Absolute Beginners

•作者: Bob Tabor (Microsoft MVP)

•链接: http://www.microsoftvirtualacademy.com/training-courses/windows-phone-8-1-development-for-absolute-beginners

•源代码链接:http://aka.ms/absolutebeginnerwp81

Windows Universal 应用 – Tip Calculator的更多相关文章

  1. Unity3D移植Windows Universal App(Windows 8.1 及Windows Phone 8.1)版本遇到的坑

    移植的情况以及遇到的问题: 1.选用的版本是最新的Unity5.0. 2.全屏播放视频Handheld.PlayFullScreenMoview的路径必须是全路径,并且前面要加上"ms-ap ...

  2. 【Windows Universal Platform】只是学习笔记 - 开始

    我是初学,之前没有windows/windows phone的应用开发经验:开博的目的只是记录和督促自己学习. 心血来潮也好,或是个人喜好的原因,想学着自己开发APP了(PS:以前做过web 开发) ...

  3. 课程上线 -“新手入门 : Windows Phone 8.1 开发”

    经过近1个月的准备和录制,“新手入门 : Windows Phone 8.1 开发”系列课程已经在Microsoft 虚拟学院上线,链接地址为:http://www.microsoftvirtuala ...

  4. SQLite.Net-PCLUSING SQLITE IN WINDOWS 10 UNIVERSAL APPS

    USING SQLITE IN WINDOWS 10 UNIVERSAL APPS 1.下载SQLite VSIX package并安装 http://sqlite.org/download.html ...

  5. 将Win8.1/WP8.1应用迁移到Universal Windows Platform

    在上一篇在VS2015 RC打开CTP中创建的工程,我们介绍了怎么在RC中打开CTP中创建的Universal 工程,这一篇我们来讲下怎么将Windows 8.1/WP8.1的应用迁移到Univers ...

  6. 使用 Portable Class Library(可移植类库)开发 Universal Windows App

    今天在这里跟大家聊聊关于 Windows Universal 应用夸平台的问题,首先Universal Windows App的定义相信大家已经有所了解了(如果你是一个刚刚接触 Universal A ...

  7. 如何使用 App Studio 快速定制你自己的 Universal Windows App

    之前我为大家介绍过 App Studio 这只神器可以帮助大家快速制作一个 Windows Phone 8 的应用,今天之所以在写一篇关于 App Studio 的文章是因为,App Studio 经 ...

  8. 使用 .NET 平台,如何玩转 Universal Windows 应用?

    2015年7月30日 本文作者是 Managed Languages 团队项目经理 Lucian Wischik. 不久前,Visual Studio 2015上新增 Windows 10 应用的开发 ...

  9. 怎样使用 App Studio 高速定制你自己的 Universal Windows App

    今天之所以在写一篇关于 App Studio 的文章是由于,App Studio 经过了几次升级功能得到了明显提升还能够调用系统功能了.而且能够更方便的和应用商店关联公布 Universal Wind ...

随机推荐

  1. EntityFramework 7 如何查看执行的 SQL 代码?

    EF 其他版本:EntityFramework 如何查看执行的 SQL 代码? 在 EF7 中,并没有 Context.Database.Log 属性访问方式,但改变更加强大了,我们可以使用下面方式配 ...

  2. [c++] Templates

    Template是编译时多态.所有的模板都是在编译时产生对应的代码,它没有面向对象中的虚表,无法实现动态多态. Function Template A function template is a p ...

  3. js 把数字转成2 ,8,16进制的方法

    直接上代码 <!DOCTYPE html> <html> <body> <script> var myNumber = 128; document.wr ...

  4. objective-c 语法快速过(3)

    oc 里的匿名对象 oc 这里,很少用到,因为并不适用于oc的内存管理,只是面试笔试也许出现,要求能看懂,不要在项目里这样写,因为写匿名对象,会造成内存泄露 #import <Foundatio ...

  5. 5分钟学会使用Less预编译器

    5分钟学会使用Less预编译器 Less是什么? LESS CSS是一种动态样式语言,属于CSS预处理语言的一种,它使用类似CSS的语法为CSS赋予了动态语言的特性,如变量.继承.运算.函数等,更方便 ...

  6. hibernate笔记--缓存机制之 一级缓存(session缓存)

    一级缓存: 又称为session缓存,它和session生命周期相同,周期非常短.是事务级别的缓存: 还是以Book和Category这两个表为例,我们用代码观察一个缓存的存在: 假设现在我要去查询i ...

  7. nodejs 代理 解决开发环境跨域问题

    前后端分离项目中,会遇到跨域问题.解决方法无非就是jsonp cors等. 本次项目前端不搭node服务,线上用nginx搭站点,nginx转发ajax请求server. 本地开发环境的跨域问题用no ...

  8. PHP CURL CURLOPT参数说明(curl_setopt)

    CURLOPT_RETURNTRANSFER 选项: curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); 如果成功只将结果返回,不自动输出任何内容. 如果失败返回F ...

  9. PHP获取网站图标(favicon.ico)文件

    有的网站源码中加入了这几行代码: <link rel="shortcut icon" href="/favicon.ico" type="ima ...

  10. 关于jsp的内置对象request和response的重定向和转化(待补充)

    请求重定向 1.客户端行为 2.response.sengRedirect(): 3.本质上讲,相当于请求两次 4.URL地址会改变 请求转发 1.服务器行为 2.response.getReques ...