1. 程式人生 > >步步為營-83-用戶控件

步步為營-83-用戶控件

amp res pub oid xmlns deb 狀態 我們 lec

使用ascx目的就是為了提高某部分功能的重復利用,和方法封裝思想相似

參考了http://blog.csdn.net/dyllove98/article/details/9152843.

1需求:

1.1 創建一個用戶控件ascx B, 拉一個TextBox在這個控件上

1.2 創建另一個用戶控件ascx A 在這個用戶控件上,拉一個Textbox 和一個按鈕,是讓用戶在文本框輸入數據,點一點銨鈕,這樣動態產生ascx B用戶控件,呈現於ascx A用戶控件的頁面上。

1.3 創建一個aspx網頁。把用戶控件ascxA引用至aspx網頁上。再在aspx網頁上拉一個按鈕。讓用戶點一點這個銨鈕,去獲取動態產生的文本框的值,並顯示於aspx網頁上。

2實現

2.1 ascxB的創建(一個文本框)

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="AscxB.ascx.cs" Inherits="Web.UserControl.AscxB" %>
<asp:TextBox ID="txtB" runat="server"></asp:TextBox>

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="Web.WebForm1" %>    //aspx頁面

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="AscxB.ascx.cs" Inherits="Web.UserControl.AscxB" %>  //ascx頁面

通過對比我們可以發現 a @標簽不一樣; b 繼承的類不一樣; c 內容不同(是否含有html代碼)

2.2 ascxA的創建(一個文本框TextBox,一個銨鈕Button和一個容器PlaceHolder。在銨鈕添加onclick事件OnClick="BtnGenerate_Click")

<%@ Control Language="
C#" AutoEventWireup="true" CodeBehind="AscxA.ascx.cs" Inherits="Web.UserControl.AscxA" %> <asp:TextBox ID="txtA" runat="server"></asp:TextBox> &nbsp;&nbsp;&nbsp;&nbsp; <asp:Button ID="BtnGenerate" runat="server" Text="創建文本框" OnClick="BtnGenerate_Click" /> <br /> <asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder>

2.3 為了能讓AscxA動態加載到AscxB,通過接口實現

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.UI;

namespace Web.Interface
{
   public  interface IUserControl
    {
        UserControl GetUserControl();
    }
}

2.3 ascx B實現接口:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace Web.UserControls
{
    public partial class AscxB : System.Web.UI.UserControl,Web.Interface.IUserControl
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        public UserControl GetUserControl()
        {
            return this;
        }
    }
}

2.4 AscxA的後臺代碼

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Web.Interface;

namespace Web.UserControls

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

        }

        protected void BtnGenerate_Click(object sender, EventArgs e)
        {
            if (ViewState["yk"] == null)
            {
                ViewState["yk"] = true;
                DynamicGenerate();
            }
        }

        private void DynamicGenerate()
        {
            //獲取文本框的值
            int j = 1;
            Int32.TryParse(this.txtA.Text.Trim(),out j);

            for (int i = 0; i < j; i++)
            {
                //動態加載AscxB後,並轉化為接口 -- 如果直接接受呢?
               IUserControl uc = (IUserControl)this.LoadControl("~/AscxB.ascx");
                //加載接口
               this.PlaceHolder1.Controls.Add(uc.GetUserControl());
                //加空格
                this.PlaceHolder1.Controls.Add(new LiteralControl("&nbsp;&nbsp;"))
                  
            }
             
        }
    }
}

2.5 創建一個網頁.aspx,在此網頁中,我們引用用戶控件ascxa,還在拉一個銨鈕,和個Literal控件,銨鈕與Literal最開始狀態是隱藏的,主要是用來獲取數據與顯示數據。

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="TestUserControl1.aspx.cs" Inherits="Web.TestUserControl1" %>

<%@ Register Src="~/UserControl/AscxA.ascx" TagPrefix="uc1" TagName="AscxA" %>


<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
</head>
<body>
   <uc1:AscxA runat="server" id="AscxA" />
    <br />

   <asp:Button ID="btnShowBContents" runat="server" Text="顯示用戶控件B中的值" Visible="false"/>
    <br />
    <asp:Literal ID="LiteralResult" runat="server" Visible="false"></asp:Literal>
</body>
</html>

引用完控件以後,會多兩行這個代碼

<%@ Register Src="~/UserControl/AscxA.ascx" TagPrefix="uc1" TagName="AscxA" %>

用戶自定義控件的相對路徑,和名字

<uc1:AscxA runat="server" id="AscxA" />

2.6 在Ascx A用戶控件,當有動態產生Ascx B控件之後,在網頁的Button才會顯示。如果沒有產生過銨鈕,網頁Button就是隱藏起來。
由於是否有控件產生是發生在ascx A用戶控件,而隱藏的對象在網頁上。這涉及到用戶控件與網頁之間的溝通與協調。
為了減低程序的復雜度,創建一個接口,這個接口主體只有一個只寫屬性。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Web.Interface
{
   public interface IShowable
    {
        bool Show { set; }
    }
}

2.7 接口寫好了,我們在網頁.aspx.cs實作這個接口。說明白一點,就是網頁的銨鈕只接受顯示與隱藏,是誰來決定顯示與隱藏,它管不了。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Web.Interface;

namespace Web
{
    public partial class TestUserControl1 : System.Web.UI.Page,IShowable
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        protected void btnShowBContents_Click(object sender, EventArgs e)
        {

        }

        public bool Show
        {
            set { this.btnShowBContents.Visible = value; }
        }
    }
}

2.8 具體是誰來控制顯示與隱藏呢,剛才所說,是在用戶控件ascx A的動態產生ascx B之後,這個網頁的Button就顯示。因此,我們去用戶控件ascx a的產生控件代碼中添加:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Web.Interface;

namespace Web.UserControls

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

        protected void BtnGenerate_Click(object sender, EventArgs e)
        {
            if (ViewState["yk"] == null)
            {
                ViewState["yk"] = true;
                DynamicGenerate();
            }
        }

        private void DynamicGenerate()
        {
            //獲取文本框的值
            int j = 1;
            Int32.TryParse(this.txtA.Text.Trim(),out j);

            for (int i = 0; i < j; i++)
            {
                //動態加載AscxB後,並轉化為接口 -- 如果直接接受呢?
               IUserControl uc = (IUserControl)this.LoadControl("~/AscxB.ascx");
                //加載接口
               this.PlaceHolder1.Controls.Add(uc.GetUserControl());
                //加空格
                this.PlaceHolder1.Controls.Add(new LiteralControl("&nbsp;&nbsp;"))
                  
            }
             ((IShowable)this.Page).Show = true;
        }
    }
}

2.9有點疑問,怎樣能把網頁轉為接口呢? 因為我們上面有把網頁實現了IShowable這個接口。


Ok, 我們回到網頁cs,準備寫銨鈕click事件,來獲取數據。不過獲取數據起來,是有點困難,因為動態產生的控件,全是在用戶控件ascx A中呈現,而且每呈現的文本框是來自ascx B。
在網頁中,怎樣獲取用戶控件的ascx A的容器PlaceHolder呢? 還是寫另外一個接口,是為了讓網頁.aspx.cs去讀取用戶控件的Ascx A的PlaceHolder。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.UI.WebControls;

namespace Web.Interface
{
   public interface IPlaceHolderable
    {
       PlaceHolder GetPlaceHolder();
    }
}

2.10 用戶控件ascx A實用這個接口:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Web.Interface;

namespace Web.UserControls

{
    public partial class AscxA : System.Web.UI.UserControl,IPlaceHolderable
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            DynamicGenerate();
        }

        protected void BtnGenerate_Click(object sender, EventArgs e)
        {
            if (ViewState["yk"] == null)
            {
                ViewState["yk"] = true;
                DynamicGenerate();
            }
        }

        private void DynamicGenerate()
        {
            //獲取文本框的值
            int j = 1;
            Int32.TryParse(this.txtA.Text.Trim(),out j);

            for (int i = 0; i < j; i++)
            {
                //動態加載AscxB後,並轉化為接口 -- 如果直接接受呢?
               IUserControl uc = (IUserControl)this.LoadControl("~/AscxB.ascx");
                //加載接口
               this.PlaceHolder1.Controls.Add(uc.GetUserControl());
                //加空格
               this.PlaceHolder1.Controls.Add(new LiteralControl("&nbsp;&nbsp;"));
                  
            }
            //設置 頁面按鈕顯示
             ((IShowable)this.Page).Show = true;
        }
        /// <summary>
        /// 實現接口 IPlaceHolder()
        /// </summary>
        /// <returns></returns>
        public PlaceHolder GetPlaceHolder()
        {
            return this.PlaceHolder1;
        }
    }
}

2.11 這樣子,我們就可以在網頁.aspx.cs的獲取值的銨鈕獲取這個容器了。另外,由於容器根據用戶的需求,也許不止單一次產生一個ascx B用戶控件,也許會有好幾個。我們怎樣知道哪一個文本框TextBox是哪一個TextBox呢?
還是寫一個接口吧,

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.UI.WebControls;

namespace Web.Interface
{
   public interface ITextBoxable
    {
       TextBox GetTextBox();
    }
}

2.12 讓用戶控件AscxB來實現

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Web.Interface;

namespace Web.UserControls
{
    public partial class AscxB : System.Web.UI.UserControl, Web.Interface.IUserControl,ITextBoxable
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        public UserControl GetUserControl()
        {
            return this;
        }

        public TextBox GetTextBox()
        {
            return this.txtB;
        }
    }
}

2.13 到現在為止,我們完全可以去網頁代碼中,去寫銨鈕的Click獲取值的事件了:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Web.Interface;

namespace Web
{
    public partial class TestUserControl1 : System.Web.UI.Page,IShowable
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        protected void btnShowBContents_Click(object sender, EventArgs e)
        {
            //01 獲取placeholder容器
            IPlaceHolderable ascxA = (IPlaceHolderable)this.AscxA;
            PlaceHolder ph = ascxA.GetPlaceHolder();
            //PlaceHolder ph = this.AscxA.GetPlaceHolder();

            //02 顯示文本框的值
            string str = string.Empty;

            foreach (Control item in ph.Controls)
            {
                if (item is ITextBoxable)
                {
                    ITextBoxable txt = (ITextBoxable)item;
                    str += txt.GetTextBox().Text.Trim()+"<br/>";
                }
                if (str.Length>0)
                {
                    this.LiteralResult.Visible = true;
                    this.LiteralResult.Text = str;
                }
            }
        }

        public bool Show
        {
            set { this.btnShowBContents.Visible = value; }
        }
    }
}

2.4 註意

技術分享

技術分享

步步為營-83-用戶控件