WPF--模板选择

典型的,把模板关联到一块特定的数据上,不过通常希望动态的确定使用哪个模板---既可以基于一个属性值,也可以是一个全局状态。当真正需要大规模替换模板时,也可以使用DataTemplateSelector。

DataTemplateSelector提供了一个单一的方法----SelectTemplate,以允许通过执行任何逻辑来决定使用哪个模板。可以在被包含的元素中查找模板,并返回一些硬编码的模板,甚至动态的为每个条目创建模板。

首先,创建一个继承自DataTemplateSelector的类,并完成一些在几个模板中进行旋转的逻辑。在这个例子中,将找到XmlElement的LocalName,并从容器中获取具有该名称的资源,代码如下:

 public class LocalNameTemplateSelector : DataTemplateSelector
    {
        public override DataTemplate SelectTemplate (object item,DependencyObject container)
 
        {
            XmlElement data = item as XmlElement;
 
            if (data != null)
            {
                return ((FrameworkElement)container).FindResource(data.LocalName) as DataTemplate;
            }
            return null;
        }

为了初始化所有的模板,将构建三个模板:用于书籍的棕色矩形,用于CD的银色圆形以及用于DVD的蓝色圆形。由于模板选择器将查找XmlElement的本地名称,所以需要为每个模板设置X:Key,代码如下:

 <DataTemplate x:Key="Book" DataType="{x:Type sx:XmlElement}">
            <StackPanel Orientation="Horizontal">
            <Rectangle Margin="2" Width="14" Height="14" Fill="Brown"/>
            <TextBlock  VerticalAlignment="Center" Text="{Binding [email protected]}"></TextBlock>
            </StackPanel>
        </DataTemplate>

        <DataTemplate x:Key="CD" DataType="{x:Type sx:XmlElement}">
            <StackPanel Orientation="Horizontal">
                <Ellipse Margin="2" Width="14" Height="14" Fill="Silver"/>
                <TextBlock  VerticalAlignment="Center" Text="{Binding [email protected]}"></TextBlock>
            </StackPanel>
        </DataTemplate>

        <DataTemplate x:Key="DVD" DataType="{x:Type sx:XmlElement}">
            <StackPanel Orientation="Horizontal">
                <Ellipse Margin="2" Width="14" Height="14" Fill="Blue"/>
                <TextBlock  VerticalAlignment="Center" Text="{Binding [email protected]}"></TextBlock>
            </StackPanel>
        </DataTemplate>

余下的就是把模板选择器和ListBox进行关联,而不是设置静态模板,代码如下:

 <ListBox ItemsSource="{Binding XPath=/Media/*}">
            <ListBox.ItemTemplateSelector>
                <l:LocalNameTemplateSelector xmlns:l="clr-namespace:WpfProgressBarDemo"/>
            </ListBox.ItemTemplateSelector>
        </ListBox>

前台完整代码如下:

<Window x:Class="WpfProgressBarDemo.DataTemplateSelectorDemo"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:sx="clr-namespace:System.Xml;assembly=System.Xml"

        Title="DataTemplateSelector" Height="300" Width="300"

        DataContext="{DynamicResource dataSource}"
        >

    <Window.Resources>
        <!--数据源-->
        <XmlDataProvider x:Key="dataSource">
            <x:XData>
                <Media xmlns="">
                    <Book Author="Aretch" Title="WCF全面解析"/>
                    <Book Author="ByVoid" Title="Node.js开发指南"/>
                    <Book Author="Rogers Cardenhead" Title="21天学通Java"/>
                    <CD  Title="没有CD了"/>
                    <DVD  Title="《十面埋伏》"/>
                </Media>
            </x:XData>
        </XmlDataProvider>
        <DataTemplate x:Key="Book" DataType="{x:Type sx:XmlElement}">
            <StackPanel Orientation="Horizontal">
            <Rectangle Margin="2" Width="14" Height="14" Fill="Brown"/>
            <TextBlock  VerticalAlignment="Center" Text="{Binding [email protected]}"></TextBlock>
            </StackPanel>
        </DataTemplate>

        <DataTemplate x:Key="CD" DataType="{x:Type sx:XmlElement}">
            <StackPanel Orientation="Horizontal">
                <Ellipse Margin="2" Width="14" Height="14" Fill="Silver"/>
                <TextBlock  VerticalAlignment="Center" Text="{Binding [email protected]}"></TextBlock>
            </StackPanel>
        </DataTemplate>

        <DataTemplate x:Key="DVD" DataType="{x:Type sx:XmlElement}">
            <StackPanel Orientation="Horizontal">
                <Ellipse Margin="2" Width="14" Height="14" Fill="Blue"/>
                <TextBlock  VerticalAlignment="Center" Text="{Binding [email protected]}"></TextBlock>
            </StackPanel>
        </DataTemplate>
    </Window.Resources>
    <Grid>
        <ListBox ItemsSource="{Binding XPath=/Media/*}">
            <ListBox.ItemTemplateSelector>
                <l:LocalNameTemplateSelector xmlns:l="clr-namespace:WpfProgressBarDemo"/>
            </ListBox.ItemTemplateSelector>
        </ListBox>
    </Grid>
</Window>

好了完成了,本实例除了可以学怎样动态进行模板选择,哪还将学会怎样使用XML数据绑定。另外为了使读者能更好的理解,现提供另一个我项目中的例子供大家参考

后台:

  public class LocalNameTemplateSelector : DataTemplateSelector
    {
        public override DataTemplate SelectTemplate(object item, DependencyObject container)
        {
            if (item != null && item is DeviceCheckInfo)
            {
                DeviceCheckInfo device = item as DeviceCheckInfo;

                Window2 win = new Window2();
                if (device.CheckResult)
                    return win.FindResource("dui") as DataTemplate;
                else
                    return win.FindResource("cuo") as DataTemplate;
            }
            return null;
        }
    }

  public class DeviceCheckInfo
    {
        //设备名称
        public string Name { get; set; }
        //检测内容
        public string CheckContent { get; set; }
        //检测结果
        public bool CheckResult { get; set; }
    }

Xaml部分:

<Window x:Class="WpfProgressBarDemo.Window2"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfProgressBarDemo"
        Title="Window2" Height="433" Width="500" Loaded="Window_Loaded">
    <Window.Resources>
        <local:IShowTrueOrFalse x:Key="convetToImage"></local:IShowTrueOrFalse>

        <Style TargetType="TextBlock" >
            <Setter Property="HorizontalAlignment" Value="Center"/>
            <Setter Property="VerticalAlignment" Value="Center"/>
            <Setter Property="Margin" Value="30"/>
            <Setter Property="FontSize" Value="20"/>
        </Style>

        <DataTemplate x:Key="dui" DataType="{x:Type local:DeviceCheckInfo}" >
            <StackPanel Orientation="Horizontal" CheckBox.Checked="StackPanel_Checked">
                <TextBlock Text="{Binding Path=Name}" Margin="10"  VerticalAlignment="Center" FontSize="20"/>
                <TextBlock Text="{Binding Path=CheckContent}" Margin="10" VerticalAlignment="Center" FontSize="20"/>
                <Path x:Name="dui" Data="M43,5 L20,40 20,40 0,20 6,15 18,26 37,7 43,5 z" Fill="Green" Margin="5"  Stretch="Fill"/>
                <CheckBox Name="checkbox" Checked="checkbox_Checked"/>
            </StackPanel>
        </DataTemplate>

        <DataTemplate x:Key="cuo" DataType="{x:Type local:DeviceCheckInfo}">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding Path=Name}" Margin="10" VerticalAlignment="Center" FontSize="20"/>
                <TextBlock Text="{Binding Path=CheckContent}" Margin="10" VerticalAlignment="Center" FontSize="20"/>

                <Path Margin="5" Data="M50,25 L25,50 M25,25 50,50" Fill="#FFF4F4F5"  Height="40" Stretch="Fill" Stroke="Red"  Width="40" StrokeThickness="8"/>
                <CheckBox Name="checkbox" Checked="checkbox_Checked"/>
            </StackPanel>
        </DataTemplate>
        <local:LocalNameTemplateSelector x:Key="myDataTemplateSelector"/>
    </Window.Resources>

    <Grid>
        <ListBox Name="lbtest" ItemTemplateSelector="{StaticResource myDataTemplateSelector}" SelectionChanged="lbtest_SelectionChanged" />

           </Grid>
</Window>

				
时间: 2024-08-22 06:32:14

WPF--模板选择的相关文章

WPF模板(一)详细介绍

原文:WPF模板(一)详细介绍 本次随笔来源于电子书,人家的讲解很好,我就不画蛇添足了. 图形用户界面应用程序较之控制台界面应用程序最大的好处就是界面友好.数据显示直观.CUI程序中数据只能以文本的形式线性显示,GUI程序则允许数据以文本.列表.图形等多种形式立体显示. 用户体验在GUI程序设计中起着举足轻重的作用-----用户界面设计成什么样看上去才足够的漂亮?控件如何安排才简单易用并且少犯错误?这些都是设计师需要考虑的问题.WPF系统不但支持传统的Winfrom编程的用户界面和用户体验设计,

WPF快速入门系列(7)——深入解析WPF模板

一.引言 模板从字面意思理解是“具有一定规格的样板".在现实生活中,砖块都是方方正正的,那是因为制作砖块的模板是方方正正的,如果我们使模板为圆形的话,则制作出来的砖块就是圆形的,此时我们并不能说圆形的”砖块“不是砖块吧.因为形状只是它们的外观,其制作材料还是一样的.所以,模板可以理解为表现形式.WPF中的模板同样是表现形式的意思. 在WPF中包括三种模板:控件模板.数据模版和面板模板.它们都继承于FrameworkTemplate基类,其继承层次结果如下图所示: 从上图可以发现,Framewor

WPF TreeView 选择事件执行两次,获取TreeView的父节点的解决方法

1.TreeView选择事件执行两次 Very often, we need to execute some code in SelectedItemChanged depending on the selected TreeViewItem. ButSelectedItemChanged is called twice. This is due to stealing focus from the main window, which is screwing something up. Wha

WPF模板(二)应用

原文:WPF模板(二)应用 本次内容来源于电子书,和上一篇一样. 在WPF中有三大模板ControlTemplate,ItemsPanelTemplate,DataTemplate.其中ControlTemplate和ItemsPanelTemplate是控件模板,DataTemplate是数据模板,他们都派生自FrameworkTemplate抽象类. 1.ControlTemplate ControlTemplate:控件模板主要有两个重要属性:VisualTree内容属性和Triggers

WPF中模板选择和DataContext的一些使用

如图样: View结构 MainView(MainViewModel)|---Guide1View(Guide1ViewModel)|---Guide2View(Guide2ViewModel) |---Guide2_1View1(Guide2_1ViewModel) |---Guide2_1View2(Guide2_1ViewModel) ViewModel实例结构 Main(ViewModelViewModel)|---CurrentViewModel(GuidePageViewModelB

WPF模板

1:ControlTemplate 我们知道wpf的控件都是继承自Control,在Control类中有一个Template属性,类型就是ControlTemplate.那么利用这个ControlTemplate就可以彻底的颠覆控件的默认外观. <Window x:Class="WpfApplication1.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" x

Introduction to WPF Templates(WPF模板简介)

Introduction(简介) Windows Presentation Foundation allows the developer to completely change the look and feel of the controls. This is accomplished by using Control Templates. It means you can render your Button as an Ellipse which when hovered will c

wpf 模板选择器DataTemplateSelector及动态绑定,DataTemplate.Triggers触发器的使用

通常,如果有多个 DataTemplate 可用于同一类型的对象,并且您希望根据每个数据对象的属性提供自己的逻辑来选择要应用的 DataTemplate,则应创建 DataTemplateSelector.请注意,如果具有不同类型的对象,则可以对 DataTemplate 设置 DataType 属性.如果您执行了此操作,则无需创建 DataTemplateSelector.此外,如果对象类型相同但属性不同,也可以考虑使用 DataTrigger 或数据转换器. 通俗讲,就是根据不同的数据选择不

转 Oracle DBCA高级玩法:从模板选择、脚本调用到多租户

但凡是学过Oracle的同学,对DBCA(Database Configuration Assistant, DBCA)都不会陌生,有了这个工具,使得创建数据库成为可能.而DBCA本身有图形和静默两种方式.其中静默方式看起来高大上一些,因为一个看似复杂的创建数据库的过程,用一个命令就可以轻松搞定.静默安装的命令类似下面的形式,其中创建的数据库为testdb,字符集为ZHS16GBK. dbca -silent -createDatabase -templateName $ORACLE_HOME/

WPF 自动选择dll,以SQLite为例

在学习sqlite的过程中,发现它的dll是区分32位和64位的,起初觉得很恼火,但是仔细看了下, 发现让程序自行选择dll其实也不是一件很麻烦的事情,如下: 1>创建一个sqlite数据 2>创建一个工程 3>新建一个类 1 class Entrance : Application 2 { 3 [STAThread] 4 static void Main() 5 { 6 string dll32 = @".\SQLitedll\System.Data.SQLite32.dll