WPF数据转换
在基本绑定中,信息从源到目标的传递过程中没有任何变化。这看起来是符合逻辑的,但我们并不总是希望出现这种行为。通常,数据源使用的是低级表达方式,我们可能不希望直接在用户界面使用这种低级表达方式。WPF提供了两个工具,来进行数据转换:
字符串格式化
通过设置 Binding.StringFormat 属性对文本形式的数据进行转换——例如包含日期和数字的字符串。
值转换器
该功能更强大,使用该功能可以将任意类型的源数据转换为任意类型的对象表示,然后可以传递到关联的控件。
使用StringFormat属性
<TextBlock Grid.Row="0" Grid.Column="0" Text="{Binding Path=Price, StringFormat=ConvertDirectly:{0:C}}"></TextBlock>
<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding Path=Price, StringFormat={}{0:C}}"></TextBox>
<TextBox Grid.Row="2" Grid.Column="1" Text="{Binding Path=OrderDate, StringFormat={}{0:s}}"></TextBox>
可以看到后面两个StringFormat属性以花括号 {} 开头,完整值是 {}{0:C},而不是 {0:C},第一个则只有 {0:C},这是因为在StringFormat 值以花括号开头时需要 {} 转义序列。
使用值转换器
为创建子转换器需要执行以下四个步骤:
1、创建一个实现IValueConverter接口的类
2、为该类声明添加ValueConversion特性,并指定目标数据类型
3、实现Convert()方法,该方法将数据从原来的格式转换为显示的格式
4、实现ConvertBack()方法,该方法执行反向变换,将值从显示格式转换为原格式
[ValueConversion(typeof(decimal), typeof(string))]
public class PriceConverter : IValueConverter
{public object Convert(object value, Type targetType, object parameter, CultureInfo culture){decimal price = (decimal)value;return price.ToString("C", culture);}public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture){string price = (string)value;if (decimal.TryParse(price, System.Globalization.NumberStyles.Any, culture, out decimal result)){return result;}return value;}
}
要使用这个转换器,可以将其添加到页面的资源下,然后使用 Binding.Converter 指定。
<Window><Window.Resources><local:PriceConverter x:Key="priceConverter"/><local:PriceToBackgroundConverter x:Key="priceToBackgroundConverter" MinimumPriceToHighlight="100" DefaultBrush="{x:Null}" HighlightBrush="Orange"/><local:ImagePathConverter x:Key="imagePathConverter"/><local:MultiValueConverter x:Key="multiValueConverter"/></Window.Resources><TextBox Text="{Binding Path=Price, Converter={StaticResource priceConverter}}"></TextBox>
</Window>
多重绑定
可以将多个字段绑定到同一个输出控件,可以通过 StringFormat 或 MultiBinding.Converter 来格式化数据。多重绑定的值转换器需要实现的接口是 IMultiValueConverter,与 IValueConverter 接口比较类似,只是转换函数的第一个参数改成了数组形式。
<TextBlock Grid.Row="4" Grid.Column="0"><TextBlock.Text><MultiBinding StringFormat="{}{0}, {1}, {2}"><Binding Path="Price"/><Binding Path="OrderDate"/><Binding Path="Volume"/></MultiBinding></TextBlock.Text></TextBlock><TextBlock Grid.Row="5" Grid.Column="0"><TextBlock.Text><MultiBinding Converter="{StaticResource multiValueConverter}"><Binding Path="Price"/><Binding Path="Volume"/></MultiBinding></TextBlock.Text></TextBlock>
public class MultiValueConverter : IMultiValueConverter
{public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture){decimal price = (decimal)values[0];int volume = (int)values[1];return (price * volume).ToString("C");}public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture){throw new NotSupportedException();}
}
完整代码如下:
MainWindow.xaml
<Window x:Class="TestDataConverter.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:TestDataConverter"mc:Ignorable="d"Title="MainWindow" Height="450" Width="800"><Window.Resources><local:PriceConverter x:Key="priceConverter"/><local:PriceToBackgroundConverter x:Key="priceToBackgroundConverter" MinimumPriceToHighlight="100" DefaultBrush="{x:Null}" HighlightBrush="Orange"/><local:ImagePathConverter x:Key="imagePathConverter"/><local:MultiValueConverter x:Key="multiValueConverter"/></Window.Resources><Grid Name="myGrid" Background="{Binding Path=Price, Converter={StaticResource priceToBackgroundConverter}}"><Grid.ColumnDefinitions><ColumnDefinition/><ColumnDefinition/></Grid.ColumnDefinitions><Grid.RowDefinitions><RowDefinition/><RowDefinition/><RowDefinition/><RowDefinition/><RowDefinition/><RowDefinition/></Grid.RowDefinitions><TextBlock Grid.Row="0" Grid.Column="0" Text="{Binding Path=Price, StringFormat=ConvertDirectly:{0:C}}"></TextBlock><TextBox Grid.Row="0" Grid.Column="1" Text="{Binding Path=Price, StringFormat={}{0:C}}"></TextBox><TextBlock Grid.Row="1" Grid.Column="0">ConvertWithConverter:</TextBlock><TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Path=Price, Converter={StaticResource priceConverter}}"></TextBox><TextBlock Grid.Row="2" Grid.Column="0">ConvertDateTime:</TextBlock><TextBox Grid.Row="2" Grid.Column="1" Text="{Binding Path=OrderDate, StringFormat={}{0:s}}"></TextBox><TextBlock Grid.Row="3" Grid.Column="0">ConvertImagePath:</TextBlock><Image Grid.Row="3" Grid.Column="1" Stretch="None" HorizontalAlignment="Left" Source="{Binding Path=Image, Converter={StaticResource imagePathConverter}}"></Image><TextBlock Grid.Row="4" Grid.Column="0"><TextBlock.Text><MultiBinding StringFormat="{}{0}, {1}, {2}"><Binding Path="Price"/><Binding Path="OrderDate"/><Binding Path="Volume"/></MultiBinding></TextBlock.Text></TextBlock><TextBlock Grid.Row="5" Grid.Column="0"><TextBlock.Text><MultiBinding Converter="{StaticResource multiValueConverter}"><Binding Path="Price"/><Binding Path="Volume"/></MultiBinding></TextBlock.Text></TextBlock></Grid>
</Window>
MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.IO;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Imaging;namespace TestDataConverter;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); }
}
[ValueConversion(typeof(decimal), typeof(string))]
public class PriceConverter : IValueConverter
{public object Convert(object value, Type targetType, object parameter, CultureInfo culture){decimal price = (decimal)value;return price.ToString("C", culture);}public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture){string price = (string)value;if (decimal.TryParse(price, System.Globalization.NumberStyles.Any, culture, out decimal result)){return result;}return value;}
}
[ValueConversion(typeof(decimal), typeof(Brush))]
public class PriceToBackgroundConverter : IValueConverter
{public decimal MinimumPriceToHighlight { get; set; }public Brush HighlightBrush { get; set; }public Brush DefaultBrush { get; set; }public object Convert(object value, Type targetType, object parameter,System.Globalization.CultureInfo culture){decimal price = (decimal)value;if (price >= MinimumPriceToHighlight)return HighlightBrush;elsereturn DefaultBrush;}public object ConvertBack(object value, Type targetType, object parameter,System.Globalization.CultureInfo culture){throw new NotSupportedException();}
}
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 MultiValueConverter : IMultiValueConverter
{public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture){decimal price = (decimal)values[0];int volume = (int)values[1];return (price * volume).ToString("C");}public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture){throw new NotSupportedException();}
}public partial class MainWindow : Window
{public MainWindow(){InitializeComponent();myGrid.DataContext = Order;Order.Price = 100;Order.Volume = 10;Order.OrderDate = DateTime.Now;Order.Image = "image1.gif";}public Order Order = new Order();private void Button_Click(object sender, RoutedEventArgs e){Console.WriteLine("");}
}
相关文章:
WPF数据转换
在基本绑定中,信息从源到目标的传递过程中没有任何变化。这看起来是符合逻辑的,但我们并不总是希望出现这种行为。通常,数据源使用的是低级表达方式,我们可能不希望直接在用户界面使用这种低级表达方式。WPF提供了两个工具&#x…...
《Go 语言第一课》课程学习笔记(十三)
方法 认识 Go 方法 Go 语言从设计伊始,就不支持经典的面向对象语法元素,比如类、对象、继承,等等,但 Go 语言仍保留了名为“方法(method)”的语法元素。当然,Go 语言中的方法和面向对象中的方…...
基于RUM高效治理网站用户体验入门-价值篇
用户体验 用户体验基本包含访问网站的性能、可用性和正确性。通俗的讲,就是一把通过用户访问测量【设计者】意图的尺子。 本文目的 网站如何传递出设计者的意图,可能页面加载时间太长、或者页面在用户的浏览器中渲染时间太慢,或者第三方设备…...
Unity之Photon PUN2开发多人游戏如何实现组队功能
前言 Photon Unity Networking 2 (PUN2) 是一款基于Photon Cloud的Unity多人游戏开发框架。它提供了一系列易于使用的API和工具,使开发者可以快速构建多人戏,并轻松处理多人游戏中的网络同步、房间管理、玩家匹配等问题。 我们在查看Pun2的Demo时,会发现Demo中自带了一个简…...
大数据Flink简介与架构剖析并搭建基础运行环境
文章目录 前言Flink 简介Flink 集群剖析Flink应用场景Flink基础运行环境搭建Docker安装docker-compose文件编写创建并运行容器访问Flink web界面 前言 前面我们分别介绍了大数据计算框架Hadoop与Spark,虽然他们有的有着良好的分布式文件系统和分布式计算引擎,有的有…...
RISC-V IOPMP实际用例-Rapid-k模型在NVIDIA上的应用
安全之安全(security)博客目录导读 2023 RISC-V中国峰会 安全相关议题汇总 说明:本文参考RISC-V 2023中国峰会如下议题,版权归原作者所有。...
【UE5】给模型指定面添加自定义材质
实现步骤 1. 首先我们向UE中导入一个简单的模型,可以看到目前该模型的材质插槽只有一个,当我们修改材质时会使得模型整体的材质全部改变,如果我们只想改变模型的某些面的材质就需要继续做后续操作。 2. 选择建模模式 3. 在模式工具栏中点击…...
mall:redis项目源码解析
文章目录 一、mall开源项目1.1 来源1.2 项目转移1.3 项目克隆 二、Redis 非关系型数据库2.1 Redis简介2.2 分布式后端项目的使用流程2.3 分布式后端项目的使用场景2.4 常见的缓存问题 三、源码解析3.1 集成与配置3.1.1 导入依赖3.1.2 添加配置3.1.3 全局跨域配置 3.2 Redis测试…...
RISC-V Linux系统kernel制作
文章目录 1、下载2、编译 1、下载 Linux 官网地址:https://www.kernel.org $ wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.10.181.tar.xz $ tar xvf linux-5.10.181.tar.xz $ cd linux-5.10.1812、编译 安装依赖 $ sudo apt-get install -y flex bison bui…...
5G NR:PRACH时域资源
PRACH occasion时域位置由高层参数RACH-ConfigGeneric->prach-ConfigurationIndex指示,根据小区不同的频域和模式,38.211的第6.3.3节中给出了prach-ConfigurationIndex所对应的表格。 小区频段为FR1,FDD模式(paired频谱)/SUL,…...
LLaMA-2的模型架构
输入token;[B, L] 输出probs:[B, L, vab_size]...
掌握Java框架之Struts,开启高效开发之旅!
当今的软件开发世界,Java框架如Struts已经成为构建企业级应用的重要工具。Struts作为一个流行的MVC框架,不仅简化了Java Web开发,还提高了软件的可维护性和可扩展性。本文将带你走进Struts的世界,探索其魅力所在,让你领…...
关于Vue.set()
简介 Vue.set() 是 Vue 中的一个全局方法,其主要作用是向响应式对象添加新的属性,并确保新属性同样具有响应式。在 Vue.js 中,当数据对象的属性被直接修改时,Vue 可以监测到数据变化并响应变化。但若添加新的响应式对象属性时&am…...
Selenium 遇见伪元素该如何处理?
问题发生 在很多前端页面中,大家会见到很多::before、::after 元素,比如【百度流量研究院】: 比如【百度疫情大数据平台】: 以【百度疫情大数据平台】为例,“累计确诊”文本并没有显示在 HTML 源代码中&am…...
RPA技术介绍与应用价值
一、什么是RPA技术? RPA(Robotic Process Automation)机器人流程自动化,是一种能够模拟人类来执行重复性任务的新型技术。RPA可实现统筹安排、自动化业务处理,并提升业务工作流处理效率。用户只需通过图形方式显示的计算机操作界面对RPA软件进行动态设定即可。借助RPA (R…...
产品经理,需要具备哪些能力和知识
作为产品经理,需要具备以下能力和知识: 产品管理能力:具备全面的产品管理能力,包括产品策划、需求分析、产品规划、产品设计、项目管理、市场调研和竞争分析等。 用户导向思维:能够理解用户需求和期望,以…...
【C++】map和set
map和set 文章目录 map和set关联式容器setset介绍set的函数测试代码 multiset注意事项测试代码 mapmap介绍map的函数测试代码 关联式容器 前面了解过的vector,list,string等容器都是序列式容器,存储的都是元素本身,底层都是线性的…...
crawlab通过docker单节点部署简单爬虫
crawlab 单节点docker安装 此处介绍的是单节点的方式,多节点的情况可以把爬虫上传到一个节点中,之后会同步到其它节点上 version: 3.3 services:master:image: crawlabteam/crawlabcontainer_name: crawlab_masterrestart: alwaysenvironment:CRAWLAB…...
【STM32】中断与NVIC以外部中断为例
前言 在stm32中姑且可以认为,异常就是中断 单片机上电之后,首先执行启动文件,开辟堆栈之后,开始初始化中断向量表。 NVIC NVIC NVIC是嵌套向量中断控制器,控制着整个芯片中断相关的功能,它跟内核紧密耦…...
大学生网页设计制作作业实例代码 (全网最全,建议收藏) HTML+CSS+JS
文章目录 📚web前端期末大作业 (1500套) 集合一、网页介绍二、网页集合 三、作品演示A电影主题B漫画主题C商城主题D家乡主题E旅游主题F餐饮/美食主题G环境主题H游戏主题I 个人主题K体育主题L博客主题M汽车主题N文化主题P美妆主题Q企业主题R教育主题S其他主题 &#…...
中国分县林地面积统计数据
一、数据简介 林地是指生长乔木、竹类、灌木及其他林业植物的土地,是陆地生态系统的重要组成部分,也是森林资源的核心载体。CnOpenData中国分县林地面积统计数据基于中国国土三调及国土年度变更调查汇总统计成果整合形成,包括全国、分省、分市…...
影刀RPA跨境店群运营架构:Python协同Chromium底层调度与高并发容器化实战
定了。在跨境电商自动化的技术角斗场里,我们终于打破了“商业指纹浏览器单机RPA”的低效垄断,实现了一套足以支撑万级店铺矩阵的分布式微服务调度架构。 这几天,科技圈被“DeepSeek V4 首发华为昇腾芯片,国产 AI 开始打破英伟达 …...
AI安全——实战敏感词汇绕过手法
一、前言 在今年大概 6 月份的时候,煮波在一些公众号以及 src 平台上看到了一个船新漏洞——AI 漏洞,后面更是看到了应运而生的所谓《ai 魔咒》,随着人工智能的兴起,一些学校或者机构或者平台都部署了 AI,有些 AI 虽然…...
大模型不再“一本正经地胡说八道”!揭秘RAG如何让AI「有据可查」
RAG(Retrieval-Augmented Generation)是一种结合信息检索与文本生成的AI架构,通过让大语言模型在回答问题前先查找外部知识库,有效缓解幻觉问题,并确保答案基于最新、专有数据。RAG通过文档切块、向量嵌入、向量检索和…...
抖音获客失效?拆解本地商家流量困局的底层逻辑与破局路径
一、一个反直觉的数据先看两组数据,它们指向同一个方向。第一组:2025年,抖音本地生活服务GMV突破8500亿元。同期,入驻商家达到1519.8万家动销门店,399万新商家在一年内涌入。第二组:2026年Q1,抖…...
《科技代替了我工作》的传播入口:技术焦虑如何落到听众
从内容传播角度看,《科技代替了我工作》有天然的现实入口,但写法必须克制。它不是技术教程,也不是政策评论,而是把技术变化落到一个普通人的饭碗、身份感和安全感上。这个标题容易被记住,因为它把宏大的技术词变成了第…...
2026 网络安全渗透测试行业报告|机遇与前景
随着数字化转型的深入和网络威胁的日益复杂化,网络安全渗透测试行业在2025年迎来了前所未有的发展机遇与挑战。本文基于最新行业数据、招聘趋势与技术演进,全面剖析当前渗透测试行业的市场规模、人才供需、薪资水平、技术变革及未来发展方向,…...
深入解析Android进程与线程间通信机制:原理、实践与优化
引言 在Android开发中,进程与线程间通信(IPC)是构建高性能、高稳定性应用的核心技术。无论是多进程协作(如系统服务、插件化框架)还是多线程并发(如UI线程与后台任务),高效的通信机制直接决定了应用的流畅性与资源利用率。本文将围绕Binder机制、Handler机制、共享内存…...
告别Excel!用Python复现地理探测器(附完整代码与示例数据)
告别Excel!用Python复现地理探测器(附完整代码与示例数据) 地理探测器作为分析空间分异性的重要工具,长期以来依赖Excel插件实现计算。但对于需要批量处理、自定义分析流程的研究者而言,这种封闭式操作存在明显局限。…...
第八篇:《软件测试的经济学:投入与回报》
在商业环境中,测试不是“免费”的——它需要人力、工具、时间。但缺陷也不是免费的——它可能导致损失、赔偿、用户流失。如何让管理者理解“投入测试是投资,而不是成本”?本文将从经济学角度分析测试的投资回报率(ROI)…...
