实现Windows Phone 下的DataTemplateSelector 和 CustomDataTemplateSelector

转自:[译]实现Windows Phone 7 下的DataTemplateSelector 和 CustomDataTemplateSelector


  在这片文章中我将解释如何在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中自由添加你想要的任何元素。因此你可以用三种不同的方式展示一个数据源。

  最后的结果如左图所示。

下面是每个模板的样式:

 

 

以下是源代码:

复制代码
<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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值