Identifying all asp:Image controls in code behind - asp.net

I am trying to find all asp:Image controls in the vb.net code behind to dynamically set the ImageUrl to the same image file. This I can do seperately for each control, but writing 10+
imgQuestion.ImageUrl = cdn.Uri.ToString & "images/question.png" lines seems a little silly. I do not need to skip any image controls - every single one on the page will be changed. Is there any way to identify all of them without specifying each ID?
The IDs are not all named something similar, such as "Image1", "Image2" but rather "PaymentNote", "search", etc so I cannot loop through all the numbers with something like FindControl("Image" & controlNumber)
Is there another way to do this? I'd prefer to keep the image control IDs as something meaningful.

You can recursively use FindControl, starting from the Page and for each control check if it's an <asp:Image...
My own preferred language of choice is C#, so I won't be able to show a VB example. But here's a C# example:
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
ChangeImageUrls(Page);
}
private void ChangeImageUrls(Control ctrl)
{
foreach (Control subCtrl in ctrl.Controls)
{
if (subCtrl is Image)
{
((Image)subCtrl).ImageUrl = "...";
}
if (subCtrl.HasControls())
ChangeImageUrls(subCtrl);
}
}
}

Related

extending ASP.NET Page using MasterPage attributes as properties

I have an authentication roles-based system: different roles are redirected to different folders and in each folder there is a web.config that allows the access only to a particular username.
Few roles have the default page in common with a gridview that react in different ways depending on the role(different columns are shown, events trigger different methods, etc.).
so my problem is that everytime I need to make minor changes to a page I need to copy/paste the same changes to all the others default pages in the other folders.
In terms of code I solved by creating a DefaultFather class which extends System.Web.UI.Page and every other Default class inherits from DefaultFather. In this way, if I dont declare a Page-life-method, the DefaultFather method will be triggered.
but what about the graphic part(html, javascript, asp components, etc...)??
I created a NestedMasterPage just for the Default pages but everytime I need to change the appearance/behaviour of controls(gridview, buttons, linkbuttons) I must use the FindControl() method.
there isnt really another way to solve this problem?
Im thinking of using the Page_Load() method to search for each control with FindControl() and save them into attributes for later usage but it doesnt really look like a good solution.
It would be nice if I could use the masterpage components as properties but I think that in order to do that I should create public properties and I dont know if it will cause some kind of security problem.
any suggestion?
btw, if masterpage is the solution, should I remove the DefaultFather class and place the code directly into the masterpage? or is it a good idea to have another class just for the code?
I'd say there's nothing wrong with having both a master page and a base class for your page. They serve different purposes. The master page is generally all about layout, and the base class would be about page functionality.
If you want to manipulate the markup on your master page, rather than accessing the fields directly, I'd say create a logical function which does what you need it to do, and let the master page do it.
// Site.Master.cs
public void HideSubmitButton()
{
btnSubmit.Visible = false;
}
// Default.aspx.cs
protected void Page_Load(object sender, EventArgs e)
{
((SiteMaster)Master).HideSubmitButton();
}
I'd probably wrap that cast so you can use it more easily - that is something that would belong in your base class:
// DefaultFather.cs
protected new SiteMaster Master { get { return (SiteMaster)base.Master; } }
// Default.aspx.cs
Master.HideSubmitButton();
EDIT
Per your comment about attaching event handlers - if you need to attach events to objects that live on the master (which may not be a good idea - ideally the event handler for something living on the master lives on the master - but if you really need it) you can expose methods to do that as well, like:
// Site.Master.cs
public void AttachEventHandlerToGoButton(EventHandler eventHandler)
{
btnGo.Click += eventHandler;
}
// Default.aspx.cs
Master.AttachEventHandlerToGoButton(DoMyThing);
private void DoMyThing(object sender, EventArgs e) { }
or if you want to get fancy, write a wrapper event:
// Site.Master
<asp:Button ID="btnGo" runat="server" OnClick="btnGo_Click" />
// Site.Master.cs
public event EventHandler GoButtonClick;
protected void btnGo_Click(object sender, EventArgs e) {
if (GoButtonClick != null) {
GoButtonClick(sender, e);
}
}
// Default.aspx.cs
Master.GoButtonClick += DoMyThing;
private void DoMyThing(object sender, EventArgs e) { }
Also see my edit on the Master wrapper - you need the base. there to avoid a stack overflow.

asp.net treeview programmatically setting node color

I want to set the node colors of a treeview at runtime. I populate the treeview from a collection that has the parentid, childid, and description, and I've added a property representing the color I want applied to the node. FWIW the source is a database, the app is C#.
In a gridview I use RowDataBound() to programmatically affect the control. Im not sure how to do so in the treeview, including which event to use (DataBound()? TreeViewDataBound()?). My research has not been fruitful so far. A code snippet would be very useful.
Hopefully this will give you a raging clue.
When setting a node text, instead of setting
Node Text
set as
<div style='color: red'>Node Text</a>
you can use Prerender event:
protected void TreeView1_PreRender(object sender, EventArgs e)
{
if (IsPostBack) return;
foreach (TreeNode t in TreeView1.Nodes)
{
if (t.Value.EndsWith("1")) //Some Condition
{
string s = t.Text;
string fs = "<span style=\"color: #CC0000\">" + s + "</span>";
t.Text = fs;
}
}
}
Since .NET Framework 4.5 you can use these style properties:
TreeView.LevelStyles Property - represent the node styles at the
individual levels of the tree
TreeView.RootNodeStyle Property
TreeView.ParentNodeStyle Property
TreeView.LeafNodeStyle
Property
Assuming you are dealing with the standard TreeView control, you can do this in the TreeDataBound Event.
A brief example (not tested):
<asp:TreeView runat="server"
ID="tvMyTreeView"
OnTreeNodeDataBound="tvMyTreeView_TreeNodeDataBound"
/>
And the backend:
protected void tvMyTreeView_TreeNodeDataBound(object sender, TreeNodeEventArgs e)
{
DataRowView dr = (DataRowView)e.Node.DataItem;
e.Node.Style.Add("color", dr["COLOR"].ToString());
}
If you are using the Telerik RadTreeView, then the event name is NodeDataBound
You will probably have to tweak the example to better fit your needs, but hopefully this will get you started.

asp.NET how to change Session Language?

I am new to this and would like to create a few simple hyperlinks that change the session language parameter.
Then I will test against this parameter to show dynamically different page elements.
I have not been able to find any sort of tutorial discussing a simple solution for this, only full blown tutorials that are in depth with databases and everything.
I was hoping someone here might be able to simply lead me to a beginners tutorial on how to alter the Session language parameter?
Any help appreciated!
thanks in advance
Something along this line?
Thread.CurrentThread.CurrentCulture = new CultureInfo( "pt-BR", false );
You can learn more about it here:
Globalization and localization demystified in ASP.NET 2.0
Edit:
Based on your comment bellow I now understand better what you want to do.
For the link part you can use LinkButton in your .aspx page as:
<asp:LinkButton id="linkButton1"
runat="server"
OnCommand="LinkButton1_Click"
CommandArgument="pt-BR">Click Me for Portuguese from Brazil
</asp:LinkButton>
Now in your code-behind file .cs:
private void LinkButton1_Click(object sender, System.EventArgs e)
{
string language = e.CommandArgument.ToString();
if(language.Equals("pt-BR"))
{
// Place your logic here for Portuguese-Brazil... Show or hide DIV...
}
}
If you wanna use Session, do this:
To store the value in Session:
private void LinkButton1_Click(object sender, System.EventArgs e)
{
string language = e.CommandArgument.ToString();
Session["lang"] = language;
}
To read the value from Session:
if (Session["lang"] != null)
{
if(Session["lang"].ToString().Equals("pt-BR"))
{
// Place your logic here for Portuguese-Brazil... Show or hide DIV...
}
}

Is it possible to add a UserControl to a Composite control?

I'm trying to build a CompositeControl that's flexible. Depending on some of it's parameters, I would like my CompositeControl to load different user controls in it's CreateChildControls method. The exact UserControls aren't know at design time.
Just as a quick example, I tried with a "hard coded" UserControl and it failed:
protected override void CreateChildControls()
{
Control UserControlControl = Page.LoadControl(typeof(MyUserControl), null);
Controls.Add(UserControlControl);
Label RegularControl = new Label();
RegularControl.Text = "This gets displayed";
Controls.Add(RegularControl);
}
Is it possible to attain what I'm looking for?
Thanks
Try the following:
protected override void CreateChildControls()
{
Control UserControlControl = Page.LoadControl("~/path/to/control.ascx");
Controls.Add(UserControlControl);
}

Is it possible to make a gridview with a dropdownlist as one new control?

This is partly in reference to this:
Why isn't the SelectedIndexChanged event firing from a dropdownlist in a GridView?
I thought it different enough to ask another question.
My thought is that instead of adding a dropdownlist (ddl) to a gridview and then using the technique above that I could create a brand new control that has a ddl in it and the reference it directly.
This is more of a how do I create asp.net 2.0+ controls, I think, but is what I am asking possible? Can you make a "new" gridview control that just happens to always have a ddl in it and just refer to it (somehow) without findcontrol and all the rest?
I realize it would be highly customized for a unique app. I am just trying to see if it is possible as I may want to use this to create other controls.
Thank you.
It depends on your definition of a "new GridView". The answer is yet, but at a cost.
If you base your control on WebControl, you can write a new grid control with any functionality. Somehow, I don't think this is what you have in mind.
If you want to inherit from the existing GridView and add extra controls, then it is also doable, but with heavy limitations. The reason is because GridView's implementation breaks every possible guideline for extensibility. I guess because they never meant it to be extended. For instance, they clear Controls collection almost on every occasion and explicitly expect for the Controls[0] to be a Table. I suppose, if you decide to stay within confines of the table layout (header, footer and all), then you may have more room to play.
Finally, you could create a wrapper, which has a GridView as its private member and simply expose everything you may need plus more. But that gets ugly very quickly.
Here is a crude demonstration (working) of the second approach. Note that the drop down is at the end. You can override the Render method, but you'd have to recreate a lot of MS code.
ExtendedGridView
public class ExtendedGridView : GridView
{
protected DropDownList DropDown { get; set; }
public ExtendedGridView() : base()
{
this.DropDown = new DropDownList();
this.DropDown.Items.Add("white");
this.DropDown.Items.Add("red");
this.DropDown.Items.Add("blue");
this.DropDown.Items.Add("green");
this.DropDown.AutoPostBack = true;
this.DropDown.ID = "dropdown";
this.DropDown.SelectedIndexChanged += new EventHandler(DropDown_SelectedIndexChanged);
}
void DropDown_SelectedIndexChanged(object sender, EventArgs e)
{
BackColor = System.Drawing.Color.FromName(this.DropDown.SelectedValue);
}
protected override int CreateChildControls(System.Collections.IEnumerable dataSource, bool dataBinding)
{
int itemCount = base.CreateChildControls(dataSource, dataBinding);
Controls.Add(this.DropDown);
return itemCount;
}
}
SomePage.aspx
<%# Register TagPrefix="my" Namespace="MyProject" Assembly="MyProject" %>
<my:ExtendedGridView id="myGridView" runat="server" onpageindexchanging="myGridView_PageIndexChanging"></my:ExtendedGridView>
SomePage.aspx.cs
protected void Page_Load(object sender, EventArgs e)
{
myGridView.DataSource = new string[] { "aaa", "bbb", "ccc", "ddd", "eee" };
myGridView.AllowPaging = true;
myGridView.PageSize = 2;
myGridView.DataBind();
}
protected void myGridView_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
myGridView.PageIndex = e.NewPageIndex;
myGridView.DataBind();
}

Resources