Silverlight-TabControl扩展(2)
上一篇简单扩展了TabControl的ItemsSource属性。只是只能应用一个统一的模板展示数据,但是毕竟ItemsSource是IEnumerable类型的,这就意味着里面的每个Item都可以有自己不同的Type,而相同的DataTemolate可能并不适用。
在WPF和SL5中可以给DataTemplate标记DataType,这样ItemsControl会去自己识别相应的类型所需的模板。在SL4中也让我们来简单实践下。
在TabControlExtensions类里增加一个DataTemplate的附加属性,实验证明Type类型并不能很好的被编译器识别,还是用string了。
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类,继承增加三个不同的类型。
{
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。
<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方法稍作调整就行了。
{
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获取相应的模板,很简单。
看下效果,条纹斑马:
白肚皮黑身体的企鹅:
一圈一圈尾巴的环尾狐猴:
以及代码:这里
半路和尚 by 超时空饭盒 is licensed under a Creative Commons 署名-非商业性使用-相同方式共享 3.0 Unported License.
基于halfwaymonk.cnblogs.com上的作品创作。