Why is it that when I use a converter in my binding expression in WPF, the value is not updated when the data is updated.
I have a simple Person data model:
class Person : INotifyPropertyChanged { public string FirstName { get; set; } public string LastName { get; set; } }
My binding expression looks like this:
<TextBlock Text='{Binding Converter={StaticResource personNameConverter}' />
My converter looks like this:
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(); } }
If I bind the data without a converter it works great:
<TextBlock Text='{Binding Path=FirstName}' /> <TextBlock Text='{Binding Path=LastName}' />
What am I missing?
EDIT: Just to clarify a few things, both Joel and Alan are correct regarding the INotifyPropertyChanged interface that needs to be implemented. In reality I do actually implement it but it still doesn’t work.
I can’t use multiple TextBlock elements because I’m trying to bind the Window Title to the full name, and the Window Title does not take a template.
Finally, it is an option to add a compound property ‘FullName’ and bind to it, but I’m still wondering why updating does not happen when the binding uses a converter. Even when I put a break point in the converter code, the debugger just doesn’t get there when an update is done to the underlying data 🙁
Thanks, Uri
(see edits below; latest: #2)
It isn’t updating because your
Personobject is not capable of notifying anything that the value ofFirstNameorLastNamehas changed. See this Question.And here’s how you implement
INotifyPropertyChanged. (Updated, see Edit 2)Edit 1
Actually, since you’re after the first name and last name updating, and
Path=FirstNameand such works just fine, I don’t think you’ll need the converter at all. MultipleTextBlocksare just as valid, and can actually work better when you’re localizing to a right-to-left language.Edit 2
I’ve figured it out. It’s not being notified that the properties have updated because it is binding to the object itself, not one of those properties. Even when I made
PersonaDependencyObjectand madeFirstNameandLastNameDependencyProperties, it wouldn’t update.You will have to use a
FullNameproperty, and I’ve update the code of thePersonclass above to reflect that. Then you can bind theTitle. (Note: I’ve set thePersonobject as theWindow‘sDataContext.)If you’re editing the names in a
TextBoxand want the name changed reflected immediately instead of when theTextBoxloses focus, you can do this:I know you didn’t want to use a
FullNameproperty, but anything that would accomplish what you want would probably be a bit of a Rube Goldberg device. Such as implementingINotifyPropertyChangedand aPersonproperty on theWindowclass itself, having theWindowlisten on thePropertyChangedevent in order to fire theWindow‘sPropertyChangedevent, and using a relative binding like the following. You’d also have set thePersonproperty beforeInitializeComponent()or firePropertyChangedafter setting thePersonproperty so that it shows up, of course. (Otherwise it will benullduringInitializeComponent()and needs to know when it’s aPerson.)