zoukankan      html  css  js  c++  java
  • 实现Windows Phone7 的DataTemplateSelector和CustomDataTemplateSelector

    在这篇文章中,我将要介绍在Windows Phone 7开发环境中怎么去创建一个DataTemplateSelector的虚类和自定义一个CustomDataTemplateSelector。通常DataTemplateSelector提供一种基于数据对象和数据绑定的选择DataTemplate的途径。特别是在对于同类的对象有多个DataTemplate,并且能根据逻辑选择DataTemplate应用到数据对象上。

    简单的说,DataTemplateSelector允许我们编写一些逻辑去选择哪个DataTemplate运用到哪个特定的项上。甚至可以创建一个新的Template 。

      

    NOTE: DataTemplateSelector 在WPF中是一个很好用的类,不过它现在还没有Silverlight版本

    下面是一个在dev forums很热门的一个问题

    "I have a list of different types of elements. I would like to display a different data template for different list elements, based on what type it is. "

    这个问题的答案是利用DataTemplateSelector。因此在这篇文章里我先要解释怎么去实现一个DataTemplateSelector,然后我会介绍怎么去实现自己的自定义CustomDataTemplateSelector 。最后的效果图会贴在本文中。

    实现DataTemplateSelector虚类

    有很多的方法去建立一个动态的DataTemplateSelector 。你可以从WPF默认实现DataTemplateSelector的代码中去提取代码,利用ValueConverter实现等等。在这篇文章中我会介绍怎么去建立一个继承自ContentControl(这里把ContentControl当做一个基类) 的DataTemplateSelector 。

    我们要做的第一件事就是建立一个带有选择合适Template虚方法抽象类。这个虚方法SelectTemplate可以根据优先属性的值(在一个继承自DataTemplateSelector特定的类被重写时)返回一个合适的Template。这里需要重写基类的OnContentChanhed 事件,下面是源码:

    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

    为了建立一个自定义的模板选择器,首先需要建立一个继承自DataTemplateSelector 的类,然后要override它的SelectTemplate方法。一旦你的类定义好之后,你就可以把这个类的实例指定给你的界面element的template selector property。

    为了演示,这里我会建立一个FoodTemplateSelector 类,它包含三个不同的DataTemplates:Healthy, UnHealthy and NotDetermined。在SelectTemplate 方法里我会加上一些条件,这些条件可以根据 data context的属性值选择合适的DataTemplate。基本上我们可以通过数据源的属性值选择正确的template。

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

    这里是数据类:

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

    下一步要做的是建立三个DataTemplates 并且把它们分别设定成ListBox的一个ItemTemplate。因为这三个DataTemplate都是独立的相互之间没有联系,这意味着你可以在每个DataTemplate上使用任何的element。因此一个数据源可以三种不同的显示。

    左边的是效果图,这是这三个DataTemplates 的模样:                 


                                                        

    建立 ListBox的源码如下:

    <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的每一个item由于不同的Type属性值都有不同的template 。

     

    这里贴出有用的链接,提供了实现DataTemplateSelector  的途径:

    到这里,关于如何建立建立DataTemplateSelector 虚类和如何在Silverlight for Windows Phone 7中使用它的方法就介绍完了。

    附上示例源码包下载:WP7DataTemplateSelector.zip


    希望它能对你有用。
    原文地址:windowsphonegeekDataTemplateSelector
  • 相关阅读:
    initData()
    moveUp()
    moveLeft()
    moveDown()
    函数具体分析
    Linux命令学习笔记
    RocketMQ使用记录
    solr安装记录
    centos7下面ruby的升级
    centos7下面装fastdfs
  • 原文地址:https://www.cnblogs.com/navigator/p/2917691.html
Copyright © 2011-2022 走看看