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.
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.
The control is declared as:
<%# Register TagPrefix="filters"
and in the markup
<filter:IntFilter
These must match.
You are registering a different prefix from the one you're attempting to use.
You can either change this:
<filter:IntFilter ID="IntFilter1" runat="server" />
to this:
<filters:IntFilter ID="IntFilter1" runat="server" />
Or change this:
<%# Register TagPrefix="filters" TagName="IntFilter"
to this:
<%# Register TagPrefix="filter" TagName="IntFilter"
Close Visual Studio, delete the schema cache, and re-open Visual Studio. You can find the schemas under something like:
C:\Users\Pavel\AppData\Roaming\Microsoft\VisualStudio\10.0\ReflectedSchemas
It is safe to delete all files in this folder.
Delete the contents of that above folder, and all is well.
Related
I have a UserControl named SlidingScaleTableReadonly with a bindable public member ScaleEntries, which take a List of struct instances. In the parent page, these lists are stored in a dictionary (InsulinSlidingScaleProtocolEntries), and I must render one SlidingScaleTableReadonly for each entry in this dictionary. Here's my template code so far:
<%# Register TagPrefix="uc" TagName="SlidingScaleTableReadonly" Src="~/Patient/SlidingScaleTableReadonly.ascx" %>
<asp:Content ContentPlaceHolderID="phContent" runat="server">
<h1>Échelles</h1>
<% For Each drug In InsulinSlidingScaleProtocolEntries %>
<h2><%= drug.Key %></h2>
<uc:SlidingScaleTableReadonly runat="server" ScaleEntries="<%# drug.Value %>" />
<% Next %>
</asp:Content>
My problem is at line 7:
BC30451 'drug' is not declared. It may be inaccessible due to its protection level.
If I replace drug.Value with a property available in code behind, the new variable can be found. I'm guessing it's not possible to directly data-bind local variables in ASPX? If that's the case, how can I use data-binding inside an iteration?
Edit - Changing the provenance of the bound value
I've changed the code a bit. Right after the "For Each" loop opening, a code-behind property named CurrentDrug is reassigned with the value of drug.Value, and uc:SlidingScaleTableReadonly get it's ScaleEntry from that new property. But that doesn't work either, the reassignment won't do shuck and ScaleEntry is always Nothing (or whatever initial value I gave to CurrentDrug).
Here's the new template:
<%# Register TagPrefix="uc" TagName="SlidingScaleTableReadonly" Src="~/Patient/SlidingScaleTableReadonly.ascx" %>
<asp:Content ContentPlaceHolderID="phContent" runat="server">
<h1>Échelles</h1>
<% For Each drug In InsulinSlidingScaleProtocolEntries
CurrentDrug = drug.Value %>
<h2><%= drug.Key %></h2>
<uc:SlidingScaleTableReadonly runat="server" ScaleEntries="<%# CurrentDrug %>" />
<% Next %>
</asp:Content>
And code-behind:
Public CurrentDrug As List(Of ScaleEntry)
Public Property InsulinSlidingScaleProtocolEntries As Dictionary(Of String, List(Of ScaleEntry))
'...
End Property
Edit - (Not) a solution: Stopped using aspx templates
I have to move on, and it seems like I'm not going to do any progress with aspx templates. I've rewritten the page so the UserControl is declared and inserted in code-behind. I think that's not how one should build an interface, that's not where that kind of logic should be place but I really want to move on.
Here's the new template code:
<asp:Content ContentPlaceHolderID="phContent" runat="server">
<h1>Échelles</h1>
<div id="scaleContainer" runat="server"></div>
</asp:Content>
Code-behind:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
For Each prescription In InsulinSlidingScaleProtocolEntries
Dim label As New HtmlGenericControl("h2") With {
.InnerText = prescription.Key
}
Dim table = CType(Page.LoadControl("~/Patient/SlidingScaleTableReadonly.ascx"), SlidingScaleTableReadonly)
table.ScaleEntries = prescription.Value
scaleContainer.Controls.Add(label)
scaleContainer.Controls.Add(table)
Next
End Sub
If you have a better solution, I'll be happy to see it.
I have 2 ASP controls in a page called Play.aspx:
<asp:TextBox ID="txtGuess" runat="server"></asp:TextBox>
<asp:Button ID="Button1" runat="server" Text="Submit Guess" OnClick="PostGuess" />
The code at the top of my page is:
<%# Page Language="VB" AutoEventWireup="false" Debug="false" Inherits="Play" CodeFile="Play.aspx.vb" %>
In the CodeFile (Play.aspx.vb) I have a procedure called PostGuess which tries to reference the TextBox using the code: txtGuess.text
Visual Studio 2008 gives this error: Name 'txtGuess' is not declared.
When I access the page in a browser, I get: 'txtGuess' is not declared. It may be inaccessible due to its protection level.
This is the contents of the Play.aspx.designer.vb:
Option Strict On
Option Explicit On
Partial Public Class Play
Protected WithEvents Head1 As Global.System.Web.UI.HtmlControls.HtmlHead
Protected WithEvents form1 As Global.System.Web.UI.HtmlControls.HtmlForm
Protected WithEvents ScriptManager1 As Global.System.Web.UI.ScriptManager
Protected WithEvents LoginView1 As Global.System.Web.UI.WebControls.LoginView
End Class
It might be an easy fix, I am not very good at this, please help!
Declaring
Protected WithEvents txtGuess As Global.System.Web.UI.WebControls.TextBox
in the Play.aspx.vb file should be the ticket.
My web control doesn't appear in my web page in a different folder,
However it works in another web page in the same location.
My source code is like this :
..
<%Register src="~/UI/Human/HumanUserControl.wuc" TagPrefix="uc1"
TagName="HumanUserControl"/>
...
<uc1:HumanUserControl runat="Server" id="HumanUserControl"/>
...
Error:
Request is not available in this context
The syntax on your Register tag is incorrect. And I'm not sure why you're using a ".wuc" extension instead of the default ".ascx".
You need matching <% %> tags, like so:
<%# Register Src="~/UI/Human/HumanUserControl.wuc" TagPrefix="uc1" TagName="HumanUserControl" %>
If you delete the <%Register .../> and <uc1 .../> tags from your page completely, then in Visual Studio, drag-and-drop the user control from the Solution Explorer directly onto your page wherever you want the control to appear, it will automatically add the correct Register and user control tags for you.
If this doesn't clear things up, then provide more detailed error information, including the code where the exception is thrown.
The following works just fine:
~/UI/Human/HumanUserControl.ascx
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="HumanUserControl.ascx.cs" Inherits="UserControlTest.UI.Human.HumanUserControl" %>
<asp:Label ID="lblTest" runat="server" />
~/UI/Human/HumanUserControl.ascx.cs
namespace UserControlTest.UI.Human
{
public partial class HumanUserControl : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
lblTest.Text = Request.Browser.Browser;
}
}
}
~/Default.aspx
<%# Page Title="Home Page" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="UserControlTest._Default" %>
<%# Register Src="~/UI/Human/HumanUserControl.ascx" TagPrefix="uc1" TagName="HumanUserControl" %>
<asp:Content runat="server" ID="BodyContent" ContentPlaceHolderID="MainContent">
<uc1:HumanUserControl runat="server" id="HumanUserControl" />
</asp:Content>
I try to create custom control, loaded dynamically from .vb code.
Here is my custom control "ControlCar" in file "controlcar.ascx"
<%# Control Language="VB" ClassName="ControlCar" %>
<script runat="server">
Private m_car As Car = Nothing
Public Property Car() As Car
Get
Car= m_car
End Get
Set(ByVal value As Car)
m_car = value
End Set
End Property
Protected Sub Panel_OnLoad(ByVal sender As Object, ByVal e As System.EventArgs)
If Me.m_car Is Nothing Then
lit_color.Text = "(m_car Is Nothing)"
Else
lit_color.Text = "color of Me.m_car is (" & Me.m_car.Color & ")"
End If
End Sub
</script>
<asp:Panel ID="panel" OnLoad="Panel_OnLoad" runat="server">
this is a car<br />
color = <asp:Literal ID="lit_color" runat="server"></asp:Literal><br />
<br />
</asp:Panel>
Here is my ASP web page in file "cars.aspx" which use .vb code for events, ...
<%# Page Language="vb" Explicit="true" Inherits="PageBase" Src="/code/cars.vb"%>
<html>
<body>
<!-- Html code here --->
<asp:panel ID="panel_cars" runat="server">
</asp:panel>
</body>
And here is my .vb code in file "cars.vb"
Private Sub CreateCar()
Dim car As Car = new Car()
Dim control As ControlCar = Nothing
control= CType(LoadControl("/code/controlcar.ascx"), ControlCar)
control.Car = car
panel_cars.Controls.Add(control)
End Sub
But it fails, saying 'ControlCar' is unrecognized in cars.vb.
I know it works, if move .vb code in .aspx file and using directive
<%# Register TagPrefix="uc" TagName="ControlCar" Src="/code/controlcar.ascx" %>
But I need to separate .vb code and .aspx code like in my example.
How can I make recognizing 'ControlCar' type (defined in .ascx) in .vb file?
You need to add some kind of reference. You can use a reference directive:
<%# Reference Control="controlcar.ascx" %>.
The control is being dynamically compiled. If you have no reference, the compiler has no idea what you are trying to use.
EDIT:
You may be able to use:
Imports ASP.controlcar_ascx
If the reference must be in the code behind. I have had issues with this in the past though.
I'm trying to inject an asp.net classic web control to my asp.net mvc application. This control doesn't use view state or post back so it works fine.
But I can't plug a real-time provided value in its attribute. This code
<my:Control runat="server" Tag="<%: Model.ID %>" />
ends up with the tag value just set explicitly to "<%: Model.ID %>".
Is there a way to make it work?
I believe the syntax is as follows:
<my:Control runat="server" Tag="<%# Model.ID %>" />
The other gotcha is you must call .DataBind() on the Control at some point after the Control has been initialized. This probably means taping into the Page_Load or OnInit events of the Page.
<%# Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %>
<script runat="server">
protected override void OnInit(EventArgs e)
{
this.Label1.DataBind();
base.OnInit(e);
}
</script>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Home Page
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2><%= Html.Encode(ViewData["Message"]) %></h2>
<asp:Label ID="Label1" runat="server" Text="<%# DateTime.Now %>" />
</asp:Content>
Or, if you have access to the source, you could add a call to .DataBind() somewhere before the final Render. You would have to experiment with that.
Hope this helps.
Well, seems like the only way to do this is injecting code the control renders to the page directly. In my case the control renders a silverlight object with some javascript so I put it at the page as is.