• 分享一个UI与业务逻辑分层的框架(二)


    序言

    第一篇讲解了UI与业务逻辑分层的框架(UIMediator)的使用。本篇将说明该框架的原理及代码实现。

    整体结构

    UI与后台类绑定主要分为UI输入->后台属性,后台属性-UI更新两部分,为符合依赖倒置原则,分别抽象出IUIToProperty和IPropertyToUI两个接口。

    为了匹配WinForm的窗体事件委托方法格式(object sender, EventArgs e)两个接口方法都实现了多态。

    Mediator采用了模板方法的设计模式,实现了整个绑定方法的算法框架,子类只需实现ChangeType、BindPropertyValue、BindUIValue三个抽象方法即可。

    TextBoxMediator、RadioButtonMediator、CheckBoxMediator为Mediator子类,根据各个不同的WinForm控件而实现的中介类,实现了上述三个抽象方法。

    ChangeType:将Control基类转换为具体的控件类;

    BindPropertyValue:实现UI输入->后台属性;

    BindUIValue:实现后台属性-UI更新。

    UML图如下所示。接下来讲解具体代码实现。

    依赖倒置

    UI输入->后台属性接口:IUIToProperty

     public interface IUIToProperty
        {
           void BindPropertyValue(object sender, EventArgs e);
           void BindPropertyValue(PropertyInfo prop);
        }

    后台属性-UI更新接口:IPropertyToUI

    public interface IPropertyToUI
        {
           void BindUIValue(object sender, EventArgs e);
           void BindUIValue(PropertyInfo prop);
        }

    Mediator模板类

     public abstract class Mediator:IUIToProperty,IPropertyToUI
        {
            protected Type type;
            protected object BindInstance;
            protected string BindProperty;
    
            public void Bind<T>(Control control, T BindInstance, string BindProperty) where T : class ,IPropertyChange
            {
                this.BindInstance = BindInstance as T;
                this.BindProperty = BindProperty;
                type = typeof(T);
                BindInstance.PropertyChanged += new EventHandler(BindUIValue);
                ChangeType(control);
                BindPropertyValue(null, null);
            }
    
    
            public void BindPropertyValue(object sender, EventArgs e)
            {
                BindPropertyValue(GetProperty());
            }
    
            private PropertyInfo GetProperty()
            {
                return type.GetProperties().First(c => c.Name == BindProperty);
            }
    
            public void BindUIValue(object sender, EventArgs e)
            {
                BindUIValue(GetProperty());
            }
            
            public abstract void BindPropertyValue(PropertyInfo prop);
            protected abstract void ChangeType(Control control);
            public abstract void BindUIValue(PropertyInfo propertyInfo);

     TextBoxMediator类

    public class TextBoxMediator:Mediator
        {
    
           private TextBox tb;
           public override void BindPropertyValue(System.Reflection.PropertyInfo prop)
           {
               if (prop.PropertyType.IsValueType && string.IsNullOrEmpty(tb.Text))
               {
                   prop.SetValue(BindInstance, 0, null);
                   return;
               }
               try
               {
                   object value = Convert.ChangeType(tb.Text, prop.PropertyType);
                   prop.SetValue(BindInstance, value, null);
               }
               catch (FormatException fex)
               {
                   throw fex;
               }
               catch (Exception ex)
               {
                   throw ex;
               }
           }
    
           protected override void ChangeType(Control control)
           {
               tb = control as TextBox;
               tb.TextChanged+=new EventHandler(BindPropertyValue);
           }
    
           public override void BindUIValue(System.Reflection.PropertyInfo prop)
           {
               tb.Text = prop.GetValue(BindInstance, null).ToString();
           }
        }

    CheckBoxMediator类

    public class CheckBoxMediator:Mediator
        {
    
           private CheckBox cb;
           public override void BindPropertyValue(PropertyInfo prop)
           {
               prop.SetValue(BindInstance, cb.Checked, null);
           }
    
           protected override void ChangeType(Control control)
           {
               cb = control as CheckBox;
               cb.CheckedChanged += new EventHandler(BindPropertyValue);
           }
    
           public override void BindUIValue(PropertyInfo prop)
           {
               cb.Checked = Convert.ToBoolean(prop.GetValue(BindInstance, null));
           }
    
        }

    RadioButtonMediator类

    public class RadioButtonMediator:Mediator
        {
           RadioButton rb;
           public override void BindPropertyValue(System.Reflection.PropertyInfo prop)
            {
                prop.SetValue(BindInstance, rb.Checked, null);
    
            }
            protected override void ChangeType(System.Windows.Forms.Control control)
            {
                rb = control as RadioButton;
                rb.CheckedChanged += new EventHandler(BindPropertyValue);
            }
    public override void BindUIValue(System.Reflection.PropertyInfo prop) { rb.Checked = Convert.ToBoolean(prop.GetValue(BindInstance, null)); } }

     关于后台属性-UI更新的说明

    分析下Mediator类中的Bind方法

     public void Bind<T>(Control control, T BindInstance, string BindProperty) where T : class ,IPropertyChange
            {
                this.BindInstance = BindInstance as T;
                this.BindProperty = BindProperty;
                type = typeof(T);
                BindInstance.PropertyChanged += new EventHandler(BindUIValue);
                ChangeType(control);
                BindPropertyValue(null, null);
            }

    泛型T有一个IPropertyChange的约束,具有PropertyChanged事件,用来注册绑定BindUIValue方法。

    IPropertyChange的代码如下

    public interface IPropertyChange
        {
            event EventHandler PropertyChanged;
            void UpdateUI();
        }

    由于.NET只支持类的单继承,为避免框架对代码的侵入性选择了接口继承。

    后台类通过继承IPropertyChange,在UpdateUI实现方法中调用PropertyChanged事件。

    在需要后台驱动UI更新时调用UpdateUI方法即可。

     public void UpdateUI()
                {
                    PropertyChanged(null, null);
                }
  • 相关阅读:
    Android NDK pthreads详细使用
    Android 音视频深入 十七 FFmpeg 获取RTMP流保存为flv (附源码下载)
    Android事件分发机制
    Gradle之FTP文件下载
    JVM内存回收机制
    Git如何把本地代码推送到远程仓库
    Android 进程间通讯方式
    微信小程序之文件系统初探
    时间选择器组件之关于table走过的弯路
    腾讯地图JavaScript API GL实现文本标记的碰撞避让
  • 原文地址:https://www.cnblogs.com/huangmianwu/p/5845946.html
Copyright © 2020-2023  润新知