在 WPF(Windows Presentation Foundation)中,Converter(转换器) 是实现 数据绑定(Data Binding) 时对源数据和目标 UI 元素之间进行值转换 的关键机制。它通过实现 IValueConverter(单向/双向)或 IMultiValueConverter(多绑定)接口,让你可以灵活控制数据如何显示或如何从用户输入反向更新。
📌 一、为什么需要 Converter?
WPF 数据绑定要求源属性和目标属性类型兼容。但现实中经常遇到:
- 布尔值 → 控件可见性(
true→Visible,false→Collapsed) - 数字 → 颜色(如:0~100 分数 → 红/黄/绿)
- 枚举值 → 图标或文本
- 空字符串 → 占位符文本
这时就需要 Converter 来"翻译"数据。
🧱 二、核心接口
1. IValueConverter(最常用)
csharp
public interface IValueConverter
{
object Convert(object value, Type targetType, object parameter, CultureInfo culture);
object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture);
}
Convert:从 数据源 → UI (例如:ViewModel 的bool IsOnline→ UI 的Visibility)ConvertBack:从 UI → 数据源 (例如:用户输入的文本 → ViewModel 的DateTime)
⚠️ 如果只用于显示(OneWay 绑定),可只实现
Convert,ConvertBack抛出NotImplementedException。
2. IMultiValueConverter
用于 MultiBinding,将多个输入值合并为一个输出值。
csharp
public interface IMultiValueConverter
{
object Convert(object[] values, Type targetType, object parameter, CultureInfo culture);
object[,] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture);
}
🛠 三、实战示例
✅ 示例 1:布尔值 → 可见性(BooleanToVisibilityConverter)
WPF 内置了这个转换器,但我们可以自己实现一个更灵活的版本:
csharp
// BooleanToVisibilityConverter.cs
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
public class BooleanToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is bool boolValue)
{
// 支持取反:当 Parameter="invert" 时,true→Collapsed
bool invert = parameter?.ToString()?.ToLower() == "invert";
bool result = invert ? !boolValue : boolValue;
return result ? Visibility.Visible : Visibility.Collapsed;
}
return Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is Visibility visibility)
{
bool invert = parameter?.ToString()?.ToLower() == "invert";
bool isVisible = visibility == Visibility.Visible;
return invert ? !isVisible : isVisible;
}
return false;
}
}
在 XAML 中使用:
xml
<Window x:Class="MyApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyApp.Converters">
<Window.Resources>
<local:BooleanToVisibilityConverter x:Key="BoolToVis"/>
</Window.Resources>
<StackPanel>
<TextBlock Text="在线状态:" />
<TextBlock Text="✅ 在线"
Visibility="{Binding IsOnline, Converter={StaticResource BoolToVis}}"/>
<TextBlock Text="❌ 离线"
Visibility="{Binding IsOnline, Converter={StaticResource BoolToVis}, ConverterParameter=invert}"/>
</StackPanel>
</Window>
✅ 示例 2:数值 → 颜色(分数评级)
csharp
public class ScoreToColorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is double score)
{
if (score >= 90) return Brushes.Green;
if (score >= 60) return Brushes.Orange;
return Brushes.Red;
}
return Brushes.Gray;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException(); // 只用于显示
}
}
XAML 使用:
xml
<Window.Resources>
<local:ScoreToColorConverter x:Key="ScoreToColor"/>
</Window.Resources>
<TextBlock Text="{Binding StudentScore}"
Foreground="{Binding StudentScore, Converter={StaticResource ScoreToColor}}"/>
✅ 示例 3:空值/空字符串 → 占位符文本
csharp
public class NullToPlaceholderConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
string input = value as string;
string placeholder = parameter as string ?? "(未填写)";
return string.IsNullOrWhiteSpace(input) ? placeholder : input;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
string input = value as string;
return string.IsNullOrWhiteSpace(input) ? null : input;
}
}
XAML:
xml
<TextBlock Text="{Binding UserName, Converter={StaticResource NullToPlaceholder}, ConverterParameter='请输入姓名'}"/>
✅ 示例 4:多值转换(IMultiValueConverter)------ 拼接姓名
csharp
public class FullNameConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
string firstName = values[0] as string ?? "";
string lastName = values[1] as string ?? "";
return $"{firstName} {lastName}".Trim();
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
string fullName = value as string;
var parts = fullName?.Split(' ', 2) ?? new string[2];
return new object[] { parts.FirstOrDefault(), parts.Skip(1).FirstOrDefault() };
}
}
XAML:
xml
<Window.Resources>
<local:FullNameConverter x:Key="FullNameConv"/>
</Window.Resources>
<TextBlock>
<TextBlock.Text>
<MultiBinding Converter="{StaticResource FullNameConv}">
<Binding Path="FirstName"/>
<Binding Path="LastName"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
📦 四、最佳实践
| 建议 | 说明 |
|---|---|
| Converter 设为静态资源 | 避免重复创建实例,提升性能 |
支持 ConverterParameter |
增强复用性(如是否取反、格式字符串等) |
| 处理 null 和类型不匹配 | 防止运行时异常 |
| 文化信息(CultureInfo) | 处理本地化(如日期、货币格式) |
| 避免复杂逻辑 | Converter 应轻量,复杂逻辑放 ViewModel |
🔧 五、WPF 内置常用 Converter
WPF 自带一些转换器,位于 System.Windows.Controls 或通过资源引用:
BooleanToVisibilityConverter(需手动添加到资源)ObjectDataProvider(间接实现转换)- 但大多数场景仍需自定义。
注意:
BooleanToVisibilityConverter虽然存在,但不会自动生效,必须在资源中声明:
xml
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVis"/>
</Window.Resources>
✅ 总结
| 功能 | 实现方式 |
|---|---|
| 单值转换 | IValueConverter + {Binding Converter=...} |
| 多值转换 | IMultiValueConverter + <MultiBinding> |
| 参数传递 | ConverterParameter |
| 双向绑定 | 同时实现 Convert 和 ConvertBack |
Converter 是 WPF 数据绑定体系中实现"表现与逻辑分离"的重要桥梁,合理使用能让 UI 更灵活、代码更清晰。