我打算在我的几个类之间使用数据绑定。换句话说,我不是在模型类和 UI 之间绑定值,而是在不同类之间绑定变量。
我在多个地方读到过有关 C# 中的数据绑定的内容,但大多数都是指 Windows 窗体和源对象之间的绑定。
我还是 C# 新手。这就是我理解我应该做什么的方式:
首先,对于我的源对象,假设有一个类名DataObject
。源对象必须实现INotifyPropertyChange
接口,然后每当该属性时触发事件,health
,即将改变。我对此没有问题。
现在,假设我有一个目标对象 called CharacterClass
. life
是位于CharacterClass
,并且也是目标财产我想绑定到源对象的health
财产。
如何仅使用普通的 .NET 框架在代码中将两个属性绑定在一起(单向和双向)?
关于我为什么问这个问题的一些背景信息:
以防万一您认为这是一个重复的问题,事实并非如此。我已经通过SE搜索过了。关于代码中数据绑定的其他问题是在 WPF 或 XAML 的上下文中,这不适合我。我还阅读了 MSDN 上的几篇文章,似乎我可以创建一个Binding
对象,然后通过绑定源和目标BindingOperations.SetBinding()
。但是,那Binding
类似乎是命名空间下的 WPF 库的一部分System.Windows.Data.Binding
。虽然我使用的是 C#,但我怀疑我是否有能力访问 WPF 库,因为我主要使用 C# 作为 Unity3D 中的脚本语言。我相信我只能访问普通的 .Net 框架。但是,我对此不太确定,因为我对 C# 仍然很陌生。
尽管有很多对与所使用的 UI 框架紧密耦合的绑定的支持,但您仍然可以轻松编写自己的绑定框架。
这是一个 POC,它实现了两个对象的属性之间的单向绑定。
注意:这只是可能的方法之一,充其量是 POC(可能需要针对高性能/生产场景进行微调)并使用 .Net 2.0 类和接口,不依赖于任何 UI 框架(“vanilla”.net用你的话来说框架:))。一旦您理解了这一点,您就可以轻松扩展它以支持 2 向绑定
class Program
{
public static void Main()
{
Source src = new Source();
Destination dst = new Destination(src);
dst.Name = "Destination";
dst.MyValue = -100;
src.Value = 50; //changes MyValue as well
src.Value = 45; //changes MyValue as well
Console.ReadLine();
}
}
//A way to provide source property to destination property
//mapping to the binding engine. Any other way can be used as well
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
internal class BindToAttribute : Attribute
{
public string PropertyName
{
get;
private set;
}
//Allows binding of different properties to different sources
public int SourceId
{
get;
private set;
}
public BindToAttribute(string propertyName, int sourceId)
{
PropertyName = propertyName;
SourceId = sourceId;
}
}
//INotifyPropertyChanged, so that binding engine knows when source gets updated
internal class Source : INotifyPropertyChanged
{
private int _value;
public int Value
{
get
{
return _value;
}
set
{
if (_value != value)
{
_value = value;
Console.WriteLine("Value is now: " + _value);
OnPropertyChanged("Value");
}
}
}
void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
internal class Destination
{
private BindingEngine<Destination> _binder;
private int _myValue;
[BindTo("Value", 1)]
public int MyValue
{
get
{
return _myValue;
}
set
{
_myValue = value;
Console.WriteLine("My Value is now: " + _myValue);
}
}
//No mapping defined for this property, hence it is not bound
private string _name;
public string Name
{
get
{
return _name;
}
set
{
_name = value;
Console.WriteLine("Name is now: " + _name);
}
}
public Destination(Source src)
{
//Binder for Source no 1
_binder = new BindingEngine<Destination>(this, src, 1);
}
}
internal class BindingEngine<T>
{
private readonly T _destination;
private readonly PropertyDescriptorCollection _sourceProperties;
private readonly Dictionary<string, PropertyDescriptor> _srcToDestMapping;
public BindingEngine(T destination, INotifyPropertyChanged source, int srcId)
{
_destination = destination;
//Get a list of destination properties
PropertyDescriptorCollection destinationProperties = TypeDescriptor.GetProperties(destination);
//Get a list of source properties
_sourceProperties = TypeDescriptor.GetProperties(source);
//This is the source property to destination property mapping
_srcToDestMapping = new Dictionary<string, PropertyDescriptor>();
//listen for INotifyPropertyChanged event on the source
source.PropertyChanged += SourcePropertyChanged;
foreach (PropertyDescriptor property in destinationProperties)
{
//Prepare the mapping.
//Add those properties for which binding has been defined
var attribute = (BindToAttribute)property.Attributes[typeof(BindToAttribute)];
if (attribute != null && attribute.SourceId == srcId)
{
_srcToDestMapping[attribute.PropertyName] = property;
}
}
}
void SourcePropertyChanged(object sender, PropertyChangedEventArgs args)
{
if (_srcToDestMapping.ContainsKey(args.PropertyName))
{
//Get the destination property from mapping and update it
_srcToDestMapping[args.PropertyName].SetValue(_destination, _sourceProperties[args.PropertyName].GetValue(sender));
}
}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)