在IValueConverter 时"无法返回有效值该怎么做"。简述如下:
-
正确做法
- 返回 DependencyProperty.UnsetValue:表示"本次绑定无法提供值"。绑定引擎会将其视为绑定失败并尝试使用 Binding.FallbackValue;若未设置则目标使用属性默认值。
- 返回 Binding.DoNothing:表示"保持现状,不更新"。常用于 ConvertBack,防止把无效输入写回源。
- 返回 null:表示"明确把值设为 null"。若设置了 TargetNullValue,则会用 TargetNullValue 进行显示。
- 抛出异常:仅在需要参与校验时使用,配合 ValidatesOnExceptions。否则会产生绑定错误与日志噪音。
-
选用建议
- Convert(源→目标)失败:优先返回 UnsetValue;不想改变现有 UI 时可用 DoNothing。
- ConvertBack(目标→源)解析失败:优先返回 DoNothing;若要清空源返回 null;极少数场景才抛异常参与校验。
示例
XAML:演示 UnsetValue、DoNothing、null、异常配合校验
xml
<UserControl x:Class="H.Test.DataGrid.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:H.Test.DataGrid">
<UserControl.Resources>
<local:UnsetValueDemoConverter x:Key="Conv"/>
</UserControl.Resources>
<StackPanel Margin="12" Orientation="Vertical" Spacing="8">
<!-- 源→目标:当值非法时,Converter 返回 UnsetValue,使用 FallbackValue -->
<TextBlock Text="{Binding Amount,
Converter={StaticResource Conv},
ConverterParameter=ToText,
FallbackValue=(无数据)}"/>
<!-- 目标→源:用户输入解析失败时,返回 DoNothing,避免写回源 -->
<TextBox Text="{Binding Amount,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged,
Converter={StaticResource Conv},
ConverterParameter=ToNumber}"
ToolTip="输入数字;非法输入不会写回源"/>
<!-- 目标→源:返回 null(清空源)或抛异常参与校验 -->
<TextBox>
<TextBox.Text>
<Binding Path="Name" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged"
Converter="{StaticResource Conv}" ConverterParameter=ToName
ValidatesOnExceptions="True" />
</TextBox.Text>
</TextBox>
</StackPanel>
</UserControl>
C#:Converter 实现
csharp
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace H.Test.DataGrid
{
public sealed class UnsetValueDemoConverter : IValueConverter
{
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
var mode = parameter as string;
if (mode == "ToText")
{
// 非法源值:返回 UnsetValue,触发 FallbackValue 或使用目标属性默认值
if (value is null) return DependencyProperty.UnsetValue;
return $"金额:{value}";
}
return value;
}
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
var s = value as string ?? string.Empty;
var mode = parameter as string;
if (mode == "ToNumber")
{
// 解析失败:保持源不变
if (!double.TryParse(s, out var d)) return Binding.DoNothing;
return d;
}
if (mode == "ToName")
{
if (string.Equals(s, "null", StringComparison.OrdinalIgnoreCase))
return null; // 明确把源设为 null(可配合 TargetNullValue 展示)
if (s.Length > 20)
throw new FormatException("名称过长"); // 配合 ValidatesOnExceptions 产生校验错误
return s;
}
return value;
}
}
}
要点对比
- DependencyProperty.UnsetValue:表示"本次无值";触发 FallbackValue;不算异常,不会自动进入校验。
- Binding.DoNothing:什么也不做;目标或源保持当前值,常用于 ConvertBack。
- null:真正传递 null;可触发 TargetNullValue。
- 异常:用于校验错误,需 ValidatesOnExceptions 才会把错误挂到 Validation。
文档
- IValueConverter | Microsoft Learn
- DependencyProperty.UnsetValue | Microsoft Learn
- Binding.DoNothing | Microsoft Learn
- BindingBase.FallbackValue | Microsoft Learn
- BindingBase.TargetNullValue | Microsoft Learn
- Validation(校验)| Microsoft Learn
了解更多
System.Windows.Controls 命名空间 | Microsoft Learn
控件库 - WPF .NET Framework | Microsoft Learn
使用 Visual Studio 创建新应用教程 - WPF .NET | Microsoft Learn
HeBianGu的个人空间-HeBianGu个人主页-哔哩哔哩视频