本文原文见WindowGeek。
在Window Phone中,我们常常遇到一些情形,譬如在ListBox中,我们要根据具体的Data来决定该如何显示当前项。这可以通过DataTemplateSelector来实现。
实现DataTemplateSelector抽象类
public abstract class DataTemplateSelector : ContentControl { public virtual DataTemplate SelectTemplate(object item, DependencyObject container) { return null; } protected override void OnContentChanged(object oldContent, object newContent) { base.OnContentChanged(oldContent, newContent); ContentTemplate = SelectTemplate(newContent, this); } }
创建你自己的数据模板选择器
public class RSSTemplateSelector : DataTemplateSelector { public DataTemplate MixedTextImgTemplate { get; set; } public DataTemplate ImgTemplate { get; set; } public DataTemplate TextTemplate { get; set; } public override DataTemplate SelectTemplate(object item, DependencyObject container) { RssItemResp rss = item as RssItemResp; if (rss != null) { if (!CommonUtil.isEmpty(rss.Image) && !CommonUtil.isEmpty(rss.Description)) { return MixedTextImgTemplate; } else if (CommonUtil.isEmpty(rss.Image) && !CommonUtil.isEmpty(rss.Description)) { return TextTemplate; } else if (CommonUtil.isEmpty(rss.Description) && !CommonUtil.isEmpty(rss.Image)) { return ImgTemplate; } } return base.SelectTemplate(item, container); } }
定义XAML文件
<ListBox.ItemTemplate> <DataTemplate> <local:RSSTemplateSelector Content="{Binding}"> <local:RSSTemplateSelector.MixedTextImgTemplate> <DataTemplate> <Grid> <Grid.RowDefinitions> <RowDefinition Height="12"/> <RowDefinition Height="*"/> <RowDefinition Height="12"/> </Grid.RowDefinitions> <Image Grid.Row="0" Width="Auto" Source="Images/paperview_top.png"/> <Grid Grid.Row="1" Width="Auto"> <Grid.RowDefinitions> <RowDefinition Height="*"/> <RowDefinition Height="*"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <TextBlock Grid.Row="0" Text="{Binding Title}" /> <TextBlock Grid.Row="1" Text="{Binding UpdateTime}" /> <StackPanel Grid.Row="2" Orientation="Horizontal" Height="Auto"> <TextBlock Text="{Binding Description}" /> <Image Source="{Binding Image}" Height="100" Width="100" Margin="0,2,3,5"/> </StackPanel> </Grid> <Image Grid.Row="2" Width="Auto" Source="Images/paperview_bottom.png"/> </Grid> </DataTemplate> </local:RSSTemplateSelector.MixedTextImgTemplate> <local:RSSTemplateSelector.ImgTemplate> <DataTemplate> <Grid> <Grid.RowDefinitions> <RowDefinition Height="12"/> <RowDefinition Height="*"/> <RowDefinition Height="12"/> </Grid.RowDefinitions> <Image Grid.Row="0" Width="Auto" Source="Images/paperview_top.png"/> <StackPanel Grid.Row="1" Orientation="Vertical"> <TextBlock Text="{Binding Title}" /> <TextBlock Text="{Binding UpdateTime}" /> <StackPanel Orientation="Horizontal" Height="60"> <Image Source="{Binding Image}"/> </StackPanel> </StackPanel> <Image Grid.Row="2" Width="Auto" Source="Images/paperview_bottom.png"/> </Grid> </DataTemplate> </local:RSSTemplateSelector.ImgTemplate> <local:RSSTemplateSelector.TextTemplate> <DataTemplate> <Grid> <Grid.RowDefinitions> <RowDefinition Height="12"/> <RowDefinition Height="*"/> <RowDefinition Height="12"/> </Grid.RowDefinitions> <Image Grid.Row="0" Width="Auto" Source="Images/paperview_top.png"/> <StackPanel Orientation="Vertical"> <TextBlock Text="{Binding Title}" /> <TextBlock Text="{Binding UpdateTime}" /> <StackPanel Orientation="Horizontal" Height="60"> <TextBlock Text="{Binding Description}" /> </StackPanel> </StackPanel> <Image Grid.Row="2" Width="Auto" Source="Images/paperview_bottom.png"/> </Grid> </DataTemplate> </local:RSSTemplateSelector.TextTemplate> </local:RSSTemplateSelector> </DataTemplate> </ListBox.ItemTemplate>
综上,我们就可以实现为ListBox提供动态模板了。
前端时间也接触一下android框架层的东西,就是没有感觉;
这段时间还是难以压制自己心中对技术的渴求,又从新开始了解android框架,那我就先从JNI的实例开始了,可是在网上找了很多资料,其中的特点我总结一下:
1、版本比较多
2、内容多是入门的HelloWorld实例和环境配置为主
3、翻译过来的JNI资料有限
我也是刚入门的,所以我找了很长时间找到了一个讲的比较细致,能够实现的实例;
http://zhaoningbo.iteye.com/blog/1098817
下面是NDK的实例,谁然是ubuntu下的实例,但是讲的比较详细,我在win7下同样实现了:
http://www.cnblogs.com/shadox/archive/2011/12/02/2272564.html
供大家分享;
感谢这个作者的细心与奉献!
我也会尽力为大家分享我的更新,尽情期待吧![b][/b]
从 NSDictionary 取值的时候有两个方法,objectForKey: 和 valueForKey:,这两个方法具体有什么不同呢?
先从 NSDictionary 文档中来看这两个方法的定义:
objectForKey: returns the value associated with aKey, or nil if no value is associated with aKey. 返回指定 key 的 value,若没有这个 key 返回 nil.
valueForKey: returns the value associated with a given key. 同样是返回指定 key 的 value。
直观上看这两个方法好像没有什么区别,但文档里 valueForKey: 有额外一点:
If key does not start with “@”, invokes objectForKey:. If key does start with “@”, strips the “@” and invokes [super valueForKey:] with the rest of the key. via Discussion
一般来说 key 可以是任意字符串组合,如果 key 不是以 @ 符号开头,这时候 valueForKey: 等同于 objectForKey:,如果是以 @ 开头,去掉 key 里的 @ 然后用剩下部分作为 key 执行 [super valueForKey:]。
比如:
NSDictionary *dict = [NSDictionary dictionaryWithObject:@"theValue"
forKey:@"theKey"];
NSString *value1 = [dict objectForKey:@"theKey"];
NSString *value2 = [dict valueForKey:@"theKey"];
这时候 value1 和 value2 是一样的结果。如果是这样一个 dict:
NSDictionary *dict = [NSDictionary dictionaryWithObject:@"theValue"
forKey:@"@theKey"];// 注意这个 key 是以 @ 开头
NSString *value1 = [dict objectForKey:@"@theKey"];
NSString *value2 = [dict valueForKey:@"@theKey"];
value1 可以正确取值,但是 value2 取值会直接 crash 掉,报错信息:
Terminating app due to uncaught exception ‘NSUnknownKeyException’, reason: ‘[<__NSCFDictionary 0x892fd80> valueForUndefinedKey:]: this class is not key value coding-compliant for the key theKey.’
这是因为 valueForKey: 是 KVC(NSKeyValueCoding) 的方法,在 KVC 里可以通过 property 同名字符串来获取对应的值。比如:
@interface Person : NSObject
@property (nonatomic, retain) NSString *name;
@end
...
Person *person = [[Person alloc] init];
person.name = @"fannheyward";
NSLog(@"name:%@", [person name]);
//name:fannheyward
NSLog(@"name:%@", [person valueForKey:@"name"]);
//name:fannheyward
[person release];
valueForKey: 取值是找和指定 key 同名的 property accessor,没有的时候执行 valueForUndefinedKey:,而 valueForUndefinedKey: 的默认实现是抛出 NSUndefinedKeyException 异常。
回过头来看刚才 crash 的例子, [dict valueForKey:@"@theKey"]; 会把 key 里的 @ 去掉,也就变成了 [dict valueForKey:@"theKey"];,而 dict 不存在 theKey 这样的 property,转而执行 [dict valueForUndefinedKey:@"theKey"];,抛出 NSUndefinedKeyException 异常后 crash 掉。
objectForKey: 和 valueForKey: 在多数情况下都是一样的结果返回,但是如果 key 是以 @ 开头,valueForKey: 就成了一个大坑,建议在 NSDictionary 下只用 objectForKey: 来取值。