WPF数据模板

这篇具有很好参考价值的文章主要介绍了WPF数据模板。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

样式提供了基本的格式化能力,但它们不能消除到目前为止看到的列表的最重要的局限性:不管如何修改ListBoxItem,它都只是ListBoxItem,而不是功能更强大的元素组合。并且因为每个ListBoxItem只支持单个绑定字段,所以不可能实现包含多个字段或图像的富列表。

然而WPF另有一个工具可突破这个相当大的限制,并允许组合使用来自绑定对象的多个属性,并以特定的方式排列它们或显示比简单字符串更高级的可视化表示。这个工具就是数据模板。

数据模板是一块定义如何显示绑定的数据对象的XAML标记。有两种类型的控件支持数据模板:

内容控件 通过ContentTemplate属性支持数据模板。内容模板用于显示任何放置在Content属性中的内容。

列表控件(继承自ItemsControl类的控件) 通过ItemsTemplate属性支持数据模板。这个模板用于显示作为ItemsSource提供的集合中的每个项(或来自DataTable的每一行)。

基于列表的模板特性实际上以内容控件模板为基础,这是因为列表中的每个项均由内容控件封装。数据模板是一块普通的XAML标记。与其他XAML标记一样,数据模板可以包含任意元素的组合,还应当包含一个或多个数据绑定表达式,从而提取希望显示的信息。

分离和重用模板

数据模板可以写在应用模板控件标签下,也可以放在资源内作为公共资源,以便复用。放在资源标签内时,可以指定模板的Key并在应用控件里面通过Key关联模板,与常规的资源没什么两样;也可以指定DataType属性,会自动应用于绑定与DataType指定的数据类型相同的控件。

<DataTemplate x:Key="highlightTemplate" DataType="{x:Type local:Order}" >
    <Grid Margin="0" Background="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem} }, Path=Background}">
        <Border Margin="5" BorderThickness="1" BorderBrush="SteelBlue" Background="LightYellow" CornerRadius="4">
            <Grid Margin="3">
                <Grid.RowDefinitions>
                    <RowDefinition></RowDefinition>
                    <RowDefinition></RowDefinition>
                    <RowDefinition></RowDefinition>
                </Grid.RowDefinitions>
                <TextBlock Grid.Row="0" FontWeight="Bold" Text="{Binding Path=Price}" />
                <TextBlock Grid.Row="1" FontWeight="Bold" Text="{Binding Path=Volume}" />
                <TextBlock Grid.Row="2" FontStyle="Italic" HorizontalAlignment="Right">*** Great for vacations ***</TextBlock>
            </Grid>
        </Border>
    </Grid>
</DataTemplate>

改变模板

可以通过几种方式为同一个列表使用不同的模板

数据触发器 可根据绑定的数据对象中的属性值使用触发器修改模板中的属性。

值转换器 实现了IValueConverter接口的类,能够将值从绑定的对象转换为可用于设置模板中与格式化相关的属性的值。

模板选择器 模板选择器检查绑定的数据对象,并在几个不同模板之间进行选择。

数据触发器提供了最简单的方法。基本技术是根据数据项中的某个属性,设置模板中某个元素的某个属性。这种方法非常有用,但是不能改变与模板相关的复杂细节,只能修改模板或容器元素中的单个属性。此外触发器只能测试是否相等,不支持更复杂的比较条件。

<DataTemplate DataType="{x:Type local:Order}" >
    <DataTemplate.Triggers>
        <DataTrigger Binding="{Binding Path=Price}" Value="1000">
            <Setter Property="ListBoxItem.Foreground" Value="Red"></Setter>
            <Setter Property="ListBoxItem.FontStyle" Value="Italic"></Setter>
        </DataTrigger>
    </DataTemplate.Triggers>
</DataTemplate>

值转换器在数据转换里面介绍过了,通过Converter属性设置,可以根据绑定的对象调整自身。

<Image Grid.Column="1" Grid.RowSpan="2" Source="{Binding Path=Image, Converter={StaticResource ImagePathConverter}}"></Image>

模板选择器是一种更强大的工具,可以根据不同的条件应用完全不同的模板。模板选择器继承自DataTemplateSelector,需要实现 SelectTemplate() 函数,返回应用的DataTemplate。

public class SingleCriteriaHighlightTemplateSelector : DataTemplateSelector
{
    public System.Windows.DataTemplate DefaultTemplate { get; set; }
    public System.Windows.DataTemplate HighlightTemplate { get; set; }
    public override System.Windows.DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        Order order = (Order)item;
        if (order.Price >= 10000)
        {
            return HighlightTemplate;
        }
        else
        {
            return DefaultTemplate;
        }
    }
}
<Window>
    <Window.Resources>
    <DataTemplate x:Key="defaultTemplate" DataType="{x:Type local:Order}" >
        <DataTemplate.Triggers>
            <DataTrigger Binding="{Binding Path=Price}" Value="1000">
                <Setter Property="ListBoxItem.Foreground" Value="Red"></Setter>
            </DataTrigger>
        </DataTemplate.Triggers>
        <Grid Margin="0" Background="White">
            <Border Margin="5" BorderThickness="1" BorderBrush="SteelBlue"
            Background="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem} }, Path=Background}" CornerRadius="4">
                <Grid Margin="3">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition/>
                        <ColumnDefinition/>
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition></RowDefinition>
                        <RowDefinition></RowDefinition>
                        <RowDefinition></RowDefinition>
                    </Grid.RowDefinitions>
                    <TextBlock FontWeight="Bold" Text="{Binding Path=Price}"></TextBlock>
                    <TextBlock Grid.Row="1" Text="{Binding Path=Volume}"></TextBlock>
                    <Image Grid.Column="1" Grid.RowSpan="2" Source="{Binding Path=Image, Converter={StaticResource ImagePathConverter}}"></Image>
                </Grid>
            </Border>
        </Grid>
    </DataTemplate>
    <DataTemplate x:Key="highlightTemplate" DataType="{x:Type local:Order}" >
        <Grid Margin="0" Background="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem} }, Path=Background}">
            <Border Margin="5" BorderThickness="1" BorderBrush="SteelBlue" Background="LightYellow" CornerRadius="4">
                <Grid Margin="3">
                    <Grid.RowDefinitions>
                        <RowDefinition></RowDefinition>
                        <RowDefinition></RowDefinition>
                        <RowDefinition></RowDefinition>
                    </Grid.RowDefinitions>
                    <TextBlock Grid.Row="0" FontWeight="Bold" Text="{Binding Path=Price}" />
                    <TextBlock Grid.Row="1" FontWeight="Bold" Text="{Binding Path=Volume}" />
                    <TextBlock Grid.Row="2" FontStyle="Italic" HorizontalAlignment="Right">*** Great for vacations ***</TextBlock>
                </Grid>
            </Border>
        </Grid>
    </DataTemplate>
    </Window.Resources>

    <ListBox Grid.Row="0" Grid.Column="1" ItemsSource="{Binding Path=Orders}" ItemContainerStyle="{StaticResource listBoxItemStyle}" HorizontalContentAlignment="Stretch">
        <ListBox.ItemTemplateSelector>
            <local:SingleCriteriaHighlightTemplateSelector DefaultTemplate="{StaticResource defaultTemplate}" HighlightTemplate="{StaticResource highlightTemplate}"/>
        </ListBox.ItemTemplateSelector>
    </ListBox>
</Window>

完整代码如下:

MainWindow.xaml

<Window x:Class="DataTemplate.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:DataTemplate"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <local:ImagePathConverter x:Key="ImagePathConverter"></local:ImagePathConverter>
        <DataTemplate DataType="{x:Type local:Order}" >
            <DataTemplate.Triggers>
                <DataTrigger Binding="{Binding Path=Price}" Value="1000">
                    <Setter Property="ListBoxItem.Foreground" Value="Red"></Setter>
                    <Setter Property="ListBoxItem.FontStyle" Value="Italic"></Setter>
                </DataTrigger>
            </DataTemplate.Triggers>
            <Grid Margin="0" >
                <Border Margin="5" BorderThickness="1" BorderBrush="SteelBlue"
                    Background="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem} }, Path=Background}" CornerRadius="4">
                    <Grid Margin="3">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition/>
                            <ColumnDefinition/>
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition></RowDefinition>
                            <RowDefinition></RowDefinition>
                            <RowDefinition></RowDefinition>
                        </Grid.RowDefinitions>
                        <TextBlock FontWeight="Bold" Text="{Binding Path=Price}"></TextBlock>
                        <TextBlock Grid.Row="1" Text="{Binding Path=Volume}"></TextBlock>
                        <Image Grid.Column="1" Grid.RowSpan="2" Source="{Binding Path=Image, Converter={StaticResource ImagePathConverter}}"></Image>
                    </Grid>
                </Border>
            </Grid>
        </DataTemplate>

        <DataTemplate x:Key="defaultTemplate" DataType="{x:Type local:Order}" >
            <DataTemplate.Triggers>
                <DataTrigger Binding="{Binding Path=Price}" Value="1000">
                    <Setter Property="ListBoxItem.Foreground" Value="Red"></Setter>
                </DataTrigger>
            </DataTemplate.Triggers>
            <Grid Margin="0" Background="White">
                <Border Margin="5" BorderThickness="1" BorderBrush="SteelBlue"
                    Background="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem} }, Path=Background}" CornerRadius="4">
                    <Grid Margin="3">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition/>
                            <ColumnDefinition/>
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition></RowDefinition>
                            <RowDefinition></RowDefinition>
                            <RowDefinition></RowDefinition>
                        </Grid.RowDefinitions>
                        <TextBlock FontWeight="Bold" Text="{Binding Path=Price}"></TextBlock>
                        <TextBlock Grid.Row="1" Text="{Binding Path=Volume}"></TextBlock>
                        <Image Grid.Column="1" Grid.RowSpan="2" Source="{Binding Path=Image, Converter={StaticResource ImagePathConverter}}"></Image>
                    </Grid>
                </Border>
            </Grid>
        </DataTemplate>
        <DataTemplate x:Key="highlightTemplate" DataType="{x:Type local:Order}" >
            <Grid Margin="0" Background="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem} }, Path=Background}">
                <Border Margin="5" BorderThickness="1" BorderBrush="SteelBlue" Background="LightYellow" CornerRadius="4">
                    <Grid Margin="3">
                        <Grid.RowDefinitions>
                            <RowDefinition></RowDefinition>
                            <RowDefinition></RowDefinition>
                            <RowDefinition></RowDefinition>
                        </Grid.RowDefinitions>
                        <TextBlock Grid.Row="0" FontWeight="Bold" Text="{Binding Path=Price}" />
                        <TextBlock Grid.Row="1" FontWeight="Bold" Text="{Binding Path=Volume}" />
                        <TextBlock Grid.Row="2" FontStyle="Italic" HorizontalAlignment="Right">*** Great for vacations ***</TextBlock>
                    </Grid>
                </Border>
            </Grid>
        </DataTemplate>
        
        <Style x:Key="listBoxItemStyle" TargetType="{x:Type ListBoxItem}">
            <Setter Property="Control.Padding" Value="0"></Setter>
            <Style.Triggers>
                <Trigger Property="ListBoxItem.IsSelected" Value="True">
                    <Setter Property="ListBoxItem.Background" Value="DarkRed" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <Grid Name="myGrid" >
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>

        <ListBox Grid.Row="0" Grid.Column="0" ItemsSource="{Binding Path=Orders}" ItemContainerStyle="{StaticResource listBoxItemStyle}" HorizontalContentAlignment="Stretch"/>

        <ListBox Grid.Row="0" Grid.Column="1" ItemsSource="{Binding Path=Orders}" ItemContainerStyle="{StaticResource listBoxItemStyle}" HorizontalContentAlignment="Stretch">
            <ListBox.ItemTemplateSelector>
                <local:SingleCriteriaHighlightTemplateSelector DefaultTemplate="{StaticResource defaultTemplate}" HighlightTemplate="{StaticResource highlightTemplate}"/>
            </ListBox.ItemTemplateSelector>
        </ListBox>

        <ListView Grid.Row="1" Grid.Column="0" ItemsSource="{Binding Path=Orders}" HorizontalContentAlignment="Stretch" ></ListView>
    </Grid>
</Window>

MainWindow.xaml.cs文章来源地址https://www.toymoban.com/news/detail-689006.html

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media.Imaging;

namespace DataTemplate;

public class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler? PropertyChanged;
    protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
    protected virtual bool SetProperty<T>(ref T member, T value, [CallerMemberName] string? propertyName = null)
    {
        if (EqualityComparer<T>.Default.Equals(member, value))
        {
            return false;
        }
        member = value;
        OnPropertyChanged(propertyName);
        return true;
    }
}
public class Order : ViewModelBase
{
    public decimal price = 0;
    public decimal Price { get => price; set => SetProperty(ref price, value); }
    public int volume = 0;
    public int Volume { get => volume; set => SetProperty(ref volume, value); }

    public DateTime orderDate = DateTime.Now;
    public DateTime OrderDate { get => orderDate; set => SetProperty(ref orderDate, value); }

    public string image = string.Empty;
    public string Image { get => image; set => SetProperty(ref image, value); }
}
public class ImagePathConverter : IValueConverter
{
    private string imageDirectory = Directory.GetCurrentDirectory();
    public string ImageDirectory
    {
        get { return imageDirectory; }
        set { imageDirectory = value; }
    }
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        string imagePath = Path.Combine(ImageDirectory, (string)value);
        return new BitmapImage(new Uri(imagePath));
    }
    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotSupportedException("The method or operation is not implemented.");
    }
}

public class SingleCriteriaHighlightTemplateSelector : DataTemplateSelector
{
    public System.Windows.DataTemplate DefaultTemplate { get; set; }
    public System.Windows.DataTemplate HighlightTemplate { get; set; }
    public override System.Windows.DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        Order order = (Order)item;
        if (order.Price >= 10000)
        {
            return HighlightTemplate;
        }
        else
        {
            return DefaultTemplate;
        }
    }
}

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        myGrid.DataContext = this;

        Order order1 = new Order();
        Order order2 = new Order();
        Order order3 = new Order();
        Order order4 = new Order();

        order1.Price = 100;
        order1.Volume = 10;
        order1.Image = "image1.gif";

        order2.Price = 1000;
        order2.Volume = 100;
        order2.Image = "image2.gif";

        order3.Price = 10000;
        order3.Volume = 1000;
        order3.Image = "image3.gif";

        order4.Price = 100000;
        order4.Volume = 10000;
        order4.Image = "image4.gif";

        Orders.Add(order1);
        Orders.Add(order2);
        Orders.Add(order3);
        Orders.Add(order4);
    }
    public ObservableCollection<Order> Orders { get; set; } = new();
}

到了这里,关于WPF数据模板的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 哈工大CSAPP程序人生大作业

    正在上传…重新上传取消 计算机系统 大作业 题     目   程序人生 -Hello’s P2P  专       业    计算机科学与技术        学    号   2021110991             班    级      2103101             学       生         安心           指 导 教 师    

    2023年04月24日
    浏览(68)
  • 【程序人生】上海城市开发者社区小聚有感

    📫作者简介: 小明java问道之路 , 2022年度博客之星全国TOP3 ,专注于后端、中间件、计算机底层、架构设计演进与稳定性建设优化,文章内容兼具广度、深度、大厂技术方案,对待技术喜欢推理加验证,就职于知名金融公司后端高级工程师。          📫 热衷分享,喜欢原

    2024年02月06日
    浏览(65)
  • 【程序人生】如何在工作中保持稳定的情绪?

    在工作中保持稳定的情绪是现代生活中一个备受关注的话题。随着职场压力和工作挑战的增加,我们常常发现自己情绪波动不定,甚至受到负面情绪的困扰。然而,保持稳定的情绪对于我们的工作效率、人际关系和整体幸福感都至关重要。 无论你是一位职场新人还是一位资深

    2024年02月15日
    浏览(43)
  • 程序人生 | 编程的上帝视角应该怎么去找

      前言 📫 作者简介 :小明java问道之路,专注于Linux内核/汇编/HotSpot/C++/Java/源码/架构/算法 就职于大型金融公司后端高级工程师,擅长交易领域的高安全/可用/并发/性能的架构设计📫  🏆 CSDN专家博主/Java优质创作者/CSDN内容合伙人 、InfoQ签约作者 、阿里云专家/签约博主、

    2023年04月24日
    浏览(86)
  • C罗老矣,我的程序人生还有多远

    ☆ 随着12月11号摩洛哥1-0葡萄牙比赛的结束,不仅说明葡萄牙对要结束本届卡塔尔世界杯了,就连C罗此生的世界杯之旅也将画上句号了。 ☆ 37岁的球星本该是人生最璀璨的阶段,但在足球生涯中,这已经是大龄了。不禁让我想到,身为开发的我,也大概类似吧。   目录  1、

    2024年01月16日
    浏览(49)
  • 程序人生——Java数组和集合使用建议(2)

    程序人生——Java数组和集合使用建议(2) 需求:要删除一个ArrayList中的20-30范围内的元素;将原列表转换为一个可变列表,然后使用subList获取到原列表20到30范围内的一个视图(View),然后清空该视图内的元素,即可在原列表中删除20到30范围内的元素 建议72:生成子列表后

    2024年03月19日
    浏览(47)
  • 【程序人生】还记得当初自己为什么选择计算机?

            还记得人生中第一次接触计算机编程是在高中,第一门编程语言是Python(很可惜由于条件限制的原因,当时没能坚持学下去......现在想来有点后悔,没能坚持,唉......)。但是,错过的就错过了,把握当前才是正确的选择。努力最好的时机永远是在过去,其次就在当

    2024年02月04日
    浏览(63)
  • 《人生苦短,我学Python》——第一个python程序

    Hello!朋友们大家好,从今天开始,我们将学习 Python 的相关内容。 首先,让我们来思考一个问题,编程是什么? 编程是人类与电脑沟通的过程,可以告诉电脑做什么以及怎么做。人类用编程构建数字世界,比如网站、App、办公软件等等。 世界上有很多种编程语言,比如C,

    2024年02月11日
    浏览(42)
  • 人工智能AI时代:全栈程序员的人生规划

    博主 默语带您 Go to New World. ✍ 个人主页—— 默语 的博客👦🏻 《java 面试题大全》 🍩惟余辈才疏学浅,临摹之作或有不妥之处,还请读者海涵指正。☕🍭 《MYSQL从入门到精通》数据库是开发者必会基础之一~ 🪁 吾期望此文有资助于尔,即使粗浅难及深广,亦备添少许微薄

    2024年02月11日
    浏览(79)
  • 程序人生 | 与足球共舞的火柴人(致敬格拉利什,赋予足球更深的意义)

    个人简介 👀 个人主页: 前端杂货铺 🙋‍♂️ 学习方向: 主攻前端方向,也会涉及到服务端 📃 个人状态: 在校大学生一枚,已拿多个前端 offer(秋招) 🚀 未来打算: 为中国的工业软件事业效力n年 🥇 推荐学习:🍍前端面试宝典 🍉Vue2 🍋Vue3 🍓Vue2Vue3项目实战 🥝

    2024年02月02日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包