本文原文见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: 来取值。