Search code examples
asp.netvb.netvisual-studio-2010webusercontrol

Using ASPX Web User Control with Visual Studio 2010


I am trying to implement a Web User Control into one of my APSX pages but keep getting the following warning:

Element 'IntFilter' is not a known element. This can occur if there is a compilation error in the Web site, or the web.config file is missing.

The user control is defined in the same web project as the aspx page.

Question:
How do I resolve this warning (I do not want to move the control to a separate project)?
Also, what do I need to do to enable IntelliSense for this control so I can set its FilterTypeSelection property from ASPX?

Code for "~/FilterControls/IntFilter.ascx"

<%@ Control Language="vb" AutoEventWireup="false" CodeBehind="IntFilter.ascx.vb" Inherits="StaffSupport.Filters.IntegerFilter" %>
<asp:DropDownList ID="typeFilterDropDownList" runat="server">
    <asp:ListItem Selected="True"  Text ="Any"          Value="-1" />
    <asp:ListItem Selected="False" Text ="Equal"        Value= "0" />
</asp:DropDownList><br />
<asp:TextBox ID="TextBox1" runat="server" /><asp:CheckBox ID="CheckBox1" runat="server" Text="Inclusive" /><br />
<asp:TextBox ID="TextBox2" runat="server" /><asp:CheckBox ID="CheckBox2" runat="server" Text="Inclusive" /><br />

Code for "~/FilterControls/IntFilter.ascx.vb"

Namespace Filters
    Public Class IntegerFilter
        Inherits System.Web.UI.UserControl

        Public Enum NumberFilterTypes As SByte
            Any = -1
            Equals = 0
        End Enum

        Public Property FilterTypeSelection As NumberFilterTypes
            Get
                Dim value As SByte
                If Not  Integer.TryParse(typeFilterDropDownList.SelectedValue, value) Then
                    value = -1
                End If

                Return CType(value, NumberFilterTypes)
            End Get
            Set(value As NumberFilterTypes)
                typeFilterDropDownList.SelectedValue = CSByte(value)
            End Set
        End Property

        Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

        End Sub

    End Class
End Namespace

Code for "OpenCases.aspx"

<%@ Page Title="" Language="vb" AutoEventWireup="false" MasterPageFile="~/StaffSite.Master" CodeBehind="OpenCases.aspx.vb" Inherits="StaffSupport.OpenCases" %>
<%@ Register TagPrefix="filters" TagName="IntFilter" src="~/FilterControls/IntFilter.ascx" %>
<asp:Content ID="bodyContent" ContentPlaceHolderID="cphBody" runat="server">
    ID<br />
    <filters:IntFilter ID="IntFilter1" runat="server" />
</asp:Content>

Code for "OpenCases.aspx.vb"

    Public Class OpenCases
        Inherits System.Web.UI.Page
    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Page.ViewStateMode = UI.ViewStateMode.Disabled
    End Sub

Update 2012/02/21:
Fixed the "filters" vs "filter" miss match.

Also of note, if you drag the control from the Solution Explorer to the page in Design view it will add the references you need (though it was still generating the warning for me). If you drag it to the page in source view it will add an a tag with a href to the element.

Update 2012/02/21 b:
Found the solution, see my answer below.


Solution

  • Apparently you have to reference both the ASCX page and the assembly.
    If you drag the ASCX page from the "Solution Explorer" window to the Design view for the page you are editing it will add the reference for the ASCX page, but you will have to add the assembly reference manually.

    OpenCases.aspx

    <%@ Page Title="" Language="vb" AutoEventWireup="false" MasterPageFile="~/StaffSite.Master" CodeBehind="OpenCases.aspx.vb" Inherits="StaffSupport.OpenCases" %>
    <%@ Register Assembly="StaffSupport" Namespace="StaffSupport.Filters" TagPrefix="filters" %><%-- Assembly Reference --%>
    <%@ Register TagPrefix="filters" TagName="IntFilter" src="~/FilterControls/IntFilter.ascx" %>
    <asp:Content ID="bodyContent" ContentPlaceHolderID="cphBody" runat="server">
        ID<br />
        <filters:IntFilter ID="IntFilter1" runat="server" />
    </asp:Content>
    

    Note: beware of object type collisions. For example the following would also work:

    <%@ Page Title="" Language="vb" AutoEventWireup="false" MasterPageFile="~/StaffSite.Master" CodeBehind="OpenCases.aspx.vb" Inherits="StaffSupport.OpenCases" %>
    <%@ Register Assembly="StaffSupport" Namespace="StaffSupport.Filters" TagPrefix="pre1" %><%-- Assembly Reference --%>
    <%@ Register TagPrefix="pre2" TagName="IntFilter" src="~/FilterControls/IntFilter.ascx" %>
    <asp:Content ID="bodyContent" ContentPlaceHolderID="cphBody" runat="server">
        ID<br />
        <pre1:IntFilter ID="IntFilter1" runat="server" />
    </asp:Content>
    

    This is why it started working for me Friday after I posted this, I had added a custom control which implemented System.Web.UI.WebControls.TextBox so I could drag and drop it from the Toolbox. Since it was in the same namespace the control added the assembly reference when it added the control to the page.

    Note: if you are referencing dll files which are contained in your project then you may need to remove the page registrations, build, then add the page registrations back. Otherwise the compiler may complain that the dll files are not in the bin.

    Update: 2013/04/18
    It appears you only need to add the assembly reference if the UserControl is not defined in the same namespace.

    • If the parrent is defined in Proj.Presentation and the UserControl is defined in Proj.Presentation then you should not need the assembly reference.
    • If the parrent is defined in Proj.Page and the UserControl is defined in Proj.Page.UserControl then you should not need the assembly reference.
    • If the parrent is defined in Proj.Page and the UserControl is defined in Proj.UserControl then you need the assembly reference.