Reputation: 2301
I am seeking advice on how to be notified when one of many properties change.
For example, lets say I want to bind a control's text to a FullAddress property in my WPF ViewModel that I can calculate on the fly whenever one of a set of properties changes, such as StreetNumber, StreetName, Suburb, PostCode etc.
I am thinking that I need to bind my displaying control to the FullAddress property, but how do I have it automatically update whenever one of the dependent properties changes? Can I bind the property's codebehind to multiple other properties on the same ViewModel? If so how? Is there a better way?
Upvotes: 0
Views: 116
Reputation: 437604
I think your only option here is to have objects of your class subscribe to their own INPC events and change their dependent properties automatically. The workflow would go like this:
FullAddress
has changed, and updates the FullAddress
valueFullAddress
setter fires its own INPC eventFullAddress
has changed and updates the UIUpdate: Sample code
class NotificationExample : INotifyPropertyChanged
{
private string firstName;
private string lastName;
public event PropertyChangedEventHandler PropertyChanged;
public string FirstName
{
get { return this.firstName; }
set
{
this.firstName = value;
this.OnPropertyChanged("FirstName");
}
}
public string LastName
{
get { return this.lastName; }
set
{
this.lastName = value;
this.OnPropertyChanged("LastName");
}
}
public string FullName
{
get { return string.Format("{0} {1}", this.firstName, this.lastName); }
}
public NotificationExample()
{
this.PropertyChanged += this.NotifyIfFullNameChanged;
}
private void OnPropertyChanged(string propertyName)
{
var handler = this.PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
private void NotifyIfFullNameChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "FirstName" || e.PropertyName == "LastName")
{
this.OnPropertyChanged("FullName");
}
}
}
Upvotes: 1
Reputation: 5003
You can use MultiBinding and do not use FullAddress property at all
EDIT:
If you only need to show the full address you can use StringFormat
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}{0}, {1}">
<Binding Path="City"/>
<Binding Path="Street"/>
</MultiBinding>
</TextBlock.Text>
</TextBlock>
If you wish to allow users edit the whole address string and then split it into parts then you need to implement IMultiValueConverter interface
Upvotes: 1
Reputation: 20471
try something like this:
public class Address : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string address1;
public string Address1
{
get { return address1; }
set
{
address1 = value;
OnPropertyChanged("Address1");
OnPropertyChanged("FullAddress");
}
}
private string address2;
public string Address2
{
get { return address2; }
set
{
address2 = value;
OnPropertyChanged("Address2");
OnPropertyChanged("FullAddress");
}
}
private string town;
public string Town
{
get { return town; }
set
{
town = value;
OnPropertyChanged("Town");
OnPropertyChanged("FullAddress");
}
}
public string FullAddress
{
get { return string.Format("{0}, {1}, {2}", address1, address2, town); }
}
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
Upvotes: 1
Reputation: 3829
Assuming your class implements INotifyPropertyChanged then you can notify within any property setter. E.g
#region Implementation of INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
Address.BeginEdit();
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
public string FirstLine
{
get { return firstLine; }
set
{
firstLine = value;
OnPropertyChanged("FirstLine");
OnPropertyChanged("FullAddress");
}
}
public string SecondLine
{
get { return secondLine; }
set
{
secondLine= value;
OnPropertyChanged("SecondLine");
OnPropertyChanged("FullAddress");
}
}
public string FullAddress
{
get { return firstLine + secondLine; }
}
Upvotes: 1