研究下WPF 数据binding 原理

测试相关类

    public class HostTest 
    {
        public string Value{get; set;}

        public string Value1 {get ;set ;}
    }
    public class Test 
    {
        private string _value = null;
        public string Value
        {
            get { return _value; }
            set
            {
                _value = value;                
            }
        }

        private string _value1 = null;
        public string Value1
        {
            get { return _value1; }
            set
            {
                _value1 = value;               
            }
        }
    }

实现效果是将一个HostTest 对象的两个属性绑定到Test的两个属性上,然后实现HostTest对应的属性改变,两个Test 对象的属性也自动修改,反之亦然,实现代码如下:

namespace BindingDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            var host = new HostTest();
            var test = new Test();
            var test1 = new Test();
            
            host.AddBinding("Value", new Binding(test, "Value"));
            host.AddBinding("Value1", new Binding(test, "Value1"));

            host.AddBinding("Value", new Binding(test1, "Value"));
            host.AddBinding("Value1", new Binding(test1, "Value1"));

            host.Value = "Test1";
            host.Value1 = "Test1";

            Console.WriteLine(test.Value);//Test1
            Console.WriteLine(test.Value1);//Test1

            Console.WriteLine(test1.Value);//Test1
            Console.WriteLine(test1.Value1);//Test1

            test.Value = "Test2";
            test.Value1 = "Test2";
            Console.WriteLine(host.Value);//Test2
            Console.WriteLine(host.Value1);//Test2
            Console.WriteLine(test1.Value);//Test2
            Console.WriteLine(test1.Value1);//Test2
            Console.ReadLine();
        }
    }

    public delegate void OnPropertyChanged(object obj,string name);

    public interface INotifier
    {
        OnPropertyChanged OnPropertyChanged { get; set; }
    }

    public class Binding
    {
        public object Host { get; set; }
        public string HostProperty { get; set; }
        public object Target { get; set; }
        public string Property { get; set; }

        public Binding(object target, string property)
        {
            Target = target;
            Property = property;
        }

        internal void UpdateTargetValue(object value)
        {
            var property = Target.GetType().GetProperty(Property);
            property.SetValue(Target, value);
        }

        internal void UpdateHostValue()
        {
            var property = Target.GetType().GetProperty(Property);
            object value = property.GetValue(Target);
            property = Host.GetType().GetProperty(HostProperty);
            property.SetValue(Host, value);
        }
    }

    public abstract class BindingHostBase
    {
        private Dictionary<string, object> _values = new Dictionary<string, object>();
        private List<Binding> _bindings = new List<Binding>();
        private Dictionary<string, List<Binding>> _bindDict = new Dictionary<string, List<Binding>>();

        public void AddBinding(string propertyName, Binding binding)
        {
            if (!_bindDict.ContainsKey(propertyName))
            {
                _bindDict.Add(propertyName, new List<Binding>() {});
            }

            var bindings = _bindDict[propertyName];
            if (bindings.Contains(binding))
            {
                return;
            }

            bindings.Add(binding);
            _bindings.Add(binding);

            binding.Host = this;
            binding.HostProperty = propertyName;
            var notifier = binding.Target as INotifier;
            if (notifier.OnPropertyChanged == null)
            {
                notifier.OnPropertyChanged = (obj, name) =>
                {
                    var bds = _bindings.Where(b => b.Target == obj && b.Property == name).ToList();
                    if (bds != null)
                        bds.ForEach(b => b.UpdateHostValue());
                };
            }

        }

        public void SetValue(string name, object value)
        {
            if (_values.ContainsKey(name))
            {
                bool flag = _values[name] != value;
                _values[name] = value;
                if(flag)
                _bindDict[name].ForEach(b=>b.UpdateTargetValue(value));
            }
            else
            {
                _values.Add(name, value);
                _bindDict[name].ForEach(b => b.UpdateTargetValue(value));
            }
        }

        public object GetValue(string name)
        {
            if (_values.ContainsKey(name))
            {
                return _values[name];
            }
            return null;
        }
    }

    public class HostTest : BindingHostBase
    {
        public string Value
        {
            get { return (string) GetValue(nameof(Value)); }
            set { SetValue(nameof(Value), value); }
        }

        public string Value1
        {
            get { return (string)GetValue(nameof(Value1)); }
            set { SetValue(nameof(Value1), value); }
        }
    }

    public class Test : INotifier
    {
        private string _value = null;

        public string Value
        {
            get { return _value; }
            set
            {
                _value = value;
                RaisePropertyChanged(nameof(Value));
            }
        }

        private string _value1 = null;

        public string Value1
        {
            get { return _value1; }
            set
            {
                _value1 = value;
                RaisePropertyChanged(nameof(Value1));
            }
        }

        public OnPropertyChanged OnPropertyChanged { get ; set ; }

        public void RaisePropertyChanged(string name)
        {
            OnPropertyChanged?.Invoke(this, name);
        }
    }

}

如有bug,请指教?

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值