Silverlight-TabControl扩展

TabControl是平常用的比较多的布局控件,虽然它是继承自ItemsControl,但是它的ItemsSource实在是很不好用,谁用谁知道。

prism里为TabControl提供了TabControlRegionAdapter和TabControlRegionSyncBehavior,参考其部分实现方式让我们也来实现个TabControl的扩展来更好的MVVM。

看代码:

public class TabControlExtensions
{
public static IEnumerable GetItemsSource(DependencyObject d)
{
return (IEnumerable)d.GetValue(ItemsSourceProperty);
}

public static void SetItemsSource(DependencyObject d, IEnumerable value)
{
d.SetValue(ItemsSourceProperty, value);
}

public static readonly DependencyProperty ItemsSourceProperty =
DependencyProperty.RegisterAttached(
" ItemsSource " , typeof (IEnumerable), typeof (TabControl),
new PropertyMetadata(OnItemsSourceChanged));

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 tabItem
= new TabItem
{
DataContext
= item,
Header
= item,
HeaderTemplate
= headerTemplate,
Content
= item,
ContentTemplate
= contentTemplate,
};
source.Items.Add(tabItem);
}
}
}



public static DataTemplate GetHeaderTemplate(DependencyObject d)
{
return (DataTemplate)d.GetValue(HeaderTemplateProperty);
}

public static void SetHeaderTemplate(DependencyObject d, DataTemplate value)
{
d.SetValue(HeaderTemplateProperty, value);
}

public static readonly DependencyProperty HeaderTemplateProperty =
DependencyProperty.RegisterAttached(
" HeaderTemplate " , typeof (DataTemplate), typeof (TabControl),
new PropertyMetadata(OnHeaderTemplateChanged));

private static void OnHeaderTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var source
= d as TabControl;
var template
= e.NewValue as DataTemplate;

foreach (TabItem item in source.Items)
{
item.HeaderTemplate
= template;
}
}


public static DataTemplate GetContentTempalte(DependencyObject d)
{
return (DataTemplate)d.GetValue(ContentTempalteProperty);
}

public static void SetContentTempalte(DependencyObject d, DataTemplate value)
{
d.SetValue(ContentTempalteProperty, value);
}

public static readonly DependencyProperty ContentTempalteProperty =
DependencyProperty.Register(
" ContentTempalte " , typeof (DataTemplate), typeof (TabControl),
new PropertyMetadata(OnContentTempalteChanged));

private static void OnContentTempalteChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var source
= d as TabControl;
var template
= e.NewValue as DataTemplate;

foreach (TabItem item in source.Items)
{
item.ContentTemplate
= template;
}
}
}

扩展类TabControlExtensions提供了三个附加属性:

ItemsSource用于设置TabControl的数据源(摒弃自身的ItemsSource不用了)。

HeaderTemplate和ContentTempalte方便设置数据的显示模板(ItemsControl也有ItemTemplate属性,为了清晰,此处就单独拎出来了)。

在三个回调方法里的操作很简单,一看就明白。

来个Model类:

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

再来个简单的ViewModel类:

public class Zoo
{
public IEnumerable < Animal > Animals { get ; private set ; }

public Zoo()
{
this .Animals = new List < Animal >
{
new Animal{Name = " 斑马 " ,Count = 10 ,From = " 塞伦盖提 " },
new Animal{Name = " 企鹅 " ,Count = 23 ,From = " 加拉帕戈斯 " },
new Animal{Name = " 环尾狐猴 " ,Count = 8 ,From = " 马达加斯加 " },
};
}
}

看下Xaml里的具体设置和最后的效果:  

< UserControl x:Class ="TabControlExtensions.MainPage"
xmlns
="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sdk
="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
xmlns:local
="clr-namespace:TabControlExtensions" >

< UserControl.DataContext >
< local:Zoo />
</ UserControl.DataContext >

< UserControl.Resources >
< DataTemplate x:Key ="HeaderTempalte" >
< TextBlock Text =" {Binding Name} " />
</ DataTemplate >
< DataTemplate x:Key ="ContentTemplate" >
< StackPanel >
< TextBlock Text =" {Binding Count,StringFormat='数量:\{0\}'} " />
< TextBlock Text =" {Binding From,StringFormat='来自:\{0\}'} " />
</ StackPanel >
</ DataTemplate >
</ UserControl.Resources >

< Grid x:Name ="LayoutRoot" Background ="White" >
< sdk:TabControl Margin ="30"
local:TabControlExtensions.ItemsSource
=" {Binding Animals} "
local:TabControlExtensions.HeaderTemplate
=" {StaticResource HeaderTempalte} "
local:TabControlExtensions.ContentTempalte
=" {StaticResource ContentTemplate} " />
</ Grid >
</ UserControl >

Silverlight-TabControl扩展

只要想的到,其实一切都很简单。

另外现在的方式只能在ItemsSource里的每个Item拥有相同或者类似的属性时才有最好的效果,下次继续扩展。

你可能感兴趣的:(silverlight)