INotifyPropertyChanged in C # Structures

Hello I have the following code:

public struct zoomInfo : INotifyPropertyChanged
{
    public float zoom;
    public float translateX;
    public float translateY;
    private int level;

    public int zoomLevel 
    { 
        get { return level; }
        set { 
            level = value;
            OnPropertyChanged("zoomLevel");
        }
    }

    //region Implementation of INotifyPropertyChanged

    public event PropertyChangedEventHandler PropertyChanged;
    private void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    //endregion

};

      

When I bind this to a control it doesn't work. PropertyChangedEventHandler is always null. But when I change this to a class instead of a struct, the PropertyChangedEventHandler property is not null and required works fine. So the question is, does INotifyPropertyChanged only work on classes?

+3


source to share


1 answer


You can implement INotifyPropertyChanged

in a struct, but you should never do that because struct semantics don't work well (I would say generally) with this interface and events in general. Consider this:

struct EventStruct : INotifyPropertyChanged {
    private string _property;

    public string Property
    {
        get { return _property; }
        set
        {
            _property = value;
            OnPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    private void OnPropertyChanged([CallerMemberName] string propertyName = null) {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

      

Now we will just sign the event and change the property:

class Program {
    static void Main() {
        var s = new EventStruct();
        s.PropertyChanged += OnPropertyChanged;
        s.Property = "test";
        Console.ReadKey();
    }        

    private static void OnPropertyChanged(object sender, PropertyChangedEventArgs e) {
        Console.WriteLine(e.PropertyName + " changed");
    }        
}

      

"Property changed" is displayed. Therefore, you cannot say that structures and events don't work at all (or that INotifyPropertyChanged

doesn't work with structs). It works, sort of, until you try to pass this structure anywhere:

class Program {
    static void Main() {
        var s = new EventStruct();            
        Bind(s);
        s.Property = "test";
        Console.ReadKey();
    }

    static void Bind(INotifyPropertyChanged item) {
        // this is not the same instance of EventStruct,
        // it a copy, and event will never be fired on this copy
        item.PropertyChanged += OnPropertyChanged;
    }

    private static void OnPropertyChanged(object sender, PropertyChangedEventArgs e) {
        Console.WriteLine(e.PropertyName + " changed");
    }        
}

      



Passing struct to Bind

method as INotifyPropertyChanged

fields, which is the struct that makes the copy, so you subscribe to the event PropertyChanged

using one instance EventStruct

(copy), but the event is fired on another instance of the structure. Thus, the list of event subscribers is empty in this instance where the event was actually fired. The same happens if you just pass the struct and not the interface (in this case, the struct is copied because it is passed by value):

static void Bind(EventStruct item) {
    item.PropertyChanged += OnPropertyChanged;
}

      

If you follow the link it will work again:

static void Bind(ref EventStruct item) {
    item.PropertyChanged += OnPropertyChanged;
}

      

For this reason, you should never implement events in structs, at least I don't need a use case where it can be useful and not lead to problems.

+2


source







All Articles