One Hyperlink In Many Different Locations - asp.net

I'd like to implement a hyperlink in many locations on my website, however I just want to have it defined once not several times over. What is the best way to achieve this?
I started down the road of listing it in the node of web.config but I was only able to get that to list as a literal and wasn't successful in having it end up as a hyperlink.
I don't know much about master pages, but what I do know about them seems to me that they aren't the answer for this task because they wouldn't allow for that hyperlink to be located on some pages and not others and in different locations on some pages than others.
Help please! :)
I'm working in ASP.net VB.net

Put a HyperLink control on each page where you want it.
e.g. <asp:HyperLink runat="server" id="LogInLink">Login</asp:HyperLink>
Then either set the NavigateUrl property on the hyperlink in code-behind, e.g. this.LogInLink.NavigateUrl = Global.MySpecialUrl; or use <%=Global.MySpecialUrl%> notation to reference the value you want from your code in the NavigateUrl in the markup.
[Sorry, that's C# code]

You can create a custom control that inherits from HyperLink. This method will not require to use code-behind on individual pages but you will need to create a new class and modify your web.config file. Alter the namespaces as needed.
SpecialLink.vb
Namespace YourWebSite.Controls
Public Class SpecialLink
Inherits HyperLink
Public Sub New()
NavigateUrl = "~/SpecialLinkUri.aspx"
Text = "Special Link Text"
End Sub
End Class
End Namespace
web.config (add this to the system.web node)
This allows you to use this control on any page/master page/user control throughout your site
<pages>
<controls>
<add namespace="YourWebSite.Controls" tagPrefix="YourWebSite"/>
</controls>
</pages>
Using it on your page
<p>This is some text, here's the link: <YourWebSite:SpecialLink></YourWebSite:SpecialLink></p>
<p>This is some text, <YourWebSite:SpecialLink>here's the link</YourWebSite:SpecialLink>.</p>

Related

Accessing text boxes in a web control on a master page

I need to access multiple textboxes on a master page. The textboxes are declared in a separate web control and it won't let me call the names of the textboxes so I can populate them with data. I have multiple textboxes like I said, but for example, when I try to write to txtName it will not let me even though when I click on the Design View it says it is there.
Can anybody help me out?
Expose the text boxes inside the web control as properties.
In webcontrol.ascx
<asp:TextBox runat="server" id="txtName" />
In webcontrol.ascx.cs
public virtual TextBox TxtName { get {return txtName;} //note capitalization
Then do the same thing in the master page to expose the web control.
In masterpage.master
<uc1:MyWebControl runat="server" id="MyWebControl1" />
In mastermage.master.cs
public virtual MyWebControl myWebControl{get {return myWebControl1;}}
Then make your master page strongly typed from the content page by adding a MasterType directive.
In default.aspx
<%# MasterType TypeName="MyMasterPageClass" />
Then you can access it from your content page code behind. In default.aspx.cs
Master.myWebControl.TxtName.Text="Hello, world!";
The reason it's necessary to do this is that controls declared on .aspx, .ascx, and .master pages are protected instead of public and there's no way (as of right now) to change them that I'm aware of. So we can use properties to expose these controls as public.

Setting static variable in compiled ASP.NET

I have compiled ASP.NET dynamic page with editable aspx pages.
I would like to some links to be generated upon changing some static variable
What i did is edit:
web.config as follows:
<appSettings>
<add key="currentEnvironment" value="dev-"/>
</appSettings>
and then
edited aspx page as follows
Home
But there is nothing appened when i try and run the .aspx page. Please help
You can't put a server tag inside another tag's markup like that, but you can just use the value directly. If you remove it and change the # to a =, it will work.
Home
Although if you can access the code behind, that would be a much cleaner way to do it, as in:
<asp:HyperLink ID="_index" runat="server">Home</asp:HyperLink>
and then set value from code behind
_index.NavigateUrl = String.Format("http://{0}www.mysite.com/web/index.html", ConfigurationSettings.AppSettings["currentEnvironment"]);

Create a usercontrol instance programmatically in ASP.NET

I have a UserControl that I need to add dynamically. I tried to follow this MSDN article, but I'm not having any success....
http://msdn.microsoft.com/en-us/library/c0az2h86.aspx
The UserControl is basically an image gallery, and it loads some pictures based on an ID. My idea was to make this ID available as a property. Then when I create an instance of the control, I could set this ID and add it to the form.
I added a reference to the control in the .aspx page that will use it, like this:
<%# Reference Control="~/PictureGallery.ascx" %>
And in the UserControl I added a ClassName like this:
<%# Control Language="C#" AutoEventWireup="true" CodeFile="PictureGallery.ascx.cs"
Inherits="PictureGallery" ClassName="PictureGallery" %>
When I try to create an instance in the .aspx.cs like the article suggests, Dim gallery As ASP.PictureGallery, I get an "Type ASP.PictureGallery is not defined".
The article mentions a namespace, ASP, and I tried importing it to the .aspx.cs with no luck.
So, I'm not able to get a reference to the UserControl.
How can it be fixed?
It sounds like you are confusing two separate ways of working with a UserControl.
One way is to register the control on your page so that you can put it into the page at Design Time e.g.
<div>
<asp:PictureGallery id="myGallery" runat="server" MyProperty="SomeValue">
</asp:PictureGallery>
</div>
The second is programmatically (or dynamically) adding it into the page at runtime in your code behind. If so, then you need to use the LoadControl function which is mentioned in the sample. You do not need to register the control in the aspx file if you do this.
e.g.
Dim gallery as PictureGallery = LoadControl("~/PathToControl/gallery.ascx")
gallery.MyProperty = "SomeValue"
placeHolder.controls.add(gallery)
edit
What is the class name of the control in the code behind...something like this:
Partial Public Class MyControlsClassName
Inherits System.Web.UI.UserControl
That is the type you need to use when you declare it. Is it within a namespace perhaps?
I don't think you've placed the control in your code behind. You may well have created the reference, but do you have a tag such as <asp:PictureGalary id="gallary"></asp:PictureGalary> anywhere in your aspx?
The ASP namespace is generated at run time- user controls get "compiled" as they are used by .aspx pages so this is why you get the error message "Type ASP.PictureGallery is not defined".
When adding user controls dynamically you should use the Page.LoadControl method:
Page.LoadControl("~/PictureGallery.ascx")

Creating ASP.NET composite control. How to apply properties associated with SkinID?

I am creating a custom composite control based off of an asp:Label control. I'd like to be able to have the label's default properties be skinable as well as additional properties that I add to my control.
But when I add a skin definition to the Default.skin file in my themes directory, and add the control to my page with the SkinId specified, I cannot figure out how to get the control to render with the Skinned properties.
Additional points:
My custom control is defined in a separate library/dll.
I added one test property, and added the [Themeable(false)] attribute. Then I set that property in the .skin file. I didn't get any errors when I tried to view the page, so it appears to me that the .skin file is not getting applied or that the control def in the skin file doesn't get matched up with the control def in the aspx page.
From the skin file:
<ctrl:ExtendedLabel SkinId="test" runat="server"
Expandable="true" Lookup="true" Required="true"
RequiredCssClass="required" Text="Hello" />
From the aspx page:
<ctrl:ExtendedLabel SkinID="test" runat="server"/>
From web.config:
<pages>
<controls>
<add tagPrefix="ctrl" namespace="MyCompany.WebControls"
assembly="MyCompany.Web" />
</controls>
</pages>
I added a test property to the control, marked it as [Themeable(false)] in order to test if I'd get the runtime error when setting that property in the skin file. No error.
Notice that the pages tag doesn't have a styleSheetTheme attribute. I do however, have a Base page class that overrides StyleSheetTheme property, which seems to work for everything else.
If I add the styleSheetTheme attribute to the pages tag in web.config, the skin stuff works, including getting the error if I try to set the non-Themeable property.
What's the difference? How can I get it to work with the Base page class property code?
What are you getting when you try this? I just created a simple test project and was able to skin a custom property on a web custom control. My steps were:
Create the custom control.
Add [Themeable(true)] attribute to the class definition in the code-behind file.
Add a Label control to my custom control.
Add a property named "LabelText" to my custom control, which gets/sets the label controls Text value.
In web.config, add 'theme="TestTheme"' to the system.web/pages section.
In web.config, add '<add tagPrefix="mine" tagName="Test" src="~/UI/Test.ascx" />' to the system.web/pages/controls section.
In my Default.skin file, added '<mine:Test runat="server" LabelText="Test Text" />
In Default.aspx, added '<mine:Test id="test1" runat="server" />'
Load the page up and see the text "Test Text", which was only present in the Skin file.
Hopefully one of my steps above will be something you forgot, but if not, please update your question with details on what you are trying and what you are seeing.

FormView on a Master Page can't see databound controls through ContentPlaceHolder boundary

I have a number of similarly structured FormViews. In an effort to avoid duplicate markup, I've created a master page that contains the FormView, and placed a ContentPlaceHolder inside the FormView. The specific databound controls - which are the only thing that change from page to page - are then on the page that uses that master page.
So I have a master page that looks something like this:
<%# master ... %>
...
<form runat=server>
...
<asp:formview runat="server" ... >
<edititemtemplate>
... Lots of common markup ...
<asp:contentplaceholder id='FormRows' runat='server' />
... Lots more common markup ...
</edititemtemplate>
</asp:formview>
...
</form>
and a page using that master page that looks something like this:
<%# page masterpagefile="Form.Master" ... %>
<asp:content contentplaceholderid="FormRows" runat="server" >
...
<p>
Field One:
<asp:textbox runat=server text='<%#Bind("Field1")%>' id='Field1' />
</p>
<p>
Field Two:
<asp:textbox runat=server text='<%#Bind("Field2")%>' id='Field2' />
</p>
...
</asp:content>
With an existing record, the FormView sees through to the databound controls (Field1, etc) and populates them with the correct data. But when inserting or updating, it doesn't see them, and they're not included in the insert or update. In the FormView_ItemInserting event, e.Values is empty; likewise in the FormView_ItemUpdating event, e.NewValues is empty.
So:
Is there a way to provoke the FormView on the master page to see through to the databound controls inside the ContentPlaceholder?
Failing that, is there a straightforward way of identifying controls that are databound with <%#Bind(...)%> so that I can add them manually to the values bag?
There are a couple of things that come to mind why this setup will not work and may lead to more code than markup.
If you have a datasource defined in the master page it will not handle the different data bound controls from each page without adding more logic to the master page to change the query etc.
All form views will be coupled together increasing the complexity of changes down the road
I would go with separate pages for each FormView reducing the complexity of code, debugging and the ability to change
Just my two cents
I think this will prove difficult, if not possible; in fact I'm surprised that the databinding works at all!
You may want to try a different method of encapsulating your FormView control.
You could try placing the FormView control in an .ascx control with a PlaceHolder where you now have the ContentPlaceHolder.
Then on each ASPX page, you could have a mirror ASCX page that contains the filler for the placeholder. You could give them the same names (Page1.aspx uses Page1.ascx) or set up a naming convention like Page1-Content.ascx, so that your FormView ascx would figure out what it's filler control is named, use Page.LoadControl() to load the control by path, and plug that content in during the Init phase.
Now, your content controls have the advantage of being able to have public properties, so you could bind to those public properties, and have the properties shuttle the data to and from the appropriate server controls in the filler .ascx file.
Unfortunately it's double the files (because of the ASPX and ASCX required for each page) but fairly work-unintensive compared to the alternative (duplicating all that code)
Of course, you haven't told us what all your common markup is, but your common markup could go into a CommonMarkupHeader.ascx and CommonMarkupFooter.ascx as well and included on each page's unique FormView.
Where do you have server form tag? May be in content place holder insted of master page, so your values not send to server page after submit
You might be able to do something like this...
Define an interface for your "data pages" that has a method signature that returns a bindable data source..
public interface IFormViewChild {
IEnumerable GetFormData();
}
Then you can have your "data pages" implement that interface...
public class ChildDataPage : Page, IDataPage {
public IEnumerable GetFormData() {
// code to return stuff here
}
}
Finally, in your masterpage's Load() event...
if (Page is IFormViewChild) {
myFormViewControl.DataSource = ((IFormViewChild)Page).GetFormData();
myFormViewControl.DataBind();
}
Please keep in mind that this is all psudo code typed directly into this web form editor.. so it's probably wrong. But it might not be :)
Here's a provisional solution - not elegant, but it works. In the code-behind for Form.Master I have something along these lines:
Private Sub FormView1_ItemInserting(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.FormViewInsertEventArgs) Handles FormView1.ItemInserting
ManuallyAddValues(e.Values)
End Sub
Private Sub FormView1_ItemUpdating(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.FormViewUpdateEventArgs) Handles FormView1.ItemUpdating
ManuallyAddValues(e.NewValues)
End Sub
Private Sub ManuallyAddValues(ByRef Values As IOrderedDictionary)
For Each Field As Core.Field In FormView1.DataSourceControl.IncludedFields
If Values(Field.Name) Is Nothing Then
Dim DataboundControl As Control = FormView1.FindControl("FormRows").FindControl(Field.Name)
Values.Add(Field.Name, GetValue(DataboundControl))
End If
Next
End Sub
This isn't so elegant because
I have to know the names of all databound controls
This relies on the assumption that the ID of each control matches the fieldname
The 'GetValue' function (not included here) is a clumsy solution: it checks for various types (textbox, dropdownlist, checkbox, etc.) and gets the string value from the appropriate property (textbox.text, dropdownlist.selectedvalue, checkbox.checked, etc.).
I'd still love to at least have a way of knowing what's bound with the '<%#Bind("Foo")%>' syntax and getting that information directly.

Resources