Home > OS >  Raise an event when last property is assigned
Raise an event when last property is assigned

Time:09-24

Is there a way to run an event when the last property is assigned to an object? I don´t want to use INotifyPropertyChanged to fire the event every time a property value changed.
I want the event or method to fire only when the last property has been assigned.

For example here the event gets fired when the Color is assigned

            Model model = new Model();
            model.Blocks = 2;
            model.Layers = 3;

            ModelManager manager = new ModelManager();
            manager.Models.Add(model);

            model.Color = Color.Blue;

Here the event gets fired when the layers are assigned

            Model model = new Model();
            model.Blocks = 2;
            

            ModelManager manager = new ModelManager();
            manager.Models.Add(model);

            model.Color = Color.Blue;
            model.Layers = 3;

EDIT: I dont have a certain amout of properties to be set to consider the object "complete". The problem is that I need to do some calculations with the properties that have been set but I dont want to repeat the calculations every time a property is changed. The time the object is created there is no problem to repeat the calculations. But then in execution time the applicationis going to change a lot of properties "at once" like hundred of times so I want to do this calculations as less as possible.

CodePudding user response:

I don´t want to use INotifyPropertyChanged to fire the event every time a property value changed.

Sure you do, just add some logic to only conditionally fire the event. For example:

public string SomeProperty
{
    get { return this.someProperty; }
    set
    {
        if (value != this.someProperty)
        {
            this.someProperty = value;
            // only fire the event if the condition is met
            if (AllPropertiesAreSet())
            {
                NotifyPropertyChanged();
            }
        }
    }
}

private bool AllPropertiesAreSet()
{
    return (
        !string.IsNullOrEmpty(SomeProperty) &&
        SomeOtherProperty != 0 &&
        !string.IsNullOrEmpty(AThirdProperty)
    );
}

Basically each property would check if all of the properties "have been set" using whatever logic you want to use to define that state. The first one to get a true response from the condition would be the "last" property to be set.

Alternatively it doesn't need to specifically be an INotifyPropertyChanged event. You can create your own event, or just invoke a method, or do whatever you like in the body of that if block.

CodePudding user response:

You could just setup a list of properties that have to be changed before anything happens (like firing an event) and implement some check in the setter of your properties.

public class Model
{
    private bool _alreadyDidSomething;
    private readonly IList<string> _requiredProperties = new List<string>
    {
        nameof(PropertyA),
        nameof(PropertyB)
    };

    private string _propertyA;
    public string PropertyA
    {
        get => _propertyA;
        set
        {
            if (_propertyA == value)
                return;
            _propertyA = value;
            
            RemoveProperty();
            DoSomething();
        }
    }

    private string _propertyB;
    public string PropertyB
    {
        get => _propertyB;
        set
        {
            if (_propertyB == value)
                return;
            _propertyB = value;

            RemoveProperty();
            DoSomething();
        }
    }

    private void RemoveProperty([CallerMemberName] string propertyName = null)
    {
        _requiredProperties.Remove(propertyName);
    }

    private void DoSomething()
    {
        if (_requiredProperties.Count == 0 && !_alreadyDidSomething)
        {
            // fire event or do whatever you want to do!
            _alreadyDidSomething = true;
        }
    }
}

Everytime you change a property for the first time, its name will get removed from the list. In the "DoSomething" method you can check this list and whether it is empty and then do whatever you want to do.

The advantage of this approach is, that you can even configure which properties are relevant for the whole object to be considered "complete" before doing something. And you can choose whether to exeucte your action multiple times from than on or not

var model1 = new Model();
model1.PropertyA = "Value A"; // Does not trigger the event.
model1.PropertyB = "Value B"; // Does trigger the event.

var model2 = new Model();
model2.PropertyB = "Value B"; // Does not trigger the event.
model2.PropertyA = "Value A"; // Does trigger the event.

CodePudding user response:

A simple alternative would be to just simply have a method in the class Model called NotifyAll() that implements NotifyPropertyChanged(string propertyName) for all the properties in that class. Call that method only when you assign the last property some value.

  •  Tags:  
  • c#
  • Related