首页/技术分享

二次开发教程:研究下WPF 数据binding 原理

发布于:2019-07-24 16:38:12
3872人 分享

测试相关类


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

        }

    }

 

}

转载请注明来源本文地址:https://www.tuituisoft/blog/3175.html

上一篇:

二次开发教程:Hello Emit

下一篇:

二次开发教程:MyBatis增删查改