TripleAntigen
TripleAntigen

Reputation: 2301

Generating string in code when one of a group of properties change

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

Answers (4)

Jon
Jon

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:

  1. Object is created
  2. Object subscribes to its own INPC
  3. A dependent property is changed
  4. The INPC subscription detects that a dependent property for FullAddress has changed, and updates the FullAddress value
  5. The FullAddress setter fires its own INPC event
  6. WPF detects that FullAddress has changed and updates the UI

Update: 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

alpha-mouse
alpha-mouse

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

Dean Chalk
Dean Chalk

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

David Ward
David Ward

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

Related Questions