在这片文章中我将解释如何在Silverlight for Windows Phone7中创建一个DataTemplateSelector抽象类以及CustomDataTemplateSelector。DataTemplateSelector可以基于数据对象和数据绑定提供一种方式去选择DataTemplate。特殊情况下,当你对于同一种对象有多个DataTemplate并且你想要按照自己的逻辑去选择DataTemplate应用到各个数据对象的属性的时候需要一些DataTemplateSelector。

  总之,DataTemplateSelector使你对于一些特殊项,可以写一些逻辑选择使用哪种DataTemplate。如果有必要,你甚至可以创建一个新的数据模板。

  注意:DataTemplateSelector在WPF是一个众所周知的类,但是在Silverlight中不支持。

  下面是我在开发者论坛中看到的一个很流行的问题:“我有一列不同类型的元素,我想针对不同的列表元素基于它的类型显示不同的数据模板。”

  这个问题的答案就是使用DataTemplateSelector。因此在这篇文章中我会首先解释如何实现DataTemplateSelector抽象类并且证明如何实现你自己的CustomDataTemplateSelector。最后的结果会显示在右边的图中。

 

实现DataTemplateSelector抽象类

 有许多不同的方式创建一个动态的DataTemplateSelector。你可以从WPF的实现中获取一些代码或者尝试用ValueConverter等等。在这篇文章中我将展示利用ContentControl如何创建一个DataTemplateSelector(我将用ContentControl作为基类)。

  我首先将要创建一个包含SelectTemplate虚方法的抽象类,此方法返回一个基于Prority属性值的恰当的模板(当在任何为DataTemplateSelector的分部类中重载时)。我将同时重载来自基类的OnContentChanged方法。源代码如下:

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);
   }
}

 

如何创建一个CustomDataTemplateSelector

  为了创建CustomDataTemplateSelector,首先创建一个冲DataTemplateSelector类继承的类,并且重载SelectorTemplate方法。一旦你的类定义好之后,你就可以把这个类的实例指定给你的界面元素的template selector property。

  我将创建FoodTemplateSelector类,它包括三个不同DataTemplates:Healthy,UnHealthy以及NotDetermined。在SelectorTemplate方法中我将添加一些条件语句来选择合适的DataTemplate。我将基于Data的Type属性值选择正确的模板。

 

FoodTemplateSelector类源代码如下:

public class FoodTemplateSelector : DataTemplateSelector
{
public DataTemplate Healthy
    {
get;
set;
    }

public DataTemplate UnHealthy
    {
get;
set;
    } 

public DataTemplate NotDetermined
    {
get;
set;
    }

    public override DataTemplate SelectTemplate(object item,  DependencyObject container)
    {
        Data foodItem = item as Data;

if (foodItem != null)
        {
if (foodItem.Type == "Healthy")
            {
return Healthy;
            }
else if (foodItem.Type == "NotDetermined")
            {
return NotDetermined;
            }
else
            {
return UnHealthy;
            }
        }
return base.SelectTemplate(item, container);
    }
}

 

以下是Data类:

public class Data
{
    public string Name
    {
        get;
        set;
    }

    public string Description
    {
        get;
        set;
    }

    public string IconUri
    {
        get;
        set;
    }
 
    public string Type
    {
        get;
        set;
    }
}

 

为了展示FoodTemplateSelector的作用,我将利用ListBox进行数据绑定。下面是源代码:

public MainPage()
        {
            InitializeComponent();

            List<Data> list = new List<Data>();
            Data item0 = new Data() { Name = "Tomato", IconUri = "Images/Tomato.png", Type = "Healthy" };
            Data item1 = new Data() { Name = "Beer", IconUri = "Images/Beer.png", Type = "NotDetermined" };
            Data item2 = new Data() { Name = "Fries", IconUri = "Images/fries.png", Type = "Unhealthy" };
            Data item3 = new Data() { Name = "Sandwich", IconUri = "Images/Hamburger.png", Type = "Unhealthy" };
            Data item4 = new Data() { Name = "Ice-cream", IconUri = "Images/icecream.png", Type = "Healthy" };
            Data item5 = new Data() { Name = "Pizza", IconUri = "Images/Pizza.png", Type = "Unhealthy" };
            Data item6 = new Data() { Name = "Pepper", IconUri = "Images/Pepper.png", Type = "Healthy" };
            list.Add(item0);
            list.Add(item1);
            list.Add(item2);
            list.Add(item3);
            list.Add(item4);
            list.Add(item5);
            list.Add(item6);
            this.listBox.ItemsSource = list;
        }

  

然后我将创建三个不同的DataTemplate并且将他们只是为ListBox的ItemTemplate。注意每一个Template是独立的,并且与其它没有联系。这意味着你可以在每个Template中自由添加你想要的任何元素。因此你可以用三种不同的方式展示一个数据源。

datadirVolumeClaimTemplate 本地_抽象类

  最后的结果如左图所示。

下面是每个模板的样式:

 

datadirVolumeClaimTemplate 本地_Data_02

datadirVolumeClaimTemplate 本地_抽象类_03

datadirVolumeClaimTemplate 本地_Data_04

 

以下是源代码:

<ListBox x:Name="listBox" HorizontalContentAlignment="Stretch">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <local:FoodTemplateSelector Content="{Binding}">
                <local:FoodTemplateSelector.Healthy>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal" Background="YellowGreen" Width="400" Margin="10">
                            <Image Source="{Binding IconUri}" Stretch="None"/>
                            <TextBlock Text="{Binding Name}" FontSize="40" Foreground="Black" Width="280"/>
                            <TextBlock Text="healty" />
                        </StackPanel>
                    </DataTemplate>
                    </local:FoodTemplateSelector.Healthy>
                <local:FoodTemplateSelector.UnHealthy>
                    <DataTemplate>
                        <Border BorderBrush="Red" BorderThickness="2"  Width="400" Margin="10">
                        <StackPanel Orientation="Horizontal">
                            <Image Source="{Binding IconUri}" Stretch="None"/>
                                <TextBlock Text="{Binding Name}" FontSize="40" Width="280"/>
                            <Image Source="Images/attention.png" Stretch="None" Margin="10,0,0,0"/>
                        </StackPanel>
                        </Border>
                    </DataTemplate>
                </local:FoodTemplateSelector.UnHealthy>
                <local:FoodTemplateSelector.NotDetermined>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal" Background="Gray" Width="400" Margin="10">
                            <Image Source="{Binding IconUri}" Stretch="None"/>
                            <TextBlock Text="{Binding Name}" FontSize="40" Width="280"/>
                            <Image Source="Images/question.png" Stretch="None" Margin="10,0,0,0"/>
                        </StackPanel>
                    </DataTemplate>
                </local:FoodTemplateSelector.NotDetermined>
            </local:FoodTemplateSelector>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

 

最终的结果:ListBox的每一项根据不同的Type属性值使用不同的template。

以下是实现DataTemplateSelector的其他途径链接:

这就是所有关于如何实现DataTemplateSelector抽象类的方法,并且在Silverlight for windows phone 7中如何使用它。你可以在这里找到源代码:WP7SampleProject10.zip

希望这篇文章对你有帮助。