Silverlight-TabControl扩展(2)

上一篇简单扩展了TabControl的ItemsSource属性。只是只能应用一个统一的模板展示数据,但是毕竟ItemsSource是IEnumerable类型的,这就意味着里面的每个Item都可以有自己不同的Type,而相同的DataTemolate可能并不适用。

在WPF和SL5中可以给DataTemplate标记DataType,这样ItemsControl会去自己识别相应的类型所需的模板。在SL4中也让我们来简单实践下。

在TabControlExtensions类里增加一个DataTemplate的附加属性,实验证明Type类型并不能很好的被编译器识别,还是用string了。

View Code
private static Dictionary<string, DataTemplate> _templateStore = new Dictionary<string, DataTemplate>();

public static string GetDataTypeName(DependencyObject d)
{
return (string)d.GetValue(DataTypeNameProperty);
}

public static void SetDataTypeName(DependencyObject d, string value)
{
d.SetValue(DataTypeNameProperty, value);
}

public static readonly DependencyProperty DataTypeNameProperty =
DependencyProperty.Register(
"DataTypeName", typeof(string), typeof(DataTemplate),
new PropertyMetadata(OnDataTypeNameChanged));


private static void OnDataTypeNameChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var template
= d as DataTemplate;
var typeName
= (string)e.NewValue;
if (!string.IsNullOrEmpty(typeName))
{
_templateStore[typeName]
= template;
}
}

在回调方法里把相应的键值存储到一个静态字典里,以便以后取用。

稍微改一下上次的那个Animal类,继承增加三个不同的类型。

View Code
public abstract class Animal
{
public abstract string Name { get; }
public int Count { get; set; }
public string From { get; set; }
}

public class Zabra : Animal
{
public override string Name
{
get { return "斑马"; }
}
}

public class Penguin : Animal
{
public override string Name
{
get { return "企鹅"; }
}
}

public class Lemur : Animal
{

public override string Name
{
get { return "环尾狐猴"; }
}
}

然后就是在Resources里为三个不同的类型增加三个不同的DataTemplate。

View Code
<UserControl.Resources>
<DataTemplate x:Key="s" local:TabControlExtensions.DataTypeName="Penguin">
<Grid Background="Black">
<Grid.RowDefinitions>
<RowDefinition Height="0.2*"/>
<RowDefinition Height="0.6*"/>
<RowDefinition Height="0.2*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.2*"/>
<ColumnDefinition Width="0.6*"/>
<ColumnDefinition Width="0.2*"/>
</Grid.ColumnDefinitions>
<Rectangle Grid.Column="1" Fill="White" Grid.Row="1"/>
</Grid>
</DataTemplate>

<DataTemplate x:Key="ss" local:TabControlExtensions.DataTypeName="Zabra">
<Grid>
<Grid.Background>
<LinearGradientBrush EndPoint="20,20" SpreadMethod="Repeat" MappingMode="Absolute">
<GradientStop Color="Black" Offset="0"/>
<GradientStop Color="Black" Offset="0.5"/>
<GradientStop Color="White" Offset="0.5"/>
<GradientStop Color="White" Offset="1"/>
</LinearGradientBrush>
</Grid.Background>
</Grid>
</DataTemplate>

<DataTemplate x:Key="sss" local:TabControlExtensions.DataTypeName="Lemur">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.5*"/>
<ColumnDefinition Width="0.5*"/>
</Grid.ColumnDefinitions>
<Rectangle Grid.Column="1">
<Rectangle.Fill>
<LinearGradientBrush EndPoint="0,0" StartPoint="30,0" SpreadMethod="Repeat" MappingMode="Absolute">
<GradientStop Color="Black" Offset="0"/>
<GradientStop Color="Black" Offset="0.5"/>
<GradientStop Color="White" Offset="0.5"/>
<GradientStop Color="White" Offset="1"/>
</LinearGradientBrush>
</Rectangle.Fill>
</Rectangle>
</Grid>
</DataTemplate>
</UserControl.Resources>

x:key随便写一下,并为每个DataTemplate设置local:TabControlExtensions.DataTypeName附加属性,属性的值为对应的需要呈现此模板的类名,可见第一个模板是给企鹅的,第二个是给斑马的,第三个是给狐猴的。

最后只要对上次的那个OnItemsSourceChanged方法稍作调整就行了。

View Code
private static void OnItemsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var source
= d as TabControl;
var items
= e.NewValue as IEnumerable;

source.Items.Clear();

if (items != null)
{
var headerTemplate
= GetHeaderTemplate(source);
var contentTemplate
= GetContentTempalte(source);

foreach (var item in items)
{
//-------
var typeName = item.GetType().Name;
var itemTemplate
= _templateStore.ContainsKey(typeName) ? _templateStore[typeName] : null;
//-------

var tabItem
= new TabItem
{
DataContext
= item,
Header
= item,
HeaderTemplate
= headerTemplate,
Content
= item,
//---------
ContentTemplate = itemTemplate ?? contentTemplate,
//---------
};
source.Items.Add(tabItem);
}
}
}

增加的部分代码用注释标记了,从存储了键值的字典里根据Type的Name获取相应的模板,很简单。

看下效果,条纹斑马:

白肚皮黑身体的企鹅:

一圈一圈尾巴的环尾狐猴:

以及代码:这里

posted @ 2011-07-04 23:42  超时空饭盒  阅读(2627)  评论(2编辑  收藏  举报