到时通知现场取决于另一个属性变化的最佳方式 [英] Best way to Notify property change when field is depending on another

查看:125
本文介绍了到时通知现场取决于另一个属性变化的最佳方式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

什么是C#中的最佳方式通知物业对项目的实地更改,而不设置,但 GET 取决于其他领域

What is the best way in c# to notify property changed on an item's field without set but get depends on other fields ?

例如:

public class Example : INotifyPropertyChanged
{
    private MyClass _item;
    public event PropertyChangedEventHandler PropertyChanged;

    public MyClass Item
    {
        get
        {
            return _item;
        }
        protected set
        {
            _item = value;
            OnPropertyChanged("Item");
        }
    }

    public object Field
    {
        get
        {
            return _item.Field;
        }
    }
    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;

        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}



什么是最好的方式上升一对的PropertyChanged 设置项目时?我想叫 OnPropertyChanged(田);当设置 项目,但如果我有很多领域代码将很快,是丑陋,难以维护

What the best way to rise a PropertyChanged for "Field" when setting Item ? I wanted to callOnPropertyChanged("Field"); when setting Item but if I had many fields the code will quickly be ugly and unmaintainable.

编辑:

我不知道是否有一个函数/方法/属性那样工作这样的:

I wonder if there is a function/method/attribute working like this :

[DependOn(Item)]
public object Field
{
    get
    {
        return _item.Field;
    }
}



=>在项目的变化,所有的视域将通知属性已更改。

=> When Item changes, all the depending fields will notify the property changed.

是否存在?

推荐答案

的一种方法是只是调用 OnPropertyChanged 多次:

One way is to just call OnPropertyChanged multiple times:

public MyClass Item
{
    get
    {
        return _item;
    }
    protected set
    {
        _item = value;
        OnPropertyChanged("Item");
        OnPropertyChanged("Field");
    }
}

这是不是很维护,但是。另一种选择是一个二传手添加到您只获得属性和其他属性进行设置:

This isn't very maintainable, however. Another option is to add a setter to your get-only property and set it from the other property:

public MyClass Item
{
    get
    {
        return _item;
    }
    protected set
    {
        _item = value;
        OnPropertyChanged("Item");
        Field = _item.Field;
    }
}

public object Field
{
    get
    {
        return _field;
    }
    private set
    {
        _field = value;
        OnPropertyChanged("Field");
    }
}

有对使用属性没有内置的机制显示性能之间的关系,但它有可能创建一个辅助类,可以为你做。

There is no built-in mechanism for using attributes to indicate this relationship between properties, however it would be possible to create a helper class that could do it for you.

我做了什么,可能的一个很基本的例子看起来像在这里:

I've made a really basic example of what that might look like here:

[AttributeUsage( AttributeTargets.Property )]
public class DepondsOnAttribute : Attribute
{
    public DepondsOnAttribute( string name )
    {
        Name = name;
    }

    public string Name { get; }
}

public class PropertyChangedNotifier<T> : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public PropertyChangedNotifier( T owner )
    {
        mOwner = owner;
    }

    public void OnPropertyChanged( string propertyName )
    {
        var handler = PropertyChanged;
        if( handler != null ) handler( mOwner, new PropertyChangedEventArgs( propertyName ) );

        List<string> dependents;
        if( smPropertyDependencies.TryGetValue( propertyName, out dependents ) )
        {
            foreach( var dependent in dependents ) OnPropertyChanged( dependent );
        }
    }

    static PropertyChangedNotifier()
    {
        foreach( var property in typeof( T ).GetProperties() )
        {
            var dependsOn = property.GetCustomAttributes( true )
                                    .OfType<DepondsOnAttribute>()
                                    .Select( attribute => attribute.Name );

            foreach( var dependency in dependsOn )
            {
                List<string> list;
                if( !smPropertyDependencies.TryGetValue( dependency, out list ) )
                {
                    list = new List<string>();
                    smPropertyDependencies.Add( dependency, list );
                }

                if (property.Name == dependency)
                    throw new ApplicationException(String.Format("Property {0} of {1} cannot depends of itself", dependency, typeof(T).ToString()));

                list.Add( property.Name );
            }
        }
    }

    private static readonly Dictionary<string, List<string>> smPropertyDependencies = new Dictionary<string, List<string>>();

    private readonly T mOwner;
}

这是不是非常强劲(例如,你可以创建之间的循环依赖性能和改变会得到停留在一个无限递归的情况属性)。它也可以使用一些.NET 4.5和C#6的特性变得更加简单,但我会离开所有作为一个练习留给读者。它也可能不处理继承得非常好

This isn't terribly robust (for example you could create a circular dependency between properties and the property changed would get stuck in an infinite recursion situation). It can also be made simpler using some .NET 4.5 and C#6 features, but I'll leave all that as an exercise for the reader. It probably also doesn't handle inheritance very well.

要使用这个类:

public class Example : INotifyPropertyChanged
{
    private MyClass _item;
    private PropertyChangedNotifier<Example> _notifier;

    public Example()
    {
        _notifier = new PropertyChangedNotifier<Example>( this );
    }

    public event PropertyChangedEventHandler PropertyChanged
    {
        add { _notifier.PropertyChanged += value; }
        remove { _notifier.PropertyChanged -= value; }
    }

    public MyClass Item
    {
        get
        {
            return _item;
        }
        protected set
        {
            _item = value;
            OnPropertyChanged("Item");
        }
    }

    [DependsOn( "Item" )]
    public object Field
    {
        get
        {
            return _item.Field;
        }
    }
    protected void OnPropertyChanged(string propertyName)
    {
        _notifier.OnPropertyChanged( propertyName );
    }
}

这篇关于到时通知现场取决于另一个属性变化的最佳方式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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