Windows Universal 应用 – Tip Calculator
声明
以下内容取材于 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://aka.ms/absolutebeginnerwp81
Windows Universal 应用 – Tip Calculator的更多相关文章
- Unity3D移植Windows Universal App(Windows 8.1 及Windows Phone 8.1)版本遇到的坑
移植的情况以及遇到的问题: 1.选用的版本是最新的Unity5.0. 2.全屏播放视频Handheld.PlayFullScreenMoview的路径必须是全路径,并且前面要加上"ms-ap ...
- 【Windows Universal Platform】只是学习笔记 - 开始
我是初学,之前没有windows/windows phone的应用开发经验:开博的目的只是记录和督促自己学习. 心血来潮也好,或是个人喜好的原因,想学着自己开发APP了(PS:以前做过web 开发) ...
- 课程上线 -“新手入门 : Windows Phone 8.1 开发”
经过近1个月的准备和录制,“新手入门 : Windows Phone 8.1 开发”系列课程已经在Microsoft 虚拟学院上线,链接地址为:http://www.microsoftvirtuala ...
- 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 ...
- 将Win8.1/WP8.1应用迁移到Universal Windows Platform
在上一篇在VS2015 RC打开CTP中创建的工程,我们介绍了怎么在RC中打开CTP中创建的Universal 工程,这一篇我们来讲下怎么将Windows 8.1/WP8.1的应用迁移到Univers ...
- 使用 Portable Class Library(可移植类库)开发 Universal Windows App
今天在这里跟大家聊聊关于 Windows Universal 应用夸平台的问题,首先Universal Windows App的定义相信大家已经有所了解了(如果你是一个刚刚接触 Universal A ...
- 如何使用 App Studio 快速定制你自己的 Universal Windows App
之前我为大家介绍过 App Studio 这只神器可以帮助大家快速制作一个 Windows Phone 8 的应用,今天之所以在写一篇关于 App Studio 的文章是因为,App Studio 经 ...
- 使用 .NET 平台,如何玩转 Universal Windows 应用?
2015年7月30日 本文作者是 Managed Languages 团队项目经理 Lucian Wischik. 不久前,Visual Studio 2015上新增 Windows 10 应用的开发 ...
- 怎样使用 App Studio 高速定制你自己的 Universal Windows App
今天之所以在写一篇关于 App Studio 的文章是由于,App Studio 经过了几次升级功能得到了明显提升还能够调用系统功能了.而且能够更方便的和应用商店关联公布 Universal Wind ...
随机推荐
- 如何搭建NTP服务
最近,在搭建Oracle RAC过程中,需要用到DNS和NTP,其中,DNS用于域名.IP管理,NTP用于时间同步.其实,很久以前搭建过这两种服务,但技术,本质上,符合“用进废退”的客观规律.用得越频 ...
- Spring对事务管理的支持的发展历程--转
原文地址:http://www.iteye.com/topic/1123049 1.问题 Connection conn = DataSourceUtils.getConnection(); //开启 ...
- EasyUI管理后台模板(附源码)
下载地址:http://files.cnblogs.com/wyguo/easyui_demo.zip
- js的并行加载以及顺序执行
重新温习了下这段内容,发现各个浏览器的兼容性真的是搞大了头,处理起来很是麻烦. 现在现总结下并行加载多个js的方法: 1,对于动态createElement('script')的方式,对所有浏览器都是 ...
- Myeclipse中导入项目后java类中汉字注释出现乱码问题(已解决)
今天重装系统,安装了新的Myeclipse后,导入之前的项目后,,出现了乱码问题.乱码问题主要是java类中的注释,而jsp页面中汉字却完好如初: 右键项目,查看项目的编码格式,UTF-8,把java ...
- 原创:微信小程序源码解说:石头剪刀布(附源码下载)
我的博客:来源链接 昨天看有个石头剪刀布的练习,就拿出来做了一下,布局的代码浪费了很多时间,果然CSS这块的还不是很熟练,下面直接上图上代码了. JS: var numAi = 0 var timer ...
- JS函数相关及递归函数的使用
JS函数相关及递归函数的使用 通用js程序: function 函数名(参数列表) { 函数体 } 可使用alert()输出,也可用return返回值. alert与return区别: functio ...
- PHP实现新浪长链接转化成短链接API
我们经常收到类似于这样的短信(如下图),发现其中的链接并不是常规的网址链接,而是个短小精悍的短链接,产品中经常需要这样的需求,如果在给用户下发的短信中是一个很长的连接,用户体验肯定很差,因此我们需要实 ...
- 理解领域模型Domain Model
定义 业务对象模型(也叫领域模型 domain model)是描述业务用例实现的对象模型.它是对业务角色和业务实体之间应该如何联系和协作以执行业务的一种抽象.业务对象模型从业务角色内部的观点定义了业务 ...
- git学习之branch分支
作为新手,站在我的角度肤浅的来理解,分支就是相当于开辟了一个新的临时工作区,在这个工作区进行文件代码改动,然后在合并到master主工作区,这样能保证主工作区的安全性和稳定性,对于团队协作尤为重要. ...