当前位置:  开发笔记 > 编程语言 > 正文

WPF数据绑定和IValueConverter

如何解决《WPF数据绑定和IValueConverter》经验,为你挑选了2个好方法。

为什么当我在WPF中的绑定表达式中使用转换器时,在更新数据时不会更新该值.

我有一个简单的Person数据模型:

class Person : INotifyPropertyChanged
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

我的绑定表达式如下所示:


我的转换器看起来像这样:

class PersonNameConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        Person p = value as Person;
        return p.FirstName + " " + p.LastName;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

如果我在没有转换器的情况下绑定数据,那么效果很好



我错过了什么?

编辑:只是为了澄清一些事情,Joel和Alan对于需要实现的INotifyPropertyChanged接口都是正确的.实际上我确实实现了它,但它仍然无效.

我不能使用多个TextBlock元素,因为我正在尝试将Window Title绑定到全名,而Window Title不会使用模板.

最后,可以选择添加复合属性"FullName"并绑定到它,但我仍然想知道为什么绑定使用转换器时不会发生更新.即使我在转换器代码中设置了一个断点,当对底层数据进行更新时,调试器也无法实现:-(

谢谢,乌里



1> Arcturus..:

您还可以使用MultiBinding ..绑定到Person对象,FirstName和LastName.这样,只要FirstName或LastName抛出属性更改事件,该值就会更新.


    
    
    

或者,如果您只使用FirstName和LastName,则将Person对象从绑定中剥离为以下内容:


    
    

MultiValueConverter看起来像这样:

class PersonNameConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
            return values[0].ToString() + " " + values[1].ToString();
    }

    public object ConvertBack(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
            throw new NotImplementedException();
    }
}

但是,当然,所选答案也可以,但MultiBinding的工作更优雅......



2> Joel B Fant..:

(见下面的编辑;最新:#2)

它没有更新,因为您的Person对象无法通知任何值FirstNameLastName已更改的内容.看到这个问题.

以下是您的实施方式INotifyPropertyChanged.(更新,请参阅编辑2)

using System.ComponentModel;

class Person : INotifyPropertyChanged {
    public event PropertyChangedEventHandler PropertyChanged;

    string _firstname;
    public string FirstName {
        get {
            return _firstname;
        }
        set {
            _firstname = value;
            onPropertyChanged( "FirstName", "FullName" );
        }
    }

    string _lastname;
    public string LastName {
        get {
            return _lastname;
        }
        set {
            _lastname = value;
            onPropertyChanged( "LastName", "FullName" );
        }
    }

    public string FullName {
        get {
            return _firstname + " " + _lastname;
        }
    }

    void onPropertyChanged( params string[] propertyNames ) {
        PropertyChangedEventHandler handler = PropertyChanged;

        if ( handler != null ) {
            foreach ( var pn in propertyNames ) {
                handler( this, new PropertyChangedEventArgs( pn ) );
            }
        }
    }
}

编辑1

实际上,由于你是在更名的第一个名字和名字之后,Path=FirstName并且这样的工作很好,我认为你根本不需要转换器.多个TextBlocks同样有效,并且当您使用从右到左的语言本地化时,实际上可以更好地工作.

编辑2

我已经明白了.没有通知属性已更新,因为它绑定到对象本身,而不是其中一个属性.即使我做Person了一个DependencyObject和制作FirstNameLastName DependencyProperties,它不会更新.

不得不使用一个FullName属性,我已经更新了Person上面的类的代码来反映这一点.然后你可以绑定Title.(注意:我已将Person对象设置为Window's DataContext.)

Title="{Binding Path=FullName, Mode=OneWay}"

如果您正在编辑a中的名称TextBox并希望立即反映名称而不是TextBox失去焦点,则可以执行以下操作:


我知道你不想使用一个FullName属性,但任何可以实现你想要的东西都可能是一个Rube Goldberg设备.如实施INotifyPropertyChangedPerson对房地产Window类本身,具有Window侦听PropertyChanged,以触发事件WindowPropertyChanged事件,并使用相对类似下面结合.您也可以在设置Person属性之前设置属性,InitializeComponent()或者PropertyChanged在设置Person属性后触发,以便它显示出来.(否则它将在null期间InitializeComponent()并且需要知道它何时是Person.)


    


    

推荐阅读
女女的家_747
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有