在Silverlight 和WPF中使用预编译指令 if..else..endif (译)
下面的是中文翻译,有些扯淡的话就略过了,想看原文,请到这里
对于预编译指令,作者分成了几篇文章来讲解的。鉴于翻译后的文字较少,我把作者的几篇合为了一篇。下面进入正题。
一、总揽:
想要编写特定平台的代码,可以使用预编译来实现。Silverlight工程有默认的“SILVERLIGHT”预编译声明,对特定平台可以选择包含或者排除代码。可以通过使用#if
....#endif 包围的代码来实现。比如:
#if SILVERLIGHT
//Silverlight and Windows
Phone
#else
//WPF
#endif
或者
#if WINDOWS_PHONE
//Windows
Phone
#endifor
或者
#if !SILVERLIGHT || WINDOWS_PHONE
//Windows
Phone and WPF
#endifor
或者
#if SILVERLIGHT &&
!WINDOWS_PHONE
//Silverlight but NOT Windows
Phone
#endif
在后面的博客中您还会看到在不同平台之间区分代码的更多应用。
二、Custom Controls
Theme
使用默认的主题和模板自定义控件的时候,可以在“/Themes/Generic.xaml”文件里分别对Silverlight和WPF做不同的处理:
public
class MyControl : Control
{
public MyControl()
{
#if
Silverlight
this.DefaultStyleKey =
typeof(MyControl);
#endif
}
static MyControl()
{
#if
!SILVERLIGHT
DefaultStyleKeyProperty.OverrideMetadata(typeof(HoverControl),new
FrameworkPropertyMetadata(typeof(HoverControl)));
#endif
}
}
并且,WPF程序集中,需要在AssemblyInfo.cs文件里注册主题文件,
[assembly:
ThemeInfo(ResourceDictionaryLocation.None,ResourceDictionaryLocation.SourceAssembly)]
通常在创建WPF工程时,会自动添加这些代码。
三、XamlReader
XamlReader在WPF和Silverlight中的重载不同,Silverlight使用字符串,WPF使用字符串构建的字节流。比如:
UIElement
element;
#if SILVERLIGHT
element =
XamlReader.Load(xaml);
#else
using (MemoryStream xamlStream =
new MemoryStream(UTF8Encoding.Default.GetBytes(xaml)))
element = XamlReader.Load(xamlStream);
#endif
四、Creating Bitmaps
Programmatically
WPF需要你设置图片的源前后分别调用BeginInit和EndInit方法,而且加载失败时的事件也不一样。如下:
BitmapImage
bmi = new BitmapImage();
#if !SILVERLIGHT
bmi.BeginInit();
#endif
Image img = new Image();
bmi.UriSource
= new Uri(strUrl, UriKind.Absolute);
#if SILVERLIGHT
img.ImageFailed
+= img_ImageFailed;
#else
bmi.DownloadFailed +=
bmi_DownloadFailed;
bmi.EndInit();
#endif
Image myImage = new
Image();
myImage.Source = bmi;
五、Animations
如果你想应用动画,并且在运行的时候编辑他们,那么WPF需要你使用额外的参数来开始和关闭动画。比如:
#if
SILVERLIGHT
myStoryboard.Begin();
myStoryboard.Stop();
#else
myStoryboard.Begin(element, true); //true allows for changing animation
later
myStoryboard.Stop(element); //element parameter required when
Begin was called with element
#endif
六、XAML Control Instantiation
先看看一下代码:
<UserControl
Loaded="UserControl_Loaded">
<my:MyControl Loaded="MyControl_Loaded"
/>
</UserControl>
你能猜猜下面的事件和方法在XAML加载时的调用顺序是啥吗?
-
UserControl.Constructor
- MyControl.Constructor
-
UserControl.Loaded event
- MyControl.Loaded event
-
MyControl.OnApplyTemplate method
Silverlight和WPF的触发顺序是不一样的:
Silverlight
WPF
UserControl.Constructor
UserControl.Constructor
MyControl.Constructor
MyControl.Constructor
MyControl.Loaded
event MyControl.OnApplyTemplate method
UserControl.Loaded event
UserControl.Loaded event
MyControl.OnApplyTemplate
method MyControl.Loaded event
WPF自定义控件时,OnApplyTemplate方法是在Loaded之前触发的,而Silverlight里面是在Loaded之后触发的。因此,如果你的OnApplyTemplate函数,需要依赖Loaded事件首先触发的话,在WPF里面可能不会起作用。而且需要说明的是两个Loaded事件触发是对立的。还可以查看MSDN:
七、Debug.WriteLine
我经常使用System.Diagnostics.Debug.WriteLine来输出值或者警告,但是错误就不用输出了。
然而Silverlight里面有的一些重载,WPF里面没有。
下面是Silverlight里面的重载
public static void WriteLine(object value);
public static void
WriteLine(string message);
public static void WriteLine(string format,
params object[] args); //NOT IN WPF!
WPF里面的重载:
public static void
WriteLine(object value);
public static void WriteLine(string
message);
public static void WriteLine(object value, string
category);
public static void WriteLine(string message, string category);
Silverlight里面的第三个重载用法和string.Format用法一样,但是在WPF里面不存在。因此比用在两个平台中更安全。
八、大小写敏感
通常,在XAML里面,Silverlight看起来约束更少,比如大小写敏感。我最近试过在UserControl里面使用ClassModifier类,如下:
<UserControl
x:ClassModifier=”Internal”>
然而,这样用法在WPF里面就不能用了,应该使用小写的internal关键字。幸运的是也能在Silverlight里面用。