讲师中心 微信公众号
AI工具推荐 视频效率加速

[UWP]了解IValueConverter

陌敏同学_3713

陌敏同学_3713

发布时间:2025-09-06 09:14:17

|

270人浏览过

|

来源于php中文网

原创

  1. 前言

ivalueconverter是数据绑定中的强大工具,用于在binding source和binding target之间转换值。本文将详细介绍ivalueconverter的使用方法及一些常见的实现。

  1. 为什么要使用IValueConverter

假设有一个名为TestResult的类:

public class TestResult
{
    public bool Passed { get; set; }
}

UI需要根据Passed属性的值来决定结果文本的颜色是红色还是绿色。初学者通常会通过修改TestResult类,添加一个与Passed相关的属性来实现:

public class TestResult
{
    public bool Passed { get; set; }
    public Brush TestResultBrush
    {
        get
        {
            if (Passed)
                return new SolidColorBrush(Colors.Red);
            else
                return new SolidColorBrush(Colors.Green);
        }
    }
}

然后在XAML中绑定到这个属性:

<textblock foreground="{Binding TestResultBrush}" text="Score : 60"></textblock>

另一种方法是直接在Code Behind中为TextBlock更改Foreground:

var testResult = DataContext as TestResult;
if (testResult != null)
{
    if (testResult.Passed)
        ResultElement.Foreground = new SolidColorBrush(Colors.Red);
    else
        ResultElement.Foreground = new SolidColorBrush(Colors.Green);
}

这两种方法都不够优雅,会带来一系列问题:破坏了TestResult的结构,违反了开放封闭原则,导致UI和数据过度耦合,存在过多的硬编码等。

在这种情况下,通常可以使用IValueConverter来处理。在Binding中,IValueConverter可以将数据在呈现前转换为新的目标值。实现IValueConverter需要执行以下步骤:

  • 创建一个实现了IValueConverter接口的类;
  • 实现
    public object Convert(object value, Type targetType, object parameter, string language)
    方法,该方法将数据转换为新目标值;
  • 实现
    public object ConvertBack(object value, Type targetType, object parameter, string language)
    方法,该方法执行反向转换,仅在使用双向绑定时需要实现。

在这个例子中,IValueConverter的目的是将bool类型的Passed转换为Brush,实现如下:

public class BoolToBrushConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        if (value is bool passed)
            return new SolidColorBrush(passed ? Colors.Green : Colors.Red);
        return null;
    }
    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        throw new NotImplementedException();
    }
}

在XAML中使用这个Converter需要先将其定义为Resource,然后在Binding中指定Converter到这个已定义的Resource:

<grid background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <grid.resources>
        <booltobrushconverter x:key="BoolToBrushConverter"></booltobrushconverter>
    </grid.resources>
    <textblock foreground="{Binding Passed,Converter={StaticResource BoolToBrushConverter}}" text="Score : 60"></textblock>
</grid>
  1. BoolToValueConverter

在XAML的漫长历史中,IValueConverter衍生出了一些奇妙的技巧,其中最常用的是BoolToValueConverter。

public class BoolToValueConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        if (value == null || (bool) value == false)
            return DependencyProperty.UnsetValue;
        return parameter;
    }
    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        return Equals(value, parameter);
    }
}

BoolToValueConverter灵活使用了Binding中的ConverterParameter和FallbackValue两个参数,常用于解决IValueConverter中硬编码的问题。在Binding中,FallbackValue指明了如果Binding无法返回任何值时使用的值,在IValueConverter中返回DependencyProperty.UnsetValue即告诉Binding要使用FallbackValue的值。

使用BoolToValueConverter解决了上述例子的硬编码问题,在XAML中使用如下:

<grid>
    <grid.resources>
        <booltovalueconverter x:key="BoolToValueConverter"></booltovalueconverter>
    </grid.resources>
    <textblock foreground="{Binding Passed,Converter={StaticResource BoolToValueConverter},ConverterParameter=Green,FallbackValue=Red}" text="Score : 60"></textblock>
</grid>
  1. BoolToObjectConverter

需要注意的是,上述XAML中的Green和Red只是字符串,它们最终能被解析成SolidColorBrush是由于TypeConverter的支持。也就是说,上述XAML语法只能用于TypeConverter支持的数据类型,而且这种写法仍然过于硬编码。如果要支持复杂类型或本地化等问题,可以将ConverterParameter和FallbackValue绑定到StaticResource:

<grid.resources>
    <solidcolorbrush color="Green" x:key="PassedBrush"></solidcolorbrush>
    <solidcolorbrush color="Red" x:key="FailedBrush"></solidcolorbrush>
    <booltovalueconverter x:key="BoolToValueConverter"></booltovalueconverter>
</grid.resources>
<textblock foreground="{Binding Passed,Converter={StaticResource BoolToValueConverter},ConverterParameter={StaticResource PassedBrush},FallbackValue={StaticResource FailedBrush}}" text="Score : 60"></textblock>

尽管这种方法看似很灵活,但如果有大量返回相同值的BoolToValueConverter,将会使XAML产生大量冗余。UWP Community Toolkit提供了一些常用的IValueConverter实现,其中最常用的是BoolToObjectConverter。BoolToObjectConverter和BoolToValueConverter功能类似,但它提供了

public object TrueValue { get; set; }
和
public object FalseValue { get; set; }
两个属性,而且这两个属性是依赖属性,可以使用绑定为其赋值。使用如下:

<grid.resources>
    <solidcolorbrush color="Green" x:key="PassedBrush"></solidcolorbrush>
    <solidcolorbrush color="Red" x:key="FailedBrush"></solidcolorbrush>
    <booltoobjectconverter falsevalue="{StaticResource FailedBrush}" truevalue="{StaticResource PassedBrush}" x:key="BoolToObjectConverter"></booltoobjectconverter>
</grid.resources>
<textblock foreground="{Binding Passed,Converter={StaticResource BoolToObjectConverter}}" text="Score : 60"></textblock>
  1. BoolToVisibilityConverter

UWP Community Toolkit中提供了另一个常用的Converter:BoolToVisibilityConverter。这个Converter只是简单地继承了BoolToObjectConverter,并且为TrueValue和FalseValue设置了默认值:

public BoolToVisibilityConverter()
{
    TrueValue = Visibility.Visible;
    FalseValue = Visibility.Collapsed;
}

BoolToVisibilityConverter虽然简单,但确实好用。不过,从1607版本之后就不需要这个Converter了,微软是这样说的。

但有时候反而需要True对应Collapsed,于是现在是另一个常用Converter - BoolNegationConverter登上历史舞台的时候了:

<stackpanel>
    <stackpanel.resources>
        <boolnegationconverter x:key="BoolNegationConverter"></boolnegationconverter>
    </stackpanel.resources>
    <textblock foreground="Green" text="Passed" visibility="{Binding Passed}"></textblock>
    <textblock foreground="Red" text="Failed" visibility="{Binding Passed,Converter={StaticResource BoolNegationConverter}}"></textblock>
</stackpanel>
  1. StringFormatConverter

UWP的Binding缺少了StringFormat,这对Binding产生了很大影响。为了弥补这个缺陷,可以使用UWP Community Toolkit中的StringFormatConverter。它的代码也十分简单(其实这才是ConverterParameter的正确用法):

public object Convert(object value, Type targetType, object parameter, string language)
{
    if (value == null)
    {
        return null;
    }
    if (parameter == null)
    {
        return value;
    }
    return string.Format((string)parameter, value);
}

在XAML中使用如下:

<textblock text="{Binding DoubleValue,Converter={StaticResource StringFormatConverter},ConverterParameter='{}{0:N2}'}"></textblock>
<textblock text="{Binding DoubleValue,Converter={StaticResource StringFormatConverter},ConverterParameter='There are {0:N0} Items'}"></textblock>

结果如下:

[UWP]了解IValueConverter

除了弥补StringFormat的功能,StringFormatConverter还有其他应用场景。

TestModel.CS

public IEnumerable<clickmode> ClickModes => new List<clickmode> { ClickMode.Hover, ClickMode.Press, ClickMode.Release };
<listbox itemssource="{Binding ClickModes}">
    <listbox.itemtemplate>
        <datatemplate>
            <textblock text="{Binding }"></textblock>
        </datatemplate>
    </listbox.itemtemplate>
</listbox>
<listbox itemssource="{Binding ClickModes}"></listbox>

在WPF中,以上XAML都可以正常呈现,而在UWP中,以上XAML显示如下:

[UWP]了解IValueConverter

windows-healing-gateway
windows-healing-gateway

通过任务计划程序自动监控并自修复 Windows 上的 OpenClaw Gateway,具备 AI 诊断和 Telegram 报警功能。

下载

这种情况可以使用StringFormatConverter显示枚举的名称:

<listbox itemssource="{Binding ClickModes}">
    <listbox.itemtemplate>
        <datatemplate>
            <textblock text="{Binding Converter={StaticResource StringFormatConverter}}"></textblock>
        </datatemplate>
    </listbox.itemtemplate>
</listbox>

[UWP]了解IValueConverter

可以说对UWP来说,StringFormatConverter十分必要。

  1. language参数

public object Convert(object value, Type targetType, object parameter, string language)
方法中的参数language通常用于本地化,例如可以创建一个DateTimeValueConverter:

public class DateTimeValueConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        if (value is DateTime dateTime)
        {
            var culture = new CultureInfo(language);
            return dateTime.ToString(culture.DateTimeFormat);
        }
        return value;
    }
    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        throw new NotImplementedException();
    }
}
<textblock text="{Binding Date,Converter={StaticResource DateTimeValueConverter},ConverterLanguage=en-US}"></textblock>
<textblock text="{Binding Date,Converter={StaticResource DateTimeValueConverter},ConverterLanguage=zh-CN}"></textblock>

结果如下:

[UWP]了解IValueConverter

  1. targetType参数

targetType参数指转换后的目标类型,使用这个参数可以实现一个简单的Value Converter:

public class ValueConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, string language)
    {
        return System.Convert.ChangeType(value, targetType);
    }
    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        throw new NotImplementedException();
    }
}

虽然代码简单,但它可以解决不少问题,例如《了解TypeConverter》这篇文章里提到的不能在XAML中使用decimal的问题。IValueConverter要起作用依赖于BindingSource,而在XAML中虽然很多东西都可以用来做BindingSource,例如用元素自己的Tag:

<mycontentcontrol amount="{Binding Converter={StaticResource ValueConverter},Path=Tag,RelativeSource={RelativeSource Mode=Self}}" tag="10.01"></mycontentcontrol>

或者Resources中的字符串:

<grid.resources>
    <string x:key="DecimalString">10.01</string>
</grid.resources>
<mycontentcontrol amount="{Binding Source={StaticResource DecimalString},Converter={StaticResource ValueConverter}}"></mycontentcontrol>

或者更进一步写一个字符串的包装类:

public class StringWrapper
{
    public string this[string key]
    {
        get
        {
            return key;
        }
    }
}
<mycontentcontrol amount="{Binding [10.01],Source={StaticResource StringWrapper},Converter={StaticResource ValueConverter}}"></mycontentcontrol>
  1. 使用IValueConverter的其它经验

9.1 统一管理IValueConverter

由于大部分IValueConverter行为是固定的,通常我都会把常用的IValueConverter放到一个Converters.xaml,然后在App.xaml中合并资源字典,这样不用重复写创建Converter的xaml,也避免了重复创建Converter的资源消耗:

<application.resources>
    <resourcedictionary>
        <resourcedictionary.mergeddictionaries>
            <resourcedictionary source="Converters.xaml"></resourcedictionary>
        </resourcedictionary.mergeddictionaries>
    </resourcedictionary>
</application.resources>

9.2 格式化

[UWP]了解IValueConverter

Binding最让人诟病的缺点就是它的语法太长,例如以上两个TextBlock,在IDE中很难判断它们有什么不同。很多时候我都会把XAML的格式化设置成“将每个属性分行放置”,如下图:

[UWP]了解IValueConverter

这样上面两个TextBlock的XAML就清晰许多了:

[UWP]了解IValueConverter

不过这样设置也并不全是好处,怎么设置具体还是看个人喜好和屏幕尺寸。

  1. 结语

虽然IValueConverter的文章已经不少了,但还是常常见到乱来的IValueConverter实现,而且UWP的IValueConverter有一些改变,所以还是写了这篇文章。

我很想写一些常用的,或者容易用错的基础知识,但连IValueConverter都不知不觉就写得这么长了,实在没勇气写Binding的概念,何况关于Binding已经有很多很实用的文章。

我十分清楚文章写得太长就会被“保存到Pocket”,我也想每篇文章都能在三五分钟内看完,但偏偏越基础的概念就越能写得长,而且写得简短些又会被移出博客园首页,很难把握尺度。

下一篇文章会尽量写短一些。

  1. 参考
  • IValueConverter Interface
  • Binding Class
  • 深入了解数据绑定
  • Converters - UWP Community Toolkit _ Microsoft Docs

热门AI工具

更多
VibeKnow
VibeKnow Hot

一款AI视频创作工具,主要用于全球首个AI知识视频创作平台,文档、文章、网页,一键生成视频,适合需要提升相关任务效率的用户。

LibLibAI
LibLibAI Hot

一款AI视频创作工具,主要用于国内领先的AI创意平台,以海量模型、低门槛操作与“创作-分享-商业化”生态,让小白与专业创作者都能高效实现图文乃至视频创意表达,适合需要提升相关任务效率的用户。

Loomy
Loomy Hot

一款AI工具,主要用于科大讯飞发布的桌面级 AI 助理,比 OpenClaw 更易用、更安全!,适合需要提升相关任务效率的用户。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

AionClaw
AionClaw Hot

AionClaw是一款面向办公、创作和编程任务的AI桌面智能体。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

墨刀AI
墨刀AI Hot

一款AI图像与设计工具,主要用于产品经理的专属智能体,适合需要提升相关任务效率的用户。

讯飞绘文

讯飞绘文是一款由科大讯飞推出的一站式 AIGC 内容运营平台。

相关专题

更多
数据类型有哪几种
数据类型有哪几种

数据类型有整型、浮点型、字符型、字符串型、布尔型、数组、结构体和枚举等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2391

2023.10.31

php数据类型
php数据类型

本专题整合了php数据类型相关内容,阅读专题下面的文章了解更多详细内容。

494

2025.10.31

c语言 数据类型
c语言 数据类型

本专题整合了c语言数据类型相关内容,阅读专题下面的文章了解更多详细内容。

422

2026.02.12

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

5179

2023.08.02

resource是什么文件
resource是什么文件

Resource文件是一种特殊类型的文件,它通常用于存储应用程序或操作系统中的各种资源信息。它们在应用程序开发中起着关键作用,并在跨平台开发和国际化方面提供支持。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

320

2023.12.20

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

1538

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

2224

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

5724

2023.10.24

Buffalo框架数据库开发全教程
Buffalo框架数据库开发全教程

本专题围绕Buffalo框架数据库开发,讲解database.yml多环境配置、soda与fizz迁移生成回滚、模型结构体标签、增删改查与条件查询、一对多与多对多关联、数据校验、回调钩子、事务处理及原生SQL执行能力。

20

2026.09.23

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Buffalo框架快速入门指南
Buffalo框架快速入门指南

共0课时 | 0人学习

Conan 2 安装指南
Conan 2 安装指南

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn