Windows Phone 7的编程平台包括Silverlight和XNA两种
标准Silverlight工程中包括了App.xaml和MainPage.xaml两个文件。xaml用于描述UI,使业务逻辑和界面管理想隔离。App表示整个应用程序,MainPage是其中的一个页面。
方向处理:Silverlight中的SupportedOrientations控制,可以取Portraint、Landscape或PortraintOrLandscape。
SupportedOrientations="PortraitOrLandscape" Orientation="Portrait"
方向事件:Silverlight通过重载OnOrientationChanged实现。
protected override void OnOrientationChanged(OrientationChangedEventArgs args)
{
txtblk.Text = args.Orientation.ToString();
base.OnOrientationChanged(args);
}
时钟:Silverlight的DispatcherTimer类,定期触发Tick事件。
public MainPage()
{
InitializeComponent();
DispatcherTimer tmr = new DispatcherTimer();
tmr.Interval = TimeSpan.FromSeconds(1);
tmr.Tick += OnTimerTick;
tmr.Start();
}
触摸控制:XNA通过TouchPanel.GetState()获取触摸点的集合
TouchCollection touchLocations = TouchPanel.GetState();
foreach (TouchLocation touchLocation in touchLocations)
{
if (touchLocation.State == TouchLocationState.Pressed)
{}
}
XNA识别出手势
while (TouchPanel.IsGestureAvailable)
{
GestureSample gestureSample = TouchPanel.ReadGesture();
if (gestureSample.GestureType == GestureType.Tap)
{
}
}
Silverlight通过Touch.FrameReported事件,通过DirectlyOver确定用户正在触摸的元素。
Touch.FrameReported += OnTouchFrameReported;
void OnTouchFrameReported(object sender, TouchFrameEventArgs args)
{
TouchPoint primaryTouchPoint = args.GetPrimaryTouchPoint(null);
if (primaryTouchPoint != null && primaryTouchPoint.Action == TouchAction.Down)
{
if (primaryTouchPoint.TouchDevice.DirectlyOver == txtblk)
{
}
}
}
或者通过指定/重载ManipulationStated事件(如下两种),OriginalSource指明事件的来源。
ManipulationStarted="OnTextBlockManipulationStarted"
protected override void OnManipulationStarted(ManipulationStartedEventArgs args)
{
if (args.OriginalSource == txtblk)
{
}
}
路由事件:Manipulation事件源自于用户触摸的可用顶层元素。但是如果该顶层元素不关心该事件的话,该事件就会转发到该元素的负元素中去。如此,一直转发到可视化树的最高级PhoneApplicationcationFrame元素为止。沿途的任何元素都可以获取这个输入事件并进行处理,也能组织事件往树的高层继续传递。
位图:XNA中,位图是一种Texture2D类型的数据。"Hello"是资源名。
helloTexture = this.Content.Load<Texture2D>("Hello");
Silverlight中通过<Image>标签,图片默认会伸展。
<Image Source="Images/Hello.png" />
网络图片:Silverlight不变
<Image Source="http://www.charlespetzold.com/Media/HelloWP7.jpg" />
XNA需要使用WebClient下载(异步),下载完触发OpenreadCompleted事件。
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
WebClient webClient = new WebClient();
webClient.OpenReadCompleted += OnWebClientOpenReadCompleted;
webClient.OpenReadAsync(new Uri("http://www.charlespetzold.com/Media/HelloWP7.jpg"));
}
//然后通过静态Texture2D.FromStream方法创建一个Texture2D对象。
void OnWebClientOpenReadCompleted(object sender, OpenReadCompletedEventArgs args)
{
if (!args.Cancelled && args.Error == null)
{
helloTexture = Texture2D.FromStream(this.GraphicsDevice, args.Result);
}
}
由于是异步的,Draw中需要判断是否准备好。
if (helloTexture != null)
{
spriteBatch.Begin();
spriteBatch.Draw(helloTexture, position, Color.White);
spriteBatch.End();
}
实际上<Image>标签的source属性是ImageSource。抽象类ImageSource的派生类BitmapSource定义了一个名为SetSource的方法,该方法可以通过Stream对象加载位图。
BitmapImage bmp = new BitmapImage();
bmp.SetSource(args.Result);
BitmapSource也支持一个接收Uri对象的构造函数。
Uri uri = new Uri("http://www.charlespetzold.com/Media/HelloWP7.jpg");
BitmapImage bmp = new BitmapImage(uri);
位图的Build Action属性:
1.当Build Action为Resource时,位图与编译后的程序一同存储在SilverlightTapToLoad.dll文件中。
2.当Build Action为Content时,位图存储在SilverlightTapToLoad.dll文件的外部,但是存储在XAP文件的内部,还是在Images目录内。
从相机获取图片:使用CameraCaptureTask,Completed事件程序的参数PhotoResult包含有一个相片的Stream对象。
camera.Completed += OnCameraCaptureTaskCompleted;
墓碑化(tombstoning):程序中断,所需的信息被Windows Phone的操作系统自动保存。需要负责保存和恢复足够的信息来保证程序可以恢复到墓碑化之前的状态。
从手机图片库中选择:使用PhotoChooserTask、使用MediaLibrary。
加速计:使用Accelerometer类
Accelerometer acc = new Accelerometer();
acc.ReadingChanged += OnAccelerometerReadingChanged;
Silverlight不允许从非UI线程中访问UI对象,使用Dispatcher类,可以将一些工作项从非UI线程传递到一个队列中,该队列中的工作项稍后将被UI线程执行。
委托(delegate):用于关联事件和驱动函数,定义委托类的返回值和参数。
delegate void SetTextBlockTextDelegate(TextBlock txtblk, string text);
Dispatcher.BeginInvoke第一个参数是方法实例化的委托,紧接着是所需的参数。
txtblk.Dispatcher.BeginInvoke(new SetTextBlockTextDelegate(SetTextBlockText), txtblk, str);
地理位置:通过GeocoordinateWatcher获取经纬度。
页面导航:通过NavigationService
this.NavigationService.Navigate(new Uri("/SecondPage.xaml", UriKind.Relative));
页面参数传递:与HTML类似
void OnTextBlockManipulationStarted(object sender, ManipulationStartedEventArgs args)
{
string destination = "/SecondPage.xaml";
if (ContentPanel.Background is SolidColorBrush)
{
Color clr = (ContentPanel.Background as SolidColorBrush).Color;
destination += String.Format("?Red={0}&Green={1}&Blue={2}",
clr.R, clr.G, clr.B);
}
this.NavigationService.Navigate(new Uri(destination, UriKind.Relative));
}
在目标网页中
protected override void OnNavigatedTo(NavigationEventArgs args)
{
IDictionary<string, string> parameters = this.NavigationContext.QueryString;
if (parameters.ContainsKey("Red"))
{
byte R = Byte.Parse(parameters["Red"]);
}
}
页面间数据共享
1.通过Application类,因为所有页面都可以通过Application.Current返回当前程序的Application对象。
//Application.xaml.cs
public Color? SharedColor { set; get; }
Navigate之前保存到App类的属性中
void OnTextBlockManipulationStarted(object sender, ManipulationStartedEventArgs args)
{
if (ContentPanel.Background is SolidColorBrush)
(Application.Current as App).SharedColor =
(ContentPanel.Background as SolidColorBrush).Color;
this.NavigationService.Navigate(new Uri("/SecondPage.xaml", UriKind.Relative));
args.Complete();
args.Handled = true;
}
2.OnNavigatedFrom的方法,定义了两个属性,Uri类型的Uri,Object类型的Content,标识了要导航到的页面。源页面可以设置目标页面的属性或调用目标页面类的方法。
//SecondPage.xaml.cs
protected override void OnNavigatedFrom(NavigationEventArgs args)
{
if (ContentPanel.Background is SolidColorBrush)
{
Color clr = (ContentPanel.Background as SolidColorBrush).Color;
if (args.Content is MainPage)
(args.Content as MainPage).ReturnedColor = clr;
}
base.OnNavigatedFrom(args);
}
保留多个实例的数据:MainPage导航到SecondPage,每个实例都不一样。使用PhoneApplicationService类的state(IDictionary<string, object>类型)属性保存。
// Save color
PhoneApplicationService.Current.State["Color"] = clr;
墓碑化
启动(Launched):当一个应用程序从Start屏幕运行
关闭(Closed):当一个应用程序通过单击Back按键而终止
停用(Deactived):当程序正在运行时,用户按下Start按键。不过程序是真的死了,这时程序处于墓碑化状态。
激活(Activated):用户导航返回到一个程序,该程序从墓碑化还原回来。
使用PhoneApplicationService的state属性保存临时数据(一个程序同一个执行周期)
protected override void OnNavigatedFrom(NavigationEventArgs args)
{
appService.State["numTaps"] = numTaps;
}
protected override void OnNavigatedTo(NavigationEventArgs args)
{
// Load numTaps
if (appService.State.ContainsKey("numTaps"))
{
}
}
注意:访问时不能直接使用[],而必须使用TryGetValue或者ContainsKey。
应用程序设置:一个程序的所有实例中共享数据。
应用程序设置应该在Launching和Activated事件中加载,而在调用Deactivated和Closing事件的时候保存。
private void Application_Activated(object sender, ActivatedEventArgs e)
{
LoadSettings();
}
private void Application_Deactivated(object sender, DeactivatedEventArgs e)
{
SaveSettings();
}
void SaveSettings()
{
IsolatedStorageSettings settings = IsolatedStorageSettings.ApplicationSettings;
if (BackgroundBrush is SolidColorBrush)
{
settings["backgroundColor"] = (BackgroundBrush as SolidColorBrush).Color;
settings.Save();
}
}
XNA的墓碑化:使用IsolatedStorageFile和序列化
属性继承:PhoneApplicationPage中设置的属性会影响到该页面中所有的Textblock元素。某些属性可以在可视化树中进行传播。
声明命名空间:
xmlns:system="clr-namespace:System;assembly=mscorlib"
这是关联XML命名空间和.NET命名空间的标准语法。
TranslateTransform:平移变换(移动位置)
ScaleTransform:缩放变换(增大或减小尺寸)
RotateTransform:旋转变换(围绕某个点旋转)
SkewTransform:二维扭曲(在一个维度内基于另一个维度移动)
MatrixTransform:矩阵变换(基于标准举证表示的变换)
TransformGroup:复合变换(按指定顺序将多个变换复合为一个变换)
CompositeTransform:组合变换(按固定的顺序组合一系列变换)
依赖属性(Dependency Properties)
如果你要创建一个自定义控件类,并为这个类定义新的属性,如果你想给这些属性设置Style,或者你想通过给那些属性设置数据绑定(Binding),或者想对这些属性使用动画,那么你需要将这些属性设置成依赖属性(Dependency Properties)。
public static readonly DependencyProperty Color1Property =
DependencyProperty.Register("Color1",
typeof(Color),
typeof(BetterGradientButton),
new PropertyMetadata(Colors.Black, OnColorChanged));
public Color Color1
{
set { SetValue(Color1Property, value); }
get { return (Color)GetValue(Color1Property); }
}
通过调用静态的DependencyProperty.Register方法来创建DependencyProperty类型的对象。第一个参数是属性名对应的文本字符串;第二个参数是属性的类型;第三个属性是定义属性的类。最后一个参数是一个PropertyMetadata类型的对象,构造函数中一个是属性的默认值,一个是当属性值改变是调用的事件处理程序名称。