如果绑定 属性 为空,C# WPF 绑定转换器不会触发
C# WPF Binding Converter not firing if bound property is null
我目前在使用 WPF MVVM 数据绑定时遇到了一个奇怪的问题。
我们的想法是使用 ValueConverter,如果它不为空则显示绑定值,否则显示 ConverterParameter
中定义的字符串。
Person
class 具有以下属性:Name (string)
、Surname (string)
、Country (class)
.
Country
class 具有以下属性:CountryName (string)
.
当 TextBlock 绑定到 Person.Country.CountryName
且 Person.Country
为空时,IValueConverter
的使用失败 。 IValueConverter
方法 Convert
甚至不触发 来检查绑定值是否为 null。
同时 IMultiValueConverter
工作得很好,无论 Person.Country
是否为空,每次都会触发。
思路为什么会这样?尝试搜索任何 Microsoft 文章,但一无所获。
感谢任何帮助。
源 GitHub 项目可在此处找到:https://github.com/kevintw86/WpfBindingConverterIssue.git
绑定到 IValueConverter(当 Person.Country==null 时无法正常工作):
<TextBlock
Text="{Binding Person.Country.CountryName,
UpdateSourceTrigger=PropertyChanged,
Converter={StaticResource PersonConverter},
ConverterParameter=- Not set -}"
FontSize="16"/>
个人转换器:
public class PersonConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
return parameter;
if (value == DependencyProperty.UnsetValue)
return parameter;
if (string.IsNullOrWhiteSpace(value.ToString()))
return parameter;
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
绑定到 IMultiValueConverter(即使 Person.Country==null 也能正常工作):
<TextBlock FontSize="16">
<TextBlock.Text>
<MultiBinding Converter="{StaticResource PersonMultiConverter}"
ConverterParameter="- Not set -">
<MultiBinding.Bindings>
<Binding Path="Person.Country.CountryName"
UpdateSourceTrigger="PropertyChanged"/>
</MultiBinding.Bindings>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
PersonMultiConverter:
public class PersonMultiConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values == null)
return parameter;
if (values[0] == DependencyProperty.UnsetValue)
return parameter;
if (values[0] == null)
return parameter;
if (string.IsNullOrWhiteSpace(values[0].ToString()))
return parameter;
return values[0];
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
人class:
public class Person : INotifyPropertyChanged
{
private string _Name;
public string Name
{
get { return _Name; }
set
{
_Name = value;
OnPropertyChanged();
}
}
private string _Surname;
public string Surname
{
get { return _Surname; }
set
{
_Surname = value;
OnPropertyChanged();
}
}
private Country _Country;
public Country Country
{
get { return _Country; }
set
{
_Country = value;
OnPropertyChanged();
}
}
#region INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string prop = "")
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(prop));
}
#endregion
}
国家class:
public class Country : INotifyPropertyChanged
{
private string _CountryName;
public string CountryName
{
get { return _CountryName; }
set
{
_CountryName = value;
OnPropertyChanged();
}
}
#region INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string prop = "")
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(prop));
}
#endregion
}
MainWindowViewModel:
public class MainWindowViewModel : INotifyPropertyChanged
{
public MainWindowViewModel()
{
this.Person = new Person
{
Name = "John",
Surname = null,
Country = null,
};
}
#region Properties
private Person _Person;
public Person Person
{
get { return _Person; }
set
{
_Person = value;
OnPropertyChanged();
}
}
#endregion
#region INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string prop = "")
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(prop));
}
#endregion
}
考虑使用 TargetNullValue and FallbackValue 而不是转换器:
<TextBlock
Text="{Binding Person.Country.CountryName,
TargetNullValue='- Not set -',
FallbackValue='- Not set -'}"
我目前在使用 WPF MVVM 数据绑定时遇到了一个奇怪的问题。
我们的想法是使用 ValueConverter,如果它不为空则显示绑定值,否则显示 ConverterParameter
中定义的字符串。
Person
class 具有以下属性:Name (string)
、Surname (string)
、Country (class)
.
Country
class 具有以下属性:CountryName (string)
.
当 TextBlock 绑定到 Person.Country.CountryName
且 Person.Country
为空时,IValueConverter
的使用失败 。 IValueConverter
方法 Convert
甚至不触发 来检查绑定值是否为 null。
同时 IMultiValueConverter
工作得很好,无论 Person.Country
是否为空,每次都会触发。
思路为什么会这样?尝试搜索任何 Microsoft 文章,但一无所获。
感谢任何帮助。
源 GitHub 项目可在此处找到:https://github.com/kevintw86/WpfBindingConverterIssue.git
绑定到 IValueConverter(当 Person.Country==null 时无法正常工作):
<TextBlock
Text="{Binding Person.Country.CountryName,
UpdateSourceTrigger=PropertyChanged,
Converter={StaticResource PersonConverter},
ConverterParameter=- Not set -}"
FontSize="16"/>
个人转换器:
public class PersonConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
return parameter;
if (value == DependencyProperty.UnsetValue)
return parameter;
if (string.IsNullOrWhiteSpace(value.ToString()))
return parameter;
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
绑定到 IMultiValueConverter(即使 Person.Country==null 也能正常工作):
<TextBlock FontSize="16">
<TextBlock.Text>
<MultiBinding Converter="{StaticResource PersonMultiConverter}"
ConverterParameter="- Not set -">
<MultiBinding.Bindings>
<Binding Path="Person.Country.CountryName"
UpdateSourceTrigger="PropertyChanged"/>
</MultiBinding.Bindings>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
PersonMultiConverter:
public class PersonMultiConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values == null)
return parameter;
if (values[0] == DependencyProperty.UnsetValue)
return parameter;
if (values[0] == null)
return parameter;
if (string.IsNullOrWhiteSpace(values[0].ToString()))
return parameter;
return values[0];
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
人class:
public class Person : INotifyPropertyChanged
{
private string _Name;
public string Name
{
get { return _Name; }
set
{
_Name = value;
OnPropertyChanged();
}
}
private string _Surname;
public string Surname
{
get { return _Surname; }
set
{
_Surname = value;
OnPropertyChanged();
}
}
private Country _Country;
public Country Country
{
get { return _Country; }
set
{
_Country = value;
OnPropertyChanged();
}
}
#region INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string prop = "")
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(prop));
}
#endregion
}
国家class:
public class Country : INotifyPropertyChanged
{
private string _CountryName;
public string CountryName
{
get { return _CountryName; }
set
{
_CountryName = value;
OnPropertyChanged();
}
}
#region INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string prop = "")
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(prop));
}
#endregion
}
MainWindowViewModel:
public class MainWindowViewModel : INotifyPropertyChanged
{
public MainWindowViewModel()
{
this.Person = new Person
{
Name = "John",
Surname = null,
Country = null,
};
}
#region Properties
private Person _Person;
public Person Person
{
get { return _Person; }
set
{
_Person = value;
OnPropertyChanged();
}
}
#endregion
#region INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string prop = "")
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(prop));
}
#endregion
}
考虑使用 TargetNullValue and FallbackValue 而不是转换器:
<TextBlock
Text="{Binding Person.Country.CountryName,
TargetNullValue='- Not set -',
FallbackValue='- Not set -'}"