初探SmartClient奥秘

 

摘要:Smart Client Software Factory 首先是为 Smart Client 应用设计的编程框架,通过合理的使用架构模式、设计模式和最佳实践建立 Smart Client 的指导原则和框架基础。基于MVP模式(Model-View-Presenter)。,它通过 Visual Studio GuidanceAutomation 扩展了 VS 的功能。

该框架主要用于开发类似与工具类型的软件,支持多视图,自定界面视图,类似于Visual StudioPowerDesignerMapWinGis等界面。结合现在所做的项目,主要说一下几种功能:

 

一、SmartClient中的EventBrokerEventPublicationEventSubscription):

某个Event贴上EventPublicationAttribute,则我们就可以在相关的方法上利用EventSubscription这个Attribute就可以轻松订阅相关EventPublication。类似与事件委托,一对多的关系,发布一个事件,多个地方可以接收。

SCSF 启动过程中,ObjectBuilder 会到被创建的对象上去找标有 EventPublicationAttribute EventSubscriptionAttribute 的事件和方法,并通过 topic, PublicationScope 把对应的事件发布和接受者动态的关联起来,放到 WorkItem EventTopic 集合中。

eg.

          [EventPublication(EventTopicNames.MapGeometrySelectedTopic)]

        public event EventHandler<DataEventArgs<List<SelectObject>>> GeometrySelectedChanged;

 

public class EventTopicNames

{

        /// 地图选择对象改变事件名

        public const string MapGeometrySelectedTopic = "topic://MapView/GeometrySelected";

}

 

        [EventSubscription(EventTopicNames.MapGeometrySelectedTopic)]

        public void OnMapGeometrySelected(object sender, DataEventArgs<List<SelectObject>> e)

        {

            flowLayoutPanel1.Controls.Clear();

            BindSelectedView(e.Data);

            //_pgSelectElem.SelectedObject = null;

        }

 

该例子主要是在地图上框选出区域内的设备,然后在属性窗口中显示这些设备的信息

 

 




二、
RootWorkItem

整个 SCSF 应用有且只有一个 RootWorkItem

        public T ShowSingletonView<T>(string viewName) where T : IDockContent

        {

            T frm;

            frm = WorkItem.RootWorkItem.SmartParts.Get<T>(viewName);

            if (frm == null)

                frm = WorkItem.RootWorkItem.SmartParts.AddNew<T>(viewName);

            ShowView(frm);

            return frm;

        }

将窗口注册到RootWorkItem中。

 

三、ModuleController 模块控制逻辑

    public class ModuleController : WorkItemController

    {

        public override void Run()

        {

            AddServices();

            ExtendMenu();

            ExtendToolStrip();

            AddViews();

        }

private IShellForm _ShellForm = null;

 

        private WorkItem RootWorkItem

        {

            get { return this.WorkItem.RootWorkItem; }

        }

 

        private void AddServices()

        {

            _ShellForm = ModuleService.GetShellForm();

        }

        private readonly string CLICK_EVENT_NAME = "Click";

 

        private void ExtendMenu()

        {

            #region View Menu

 

            ToolStripMenuItem menuMapView = new ToolStripMenuItem();      //地图视图

            menuMapView.Name = UIExtensionSiteNames.MenuMapView;

            menuMapView.Text = UIExtensionSiteNames.MenuMapView;

            menuMapView.Image = MainViewResource.地图视图;

            WorkItem.Commands[CommandNames.CmdShowMapView].AddInvoker(menuMapView, CLICK_EVENT_NAME);

 

            ToolStripMenuItem menuPropertyView = new ToolStripMenuItem(); //属性视图

            menuPropertyView.Name = UIExtensionSiteNames.MenuPropertyView;

            menuPropertyView.Text = UIExtensionSiteNames.MenuPropertyView;

            menuPropertyView.Image = MainViewResource.属性视图;

            WorkItem.Commands[CommandNames.CmdShowPropertyView].AddInvoker(menuPropertyView, CLICK_EVENT_NAME);

            WorkItem.Commands[CommandNames.CmdShowDrawingView].AddInvoker(MenuDrawingView, CLICK_EVENT_NAME);

 

 

            ToolStripMenuItem menuView = new ToolStripMenuItem();         //视图菜单

            menuView.Name = UIExtensionSiteNames.MenuView;

            menuView.Text = UIExtensionSiteNames.MenuView;

            menuView.DropDownItems.AddRange(new ToolStripItem[] { menuMapView,   menuPropertyView });

 

            WorkItem.UIExtensionSites[NRM.Infrastructure.Interface.Constants.UIExtensionSiteNames.MainMenu].Add<ToolStripMenuItem>(menuView);

            #endregion View Menu

        }

 

        int toolPriority = 1;

        private void ExtendToolStrip()

        {

            #region 视图菜单工具条

            ShellToolStrip toolView = new ShellToolStrip(UIExtensionSiteNames.MenuView);

            _ShellForm.MainToolStrip.Add(toolView);

            int veiwPriority = 1;

 

            //地图视图

            ToolStripItem itemMapView = new ToolStripButton();

            itemMapView.Name = UIExtensionSiteNames.ToolMapView;

            itemMapView.Image = MainViewResource.地图视图;

            itemMapView.ToolTipText = "地图视图";

            ShellToolStripItem tsMapView = new ShellToolStripItem(itemMapView, UIExtensionSiteNames.MenuView, veiwPriority++);

            _ShellForm.MainToolStripItem.Add(tsMapView);

                        WorkItem.Commands[CommandNames.CmdShowLayerView].AddInvoker(itemLayerView, CLICK_EVENT_NAME);

 

            //属性视图

            ToolStripItem itemPropertyView = new ToolStripButton();

            itemPropertyView.Name = UIExtensionSiteNames.ToolPropertyView;

            itemPropertyView.Image = MainViewResource.属性视图;

            itemPropertyView.ToolTipText = "属性视图";

            ShellToolStripItem tsPropertyView = new ShellToolStripItem(itemPropertyView, UIExtensionSiteNames.MenuView, veiwPriority++);

            _ShellForm.MainToolStripItem.Add(tsPropertyView);

            WorkItem.Commands[CommandNames.CmdShowPropertyView].AddInvoker(itemPropertyView, CLICK_EVENT_NAME);

 

            #endregion 视图菜单工具条

        }

系统启动的时候,会调用ModuleControl里的Run方法

 

三、依赖注入

        [ServiceDependency]

        public WorkItem WorkItem

        {

            set { _workItem = value; }

            get { return _workItem; }

        }

WorkItem会自动获得。

 

四、MVP模式

一个登入界面的MVP模式。包含Interface层的ILoginView.cs , Presenter层的LoginPersenter.cs  页面层的Winform LoginForm.cs。

 接口层:   public interface ILoginView : IView

    {

        string UserName { get; }

        string Password { get; }

        void LoginSuccessful();

        void LoginFailed();

        event EventHandler OnLogin;

}

Persenter

public class LoginPresenter : Presenter

    {

        ILoginView _loginView;

 

        public LoginPresenter( ILoginView view ) : this(view, null)

        {}

 

        public LoginPresenter( ILoginView view, ISessionProvider session ) : base(view, session)

        {

            _loginView = base.GetView<ILoginView>();

            _loginView.OnLogin += new EventHandler(_loginView_OnLogin);

        }

 

        void _loginView_OnLogin(object sender, EventArgs e)

        {

            string userName = _loginView.UserName;

            string password = _loginView.Password;

 

            // Example of managing state without referencing System.Web

            if(this.Session != null && Session["userName"] == null)

            {

                Session["userName"] = userName;

            }

 

            if(userName.Equals("user") && password.Equals("pass"))

            {

                _loginView.LoginSuccessful();

            }

            else

            {

                _loginView.LoginFailed();

            }

        }

    }

 

 

界面层

    [PresenterType(typeof(LoginPresenter))]-------特性

    public partial class LoginForm : BaseForm, ILoginView

    {

        public LoginForm()

        {

            InitializeComponent();

 

            base.SelfRegister(this);

        }

 

        private void loginButton_Click( object sender, EventArgs e )

        {

            this.OnLogin(this, EventArgs.Empty);

        }

 

        #region ILoginView Members

 

        string ILoginView.UserName

        {

            get { return this.userName.Text; }

        }

 

        string ILoginView.Password

        {

            get { return this.password.Text; }

        }

 

        void ILoginView.LoginSuccessful()

        {

            this.DialogResult = DialogResult.OK;

            this.Close();

        }

 

        void ILoginView.LoginFailed()

        {

            errorLabel.Visible = true;

        }

 

        public event EventHandler OnLogin;

 

        #endregion

    }

MVP 是从经典的模式MVC演变而来,它们的基本思想有相通的地方:Controller/Presenter负责逻辑的处理,Model提供数据,View负责显示。

 

总结:初探SmartClient,确实让人惊讶,展现出很多魅力,据说他还有很多功能。接触挺久,现在也主要应用它的灵活界面及里面的一些机制。相信随着不断深入,将会发现更多的惊喜。欢迎各位园友拍砖,顺便指点指点,我很想知道,SmartClient中离线操作怎么实现、怎么应用。

posted @ 2009-08-26 11:02  wakerobin  阅读(4531)  评论(8编辑  收藏  举报