星期三, 12月 21, 2011

UserControl 傳值

之前有人問說,如果兩個 UserControl 在同一個page,要怎麼互相把值丟來丟去,這問題好像有學 .net 的人都會碰到,Bibby 的想法很簡單,只要雙方的可以知道彼此,那想怎樣就可以怎樣了,接下來寫個簡單的範例,加上點小技巧,希望大家可以了解

先來個圖例

image

再看結果

image

實戰演練:

先新增這兩個interface


    /// <summary>
    /// 讓Page實作,讓Page有Container的功能
    /// </summary>
    public interface IContainer
    {
        object GetObj(string key);
        void AddObj(string key,object o);
    }


    /// <summary>
    /// 讓顯示的uc2來實作,這樣就會有接值得功能
    /// </summary>
    public interface ICommand
    {
        void ToDo(object obj);
    }

Default.cs(Page)


    public partial class _Default : System.Web.UI.Page, IContainer
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            //把uc加進去,讓其他頁面可以取得想要的uc
            dic.Add("uc1", Uc11);
            dic.Add("uc2", Uc21);
        }

        //這裡把uc都加入,以後要找uc就來這找就行了
        Dictionary<string, object> dic = new Dictionary<string, object>();
        public object GetObj(string key)
        {
            if (dic.ContainsKey(key))
                return dic[key];
            return null;
        }

        public void AddObj(string key, object obj)
        {
            dic[key] = obj;
        }
    }

Uc1.cs

    public partial class Uc1 : System.Web.UI.UserControl
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);

            btn.Click += new EventHandler(btn_Click);
        }

        void btn_Click(object sender, EventArgs e)
        {
            //確認Page是否實作IContainer
            var container = Page as IContainer;
            if (Page == null)
                return;

            //確認uc2是否有時做ICommand
            var uc2 = container.GetObj("uc2");
            var command = uc2 as ICommand;
            if (command == null)
                return;

            command.ToDo(DateTime.Now);

            //((Page as IContainer).GetObj("uc2") as ICommand).ToDo(DateTime.Now);
        }
    }

Uc2.cs

    public partial class Uc2 : System.Web.UI.UserControl, ICommand
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        public void ToDo(object obj)
        {
            lit.Text = obj.ToString();
        }
    }

Code 的部份大概就是這樣子了,分兩點來解釋:

第一,讓 Page 實作 Icontainer 這 interface 就是要讓 Page 變成一個 Container 讓大家可以想要什麼東西就從 Page 這邊拿,我們可以經由 Page 來取得想要 uc,取得後轉型成想要的型態,傳統的方式用 FindControl 來找尋,缺點是相依性很重,很容易調一下版面或移一下 uc 就讓頁面死掉,這種作法是在 Page 裡面把 uc 一個一個加入 Container,如果之後頁面很複雜,我們沒辦法在 Page 知道哪些 uc 要加入,我們也可以在 uc 的 Init 事件加進去,反正我們最終的目的就是要把 Page 當作一個 Container,如何取得 uc 的方式統一管理

第二,uc2 有實作 Icommand 這 interface,其實如果沒有實作也行,只要把 object t轉成 uc2 的型別就可以了,但是在考慮相依性的問題,我們不希望 uc1 知道 uc2 是誰,實作 ICommand 就是要相依反轉降低耦合,讓 uc1 不知道 uc2,如果以後 uc2 改了,uc1 就不用動了

Source Code
http://dl.dropbox.com/u/19052216/WebShare/ObserverUC.zip

有問題一起討論吧!!

沒有留言: