C#结构中的INotifyPropertyChanged [英] INotifyPropertyChanged in c# structures

查看:33
本文介绍了C#结构中的INotifyPropertyChanged的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

你好,我有以下代码:

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

};

当我将此绑定到控件时..它不起作用.PropertyChangedEventHandler始终为null.但是当我将其更改为class而不是struct时,PropertyChangedEventHandler不为null,并且绑定可以正常工作.所以问题是,INotifyPropertyChanged仅适用于类吗?

When I bind this to a control.. it is not working. PropertyChangedEventHandler is always null.. But when I change this to class instead of struct, PropertyChangedEventHandler is not null and binding works perfectly. So the question is, does INotifyPropertyChanged only works on classes?

推荐答案

您可以在结构中实现 INotifyPropertyChanged ,但是您绝对不能这样做,因为结构的语义不能很好地发挥作用(我d完全说)与此接口以及一般的事件.考虑一下:

You can implement INotifyPropertyChanged in a struct, but you should never do that, because semantics of structs do not play well (I'd say at all) 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 just subscribe to event and change a 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");
    }        
}

输出为属性已更改".因此,您不能说结构和事件根本不起作用(或者 INotifyPropertyChanged 对结构不起作用).直到您尝试将结构传递到任何地方,它都可以工作:

Output is "Property changed". So you cannot say that structs and events do not work at all (or that INotifyPropertyChanged doesn't work with structs). It works, kind of, until you try to pass that struct 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's 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");
    }        
}

将结构作为 INotifyPropertyChanged 框传递给 Bind 方法,该框会进行复制,因此您使用以下实例之一订阅 PropertyChanged 事件 EventStruct (副本),但是在结构的另一个实例上触发了事件.因此,在实际触发事件的实例上,事件订阅者列表为空.如果只传递结构而不是接口,也会发生同样的情况(在这种情况下,结构是复制的,因为按值传递):

Passing struct to Bind method as INotifyPropertyChanged boxes that struct, which makes a copy, so you subscribe to PropertyChanged event using one instance of EventStruct (a copy), but event is fired on another instance of the struct. So event subscriber list is empty on that instance where event is actually fired. Same happens if you just pass struct and not interface (in this case struct is copied because passed by value):

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

如果您通过引用传递,它将再次起作用:

If you will pass by reference, it will work again:

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

基于这个原因,您永远不要在结构上实现事件,至少在我脑海中没有用例,在这种情况下它是有用的,不会引起麻烦.

For that reason you should never implement events on structs, at least no use case comes to my mind where this can be useful and not lead into troubles.

这篇关于C#结构中的INotifyPropertyChanged的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆