Toon posts:

[ASP.NET] Web User Control problemen

Pagina: 1
Acties:

Verwijderd

Topicstarter
Om ASP.NET onder de knie te krijgen heb ik een hobby project bedacht. Om zo veel mogelijk te leren en om efficient mogelijk te coden wil ik alle mogelijkheden van .NET die nuttig zijn gebruiken. Ik ontwikkel met Visual Studio.Net in C# en gebruik een MSDE 2000 database.

Nu moet ik op een aantal formulieren hetzelfde dropdown lijstje tonen. In dit lijstje moeten een aantal namen uit de database getoond worden, met als value het ID. Ook moet aan de hand van een kolom 'Default' in de database als default 1 van de waarden gekozen worden. Dit was al snel gemaakt. Ik weiger echter (om eerder genoemde reden) om zomaar code te copy-en van formulier naar formulier, dus besloot een Web User Control te maken.

Ik heb in mijn Solution een Web Control Library project ASPTestControls toegevoegd. Daarin heb ik 1 Web User Control aangemaakt, met de volgende inhoud:
DomainList.ascx:
C#:
1
2
3
4
<%@ Control Language="c#" AutoEventWireup="false" 
Codebehind="DomainList.ascx.cs" Inherits="ASPTestControls.DomainList" 
TargetSchema="http://schemas.microsoft.com/intellisense/ie5" debug="False"%>
<asp:dropdownlist id="ddlDomains" runat="server"></asp:dropdownlist>

DomainList.ascx.cs:
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
namespace ASPTestControls
{
    using System;
    using System.Data;
    using System.Drawing;
    using System.Web;
    using System.Web.UI.WebControls;
    using System.Web.UI.HtmlControls;
    // added later
    using System.Data.SqlClient;    // SQL Database connections

    /// <summary>
    ///     Summary description for DomainList.
    /// </summary>
    public abstract class DomainList : System.Web.UI.UserControl
    {
        protected System.Web.UI.WebControls.DropDownList ddlDomains;

        private void Page_Load(object sender, System.EventArgs e)
        {
            // Put user code to initialize the page here
        }

        private void ddlDomains_Load(object sender, System.EventArgs e)
        {
            // in the Load event, load Items collection with domains from database, only if the page is NOT a postback
            if (!Page.IsPostBack) 
            {
                SqlConnection mySqlConnection = 
                    new SqlConnection("server=(local)\\VSdotNet;database=ASPTest;Trusted_Connection=yes");
                SqlCommand mySqlCommand = new SqlCommand("select * from tblDomain", mySqlConnection);
                SqlDataReader myReader = null;
                ListItem listDomain = null;
                try 
                {
                    mySqlConnection.Open();
                    myReader = mySqlCommand.ExecuteReader();
                    ddlDomains.DataSource = myReader;
                    while (myReader.Read()) 
                    {
                        listDomain = new ListItem();
                        listDomain.Value = myReader["DomainID"].ToString();
                        listDomain.Text = myReader["DomainName"].ToString();
                        if (myReader["DefaultDomain"].ToString() == "1") 
                        {
                            listDomain.Selected = true;
                        }
                        ddlDomains.Items.Add(listDomain);
                    }
                } 
                catch (Exception exep) 
                {
                    Response.Write("Error: " + exep.Message);
                }
                finally
                {
                    if (myReader != null)
                        myReader.Close();

                    if (mySqlConnection.State == ConnectionState.Open)
                        mySqlConnection.Close();
                }
            }
        }
        #region Web Form Designer generated code
        override protected void OnInit(EventArgs e)
        {
            //
            // CODEGEN: This call is required by the ASP.NET Web Form Designer.
            //
            InitializeComponent();
            base.OnInit(e);
        }
        
        ///     Required method for Designer support - do not modify
        ///     the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.ddlDomains.Load += new System.EventHandler(this.ddlDomains_Load);
            this.Load += new System.EventHandler(this.Page_Load);

        }
        #endregion
    }
}

Vervolgens heb ik in mijn oorspronkelijke project een reference gezet naar mijn Web Control Library, en aan een pagina de volgende regels toegevoegd:
C#:
1
2
3
<%@ Register TagPrefix="ASPTestControls" Namespace="ASPTestControls" Assembly="ASPTestControls" %>
[...]
<ASPTestControls:DomainList id="ddlDomains2" runat="server" />

Als ik het project met die pagina als Start Page aanroep, krijg ik de volgende error:
Server Error in '/ASPTest' Application.
--------------------------------------------------------------------------------

Compilation Error
Description: An error occurred during the compilation of a resource required to service this request. Please review the following specific error details and modify your source code appropriately.

Compiler Error Message: CS0144: Cannot create an instance of the abstract class or interface 'ASPTestControls.DomainList'

Source Error:

Line 15: <P><asp:label id="lblMemberName" runat="server">Member name: </asp:label><asp:textbox id="txtMemberName" runat="server"></asp:textbox> @
Line 16: <asp:dropdownlist id="ddlDomains" runat="server"></asp:dropdownlist>
Line 17: <ASPTestControls:DomainList id="ddlDomains2" runat="server" />
Line 18: </P>
Line 19: <P><asp:label id="lblPassword" runat="server">Password: </asp:label><asp:textbox id="txtPassword" runat="server" TextMode="Password"></asp:textbox></P>

Source File: http://localhost/ASPTest/login.aspx Line: 17
Ik heb geen flauw idee wat ik verkeerd doe. Het merkwaardige is dat deze Web User Control wel werkt als ik hem onderdeel van het project maak, en direct naar de control file (.ascx) verwijs in de @Register tag. Alleen in dat geval krijg ik in design time in Visual Studio een error, en werkt IntelliSense e.d. er niet mee, en ik vind dat ook geen echt nette manier van werken.

Heeft er iemand ervaring met het ontwikkelen van Web User Controls in Web Control Libraries, waarbij gebruik wordt gemaakt van een standaard Web Control? Zo ja .... helluppie! (Sorry voor de grote lap code + text, ik heb alles we voor de volledigheid maar even bijgezet.)

  • tomato
  • Registratie: November 1999
  • Niet online
Waarom heb je er een abstract class van gemaakt? Ik heb verder geen idee of dan wel alles klopt, maar wanneer je 'abstract' weg laat krijg je vast deze error al niet meer ;)

Verwijderd

Topicstarter
/me grumbles
Crap ... ik dacht dat ik niet goed zocht ofzo, maar het blijkt niet zo te horen.

Je kan op 2 manieren een Web User Control maken:
1) Een Web User Control toevoegen aan een ASP.NET Web Application project. In dit geval krijg je een .ASCX file, waarin je kunt tekenen, en evt. in een code behind pagina in kan coden.
2) Een Web Control Library maken, en daarin een Web User Control maken. In dit geval krijg je alleen een .cs file om in te coden, en moet je dus ook de HTML UI via een methode .render gaan invullen.

Wat ik had gedaan is iets via methode 1 maken, en dan op manier 2 proberen te gebruiken, maar dit gaat dus niet. Je moet in dat geval zelfs van een andere class overerven.

Waarom abstract? Omdat dat via methode 1 gemaakt wordt zo gemaakt wordt in de standaard template, en dat werkt dus. Raar maar waar ...

Enniewee, dit gaat niet werken zo. Ik vraag me af of ik via methode 2 ipv van een generieke WebControl class (System.Web.UI.WebControls.WebControl) kan erven van de DropDownList class (System.Web.UI.WebControls.DropDownList), en vanaf daar verder invullen.

edit:
Hmmmmz ... dat werkt, maar ik krijg nog steeds design time errors. Dit doet met denken aan ActiveX control gedoe in VB6 :(

  • gorgi_19
  • Registratie: Mei 2002
  • Laatst online: 10:27

gorgi_19

Kruimeltjes zijn weer op :9

Ik ken C# niet zo heel goed; maar waarom inherit je een usercontrol als je een webcontrol nodig hebt (en inherit je dus geen webcontrol?)

In ieder geval; ik ben laatst bezig geweest om ASP.Net Forums om te zetten naar VB.Net en kwam deze methode ook bezig. Ik zal hier een voorbeeldje posten van een stuk code. Het geeft wel een idee.

Het zo ook best kunnen zijn dat dit methode 3 is.. :P Het mooie van deze methode vind ik dat je niet perse gebonden bent aan controlnamen; of je zoekt deze op
(Je creeert een variabele X met als inhoud een Page.LoadControl, waarin je een .ascx laadt (zonder code-behind). Vervolgens kan je hierin een control zoeken door X.Controls.FindControl("controlnaam") te zoeken.

Een andere mogelijkheid is zelf een control aan te maken en deze toe te voegen. (Zoals nu ook gebeurd in het voorbeeld)

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
using System;
using System.Drawing;
using System.Collections;
using System.Collections.Specialized;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using AspNetForums;
using AspNetForums.Components;
using System.ComponentModel;
using System.IO;

namespace AspNetForums.Controls {

    /// <summary>
    /// This Web control displays the posts for a particular forum.  The posts are displayed in
    /// a format either specifically indicated by the programmer utilizing this Web control or by
    /// the Web visitor's Forum Display settings.  The posts shown are the posts for the forum that
    /// fall within a certain date range, which can be specified via the Forum Administration Web page.
    /// </summary>
    /// <remarks>When using this control you must set the ForumID property to the forum's posts you
    /// wish to display.  Failure to set this property will result in an Exception.</remarks>
    [
    ParseChildren(true)
    ]
    public class JumpDropDownList : WebControl, INamingContainer {


        string displayText = "Jump to: ";
        User user;

        // *********************************************************************
        //  CreateChildControls
        //
        /// <summary>
        /// This event handler adds the children controls and is resonsible
        /// for determining the template type used for the control.
        /// </summary>
        /// 
        // ********************************************************************/ 
        protected override void CreateChildControls() {
            DropDownList locations;
            Label description;

            // Do we have a user?
            user = Users.GetLoggedOnUser();

            // Create a new drop down list
            locations = new DropDownList();
            locations.AutoPostBack = true;
            locations.SelectedIndexChanged += new System.EventHandler(Location_Changed);
            locations.DataSource = Locations();
            locations.DataTextField = "Text";
            locations.DataValueField = "Value";
            locations.DataBind();

            // Create a new label
            description = new Label();
            description.CssClass = "normalTextSmallBold";
            description.Text = DisplayText + " ";

            Controls.Add(description);
            Controls.Add(locations);
        }

        // *********************************************************************
        //  Location_Changed
        //
        /// <summary>
        /// User wants to jump to a new location
        /// </summary>
        /// 
        // ********************************************************************/ 
        private void Location_Changed(Object sender, EventArgs e) {

            DropDownList jumpLocation = (DropDownList) sender;
            string jumpValue = jumpLocation.SelectedItem.Value;

            if (jumpValue.StartsWith("/")) {
                Page.Response.Redirect(jumpValue);
            } else if (jumpValue.StartsWith("g")) {
                int forumGroupId = 0;
                forumGroupId = Convert.ToInt32(jumpValue.Substring(jumpValue.IndexOf("-") + 1));
                Page.Response.Redirect(Globals.UrlShowForumGroup + forumGroupId);
            } else if (jumpValue.StartsWith("f")) {
                int forumId = 0;
                forumId = Convert.ToInt32(jumpValue.Substring(jumpValue.IndexOf("-") + 1));
                Page.Response.Redirect(Globals.UrlShowForum + forumId);
            } else {
                Page.Response.Redirect(Globals.ApplicationVRoot);
            }

            // End the response
            Page.Response.End();
        }

        // *********************************************************************
        //  Locations
        //
        /// <summary>
        /// Populates the locations dropdown with various location options
        /// </summary>
        /// 
        // ********************************************************************/ 
        private ListItemCollection Locations() {
            Forums forums = new Forums();
            ListItemCollection options = new ListItemCollection();

            options.Add(new ListItem("Please select"));
            options.Add(new ListItem("---------------------"));
            options.Add(new ListItem("Forums Home", Globals.UrlHome));
            options.Add(new ListItem("Search Forums", Globals.UrlSearch));
            options.Add(new ListItem("Member List", Globals.UrlShowAllUsers));
            if (user != null)
                options.Add(new ListItem("Edit My Profile", Globals.UrlEditUserProfile));
            options.Add(new ListItem("---------------------"));

            if (user != null)
                forums.ForumListItemCollection(user.Username, Forums.ForumListStyle.Nested, options);
            else
                forums.ForumListItemCollection(null, Forums.ForumListStyle.Nested, options);

            return options;
        }

        // *********************************************************************
        //  DisplayText
        //
        /// <summary>
        /// Text preceding the drop down list of options
        /// </summary>
        /// 
        // ********************************************************************/ 
        public string DisplayText {
            get { return displayText;  }
            set { displayText = value; }
        }

    }
}

Digitaal onderwijsmateriaal, leermateriaal voor hbo


Verwijderd

Topicstarter
AspNetForums moet ik nog eens bekijken. Ik heb het geinstalled, maar de email doet het niet om een nog onduidelijke reden. Die source is zeker bruikbaar, maar zal volgens mij ook weer leiden tot dezelfde design time problems die ik nu heb. Ik zal er later nog eens naar kijken. Voorlopig heb ik het als volgt opgelost:
1) een PlaceHolder gezet op de plaats waar de DropDownList moet komen te staan
2) een Web User Control toegevoegd zoals omschreven volgens methode 2 in mijn tweede post, met als source code zoals in de eerste post
3) op de volgende manier zet ik in het Page_Load event het control neer op de webpagina:
C#:
1
2
Control domains = LoadControl("./controls/DomainList.ascx");
DomainListPlaceHolder.Controls.Add(domains);

Het werkt, is redelijk efficient, en ik wil me hier niet op stuk bijten terwijl er ook nog zat andere nieuwe dingen te leren zijn, dus laat het er verder even bij.

Tot nu toe bedankt, en ervaringen & tips blijven wel welkom natuurlijk. :)