gpt4 book ai didi

c# - 当字段依赖于另一个字段时通知属性更改的最佳方法

转载 作者:太空狗 更新时间:2023-10-29 17:49:11 24 4
gpt4 key购买 nike

在没有 setget 取决于其他字段的情况下,在 C# 中通知项目字段上的属性更改的最佳方法是什么?

例如:

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;
}
}
#if !C#6
protected void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;

if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
#else
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
// => can be called in a set like this:
// public MyClass Item { set { _item = value; OnPropertyChanged();} }
// OnPropertyChanged will be raised for "Item"
}
#endif
}

在设置 Item 时,为 "Field" 增加 PropertyChanged 的​​最佳方法是什么?我想在设置 Item 时调用 OnPropertyChanged("Field");,但如果我有很多字段,代码很快就会变得丑陋且无法维护。

编辑:

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

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

=> 当Item 改变时,所有的依赖字段都会通知属性改变。

它存在吗?

最佳答案

一种方法是多次调用 OnPropertyChanged:

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

但是,这不是很容易维护。另一种选择是向您的 get-only 属性添加一个 setter 并从其他属性设置它:

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");
}
}

没有使用属性来指示属性之间这种关系的内置机制,但是可以创建一个可以为您完成此操作的帮助程序类。

我在这里做了一个非常基本的例子:

[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 功能变得更简单,但我将把所有这些作为练习留给读者。它可能也不能很好地处理继承。

要使用这个类:

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 );
}
}

关于c# - 当字段依赖于另一个字段时通知属性更改的最佳方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38896344/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com