Silverlight-TabControl扩展

来源:互联网 时间:1970-01-01

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>

 

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

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

本文来自超时空饭盒的博客,原文地址:http://www.cnblogs.com/HalfwayMonk/archive/2011/06/28/2092790.html


相关阅读:
Top