如果绑定属性为空,则C# WPF绑定转换器不触发

afdcj2ne  于 2023-05-01  发布在  C#
关注(0)|答案(1)|浏览(133)

我目前在使用WPF MVVM数据绑定时遇到了一个奇怪的问题。
这个想法是使用ValueConverter,如果它不是null,则显示绑定值,否则显示ConverterParameter中定义的字符串。
Person类,具有以下属性:Name (string)Surname (string)Country (class)
Country类具有以下属性:CountryName (string)
如果Person.Country为null,则TextBlock绑定到Person.Country.CountryName时,IValueConverter使用失败IValueConverter方法Convert甚至不触发来检查绑定值是否为null。
同时IMultiValueConverter工作得很好,无论Person.Country是否为null,每次都会触发。
为什么会这样呢?已尝试搜索任何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"/>

PersonConverter:

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();
        }
    }

人员类别:

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
}

国家类别:

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
}

主窗口视图模型:

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
}
kjthegm6

kjthegm61#

考虑使用TargetNullValueFallbackValue代替转换器:

<TextBlock 
      Text="{Binding Person.Country.CountryName, 
      TargetNullValue='- Not set -', 
      FallbackValue='- Not set -'}"

相关问题