Can't use Control.FindControl on dynamically created System.Web.UI.WebControl - asp.net

Why would the following code not work? I am creating a control, adding a child control and attempting to retrieve it by id using the .FindControl method.
[Test]
public void TryToFindControl()
{
var myPanel = new Panel();
var textField = new TextBox
{
ID = "mycontrol"
};
myPanel.Controls.Add(textField);
var foundControl = myPanel.FindControl("mycontrol");
// this fails
Assert.IsNotNull(foundControl);
}

Panel has not been added to Page yet, so you cannot use FindControl. Instead, you need to find it inside Panel.Controls
[TestMethod]
public void TryToFindControl()
{
var myPanel = new Panel();
var textField = new TextBox
{
ID = "mycontrol"
};
myPanel.Controls.Add(textField);
var foundControl = myPanel.Controls
.OfType<TextBox>()
.FirstOrDefault(x => x.ID == "mycontrol");
Assert.IsNotNull(foundControl);
}
Testing with Page
FindControl works only if container is added to Page.
public partial class Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
var myPanel = new Panel();
var textField = new TextBox
{
ID = "mycontrol"
};
myPanel.Controls.Add(textField);
Controls.Add(myPanel);
// foundControl is not null anymore!
var foundControl = myPanel.FindControl("mycontrol");
}
}

The control must be part of the server side Page control collection hierarchy to be found.
public void TryToFindControl()
{
var myPanel = new Panel();
// key line here
Page.Controls.Add(myPanel);
var textField = new TextBox
{
ID = "mycontrol"
};
myPanel.Controls.Add(textField);
var foundControl = myPanel.FindControl("mycontrol");
Assert.IsNotNull(foundControl);
}

First I'll start form the fact I don't know of System.UI.Control, Rather System.Web.UI.Control
Then I could not find TextField Control so I used Web TextBox instead. Please adjust your code as necessary. I also used VS Test attributes
[TestMethod()]
public void TryToFindControl()
{
var editContainer = new HtmlTableCell();
editContainer.Controls.Add(new TextBox
{
ID = "mycontrol",
});
System.Web.UI.Control foundControl = null;
foreach (System.Web.UI.Control ctrl in editContainer.Controls)
{
if (ctrl.ID == "mycontrol")
{
foundControl = ctrl;
break;
}
}
// This works
Assert.IsNotNull(foundControl);
}
Based on your exact wording, if you want to access the control you added, create an instance first as variable, so you can access it directly. Please keep in mind that I don't know what you are trying to achieve globally, so my answer(s) may not apply because of that, or there maybe be better solution.
[TestMethod()]
public void TryToFindControl()
{
var editContainer = new HtmlTableCell();
var foundControl = new TextBox
{
ID = "mycontrol"
};
editContainer.Controls.Add(foundControl);
// This works
Assert.IsNotNull(foundControl);
}

Related

How to categorize product by it's types in Asp.net using Webforms

I want to sort the products by their type, using dropdownlist.
products by types isn't working when i select it in dropdown list.
stored procedure of ProductByType:
Public List<Product> GetProductsByType(int typeId)
{
try
{
using (GarageDBEntities db = new GarageDBEntities())
{
//select * from table where condition is required type
List<Product> products = (from x in db.Products
where x.TypeId == typeId
select x).ToList();
return products;
}
}
catch (Exception)
{
return null;
}
}
Index page code to display products:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class Index : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
FillPage();
}
private void FillPage()
{
//Get a lsit of all products in DB
ProductModel productModel = new ProductModel();
List<Product> products = productModel.GetAllProducts();
//Make sure products exists in the database
if (products != null)
{
//Create a new Panel with an ImageButton and 2 labels for each Product
foreach (Product product in products)
{
Panel productPanel = new Panel();
ImageButton imageButton = new ImageButton();
Label lblName = new Label();
Label lblPrice = new Label();
//Set childControls properties
imageButton.ImageUrl = "~/Images/Products/" + product.Image;
imageButton.CssClass = "productImage";
imageButton.PostBackUrl = "~/Pages/Product.aspx?id=" + product.Id;
lblName.Text = product.Name;
lblName.CssClass = "productName";
lblPrice.Text = "₹" + product.Price;
lblPrice.CssClass = "productPrice";
//Add child controls to Panel
productPanel.Controls.Add(imageButton);
productPanel.Controls.Add(new Literal { Text = "<br />" });
productPanel.Controls.Add(lblName);
productPanel.Controls.Add(new Literal { Text = "<br />" });
productPanel.Controls.Add(lblPrice);
//Add dynamic Panels to static Parent panel
pnlProducts.Controls.Add(productPanel);
}
}
else
{
//No products found
pnlProducts.Controls.Add(new Literal { Text = "No Products Found!" });
}
}
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
ProductModel productModel = new ProductModel();
List<Product> products = productModel.GetProductsByType(Convert.ToInt32(DropDownList1.SelectedItem.Value));
foreach (Product product in products)
{
Panel productPanel = new Panel();
ImageButton imageButton = new ImageButton();
Label lblName = new Label();
Label lblPrice = new Label();
//Set childControls properties
imageButton.ImageUrl = "~/Images/Products/" + product.Image;
imageButton.CssClass = "productImage";
imageButton.PostBackUrl = "~/Pages/Product.aspx?id=" + product.Id;
lblName.Text = product.Name;
lblName.CssClass = "productName";
lblPrice.Text = "₹" + product.Price;
lblPrice.CssClass = "productPrice";
//Add child controls to Panel
productPanel.Controls.Add(imageButton);
productPanel.Controls.Add(new Literal { Text = "<br />" });
productPanel.Controls.Add(lblName);
productPanel.Controls.Add(new Literal { Text = "<br />" });
productPanel.Controls.Add(lblPrice);
//Add dynamic Panels to static Parent panel
pnlProducts.Controls.Add(productPanel);
}
}
}
It always showing all the products even tho when I select product type.
As shown in image, I selected "Engine Oil" but it showing all the products.
I want it to show particular products only of the selected product type chosen in dropdownlist.
Try add the PostBack validation in your Page_Load event:
C# Code:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
FillPage();
}
}
Most likely, when selecting an item in the dropdownlist, a postback is generated which will call PageLoad and reload all the products, to avoid this the PostBack validation is usually set
Make sure to use the AutoPostBack="True" flag in the <asp:DropDownList /> control

Label TextProperty CoerceValue delegate not called

I use Reflection to set the Label.TextProperty.CoerceValue to my custom delegate (TextProperty.CoerceValue are null by default)
but when Label text changed, the delegate are not called
the same strategy are apply/tried on Image.SourceProperty, Entry.TextProperty
all are called successful
is bug or Label.TextProperty by design will not call CoerceValue delegate?
thank you very much.
Xamarin.Forms 4.3.0.947036
var property = Label.TextProperty;
var coerceValue = property.GetType().GetProperty("CoerceValue", BindingFlags.NonPublic | BindingFlags.Instance);
oldDelegate = coerceValue?.GetValue(property) as BindableProperty.CoerceValueDelegate;
coerceValue?.SetValue(property, (bindable, value) => {
var modified = ModifyValue(value); // simply modify the value if required
return modified
});
If you want to call CoerceValue when Label.Text changed, I suggest you can use Bindable Properties to bind Label.TextPrperty.
public partial class Page9 : ContentPage
{
public static readonly BindableProperty labelvalueProperty = BindableProperty.Create("labelvalue", typeof(string), typeof(Page9), null , coerceValue: CoerceValue);
public string labelvalue
{
get { return (string)GetValue(labelvalueProperty); }
set { SetValue(labelvalueProperty, value); }
}
private static object CoerceValue(BindableObject bindable, object value)
{
string str = (string)value;
if(str=="cherry")
{
str = "hello world!";
}
return str;
}
public Page9 ()
{
InitializeComponent ();
label1.SetBinding(Label.TextProperty, "labelvalue");
labelvalue = "this is test";
BindingContext = this;
}
private void Btn1_Clicked(object sender, EventArgs e)
{
labelvalue = "cherry";
}
}
You can see the CoerceValue can be fired when Label.Text property changed.
I created a new Page Page1 in a Xamarin.Forms Project, with the following simple code in the code behind:
public Page1()
{
InitializeComponent();
}
protected override void OnAppearing()
{
Label l = new Label();
BindableProperty.CoerceValueDelegate d = (s, a) =>
{
string modified = "textY"; // simply modify the value if required
return modified;
};
var property = Label.TextProperty;
var coerceValue = property.GetType().GetProperty("CoerceValue", BindingFlags.NonPublic | BindingFlags.Instance);
var oldDelegate = coerceValue?.GetValue(property) as BindableProperty.CoerceValueDelegate;
coerceValue?.SetValue(property, d);
l.Text = "1"; // Text property is set to textY thanks to CoerceValueDelegate!
base.OnAppearing();
}
when i call l.Text = "1" the BindableProperty.CoerceValueDelegate i defined is correctly called, and l.Text is set to textY as expected.
#codetale, are you able to run this code on your side?

Create TreeView with events programmatically

I am creating a tree programmatically inside a row in a table.
Works fine, but can not get the assigned event is called:
TreeView arbolCapas = new TreeView();
arbolCapas.ID = "capas";
foreach (String capa in servicio.Capas)
{
TreeNode childNodes = new TreeNode();
childNodes.Text = capa;
childNodes.ShowCheckBox = true;
childNodes.SelectAction = TreeNodeSelectAction.None;
arbolCapas.Nodes.Add(childNodes);
}
arbolCapas.SelectedNodeChanged +=new EventHandler(arbolCapas_TreeNodeCheckChanged);
tbC.Controls.Add(arbolCapas);
tbR.Cells.Add(tbC);
protected void arbolCapas_TreeNodeCheckChanged(Object sender, EventArgs e)
{
TreeView elemento = (TreeView)(((CheckBox)sender).Parent);
foreach (TreeNode node in elemento.CheckedNodes)
{ //if (node.Checked)
}
}
How I can call an event when the checkbox of a child node is checked?
Thanks a lot.
Kindly change
childNodes.SelectAction = TreeNodeSelectAction.None
to
childNodes.SelectAction = TreeNodeSelectAction.Select;
I found the solution by adding the event as follows:
arbolCapas.Attributes.Add("onclick", "OnCheckBoxCheckChanged(event)");
And then, in javascript:
function OnCheckBoxCheckChanged(evt) {
alert("check change");
}
Here the solution:
http://geekswithblogs.net/ranganh/archive/2009/01/21/updated-asp.net-treeview-checkboxes-ndash-check-all-ndash-javascript.aspx

Page cannot be null error custom MOSS 2007 Webpart

I'm trying to write a webpart that basically pulls data from a list and displays it to the user. There is a feature news list where one of the columns holds a URL to an image. The web part should get the 3 most recent feature news items and create three image controls on the page. These image controls can be scrolled through by clicking on the buttons 1,2,3. (Ie, clicking on 2 will set the Visible property of image 1 and image 3 to false).
I have managed to implement AJAX here, but am now trying to use the UpdatePanelAnimationExtender from the AJAX Control Toolkit.
I have followed all instructions on how to use the toolkit, add it to the GAC, add a safe assembly, etc, and have gotten past all the errors besides this one:
"Page cannot be null. Please ensure that this operation is being performed in the context of an ASP.NET request"
My complete code below:
using System; using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Web.UI;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.WebControls;
using System.Web.Extensions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;
using System.ComponentModel;
using AjaxControlToolkit;
namespace FeatureNewsWebpartFeature {
[Guid("7ad4b959-d494-4e85-b164-4e4231692b8b")]
public class FeatureNewsWebPart : Microsoft.SharePoint.WebPartPages.WebPart
{
private bool _error = false;
private string _listName = null;
private string _imageColumn = null;
Image image1;
Image image2;
Image image3;
UpdatePanelAnimationExtender upAnimator;
[Personalizable(PersonalizationScope.Shared)]
[WebBrowsable(true)]
[System.ComponentModel.Category("List Connection Settings")]
[WebDisplayName("List Name")]
[WebDescription("Enter the name of the news list")]
public string ListName
{
get
{
if (_listName == null)
{
_listName = "News";
}
return _listName;
}
set { _listName = value; }
}
[Personalizable(PersonalizationScope.Shared)]
[WebBrowsable(true)]
[System.ComponentModel.Category("List Connection Settings")]
[WebDisplayName("Image Column Name")]
[WebDescription("Enter the column name of the ArtfulBits Image Upload column")]
public string ImageUrlColumn
{
get
{
if (_imageColumn == null)
{
_imageColumn = "Feature Image";
}
return _imageColumn;
}
set { _imageColumn = value; }
}
public FeatureNewsWebPart()
{
this.ExportMode = WebPartExportMode.All;
}
/// <summary>
/// Create all your controls here for rendering.
/// Try to avoid using the RenderWebPart() method.
/// </summary>
protected override void CreateChildControls()
{
if (!_error)
{
try
{
base.CreateChildControls();
//Create script manager
if (ToolkitScriptManager.GetCurrent(this.Page) == null)
{
ToolkitScriptManager scriptHandler = new ToolkitScriptManager();
scriptHandler.ID = "scriptHandler";
scriptHandler.EnablePartialRendering = true;
this.Controls.Add(scriptHandler);
}
//Create update panel
System.Web.UI.UpdatePanel imageUpdatePanel = new System.Web.UI.UpdatePanel();
imageUpdatePanel.ID = "imageUpdatePanel";
imageUpdatePanel.UpdateMode = UpdatePanelUpdateMode.Conditional;
this.Controls.Add(new LiteralControl("<div id=\"updateContainer\">"));
this.Controls.Add(imageUpdatePanel);
this.Controls.Add(new LiteralControl("</div>"));
//Make SPSite object and retrieve the three most recent feature news items
SPSite site = SPContext.Current.Site;
using (SPWeb web = site.OpenWeb())
{
SPList oList = web.Lists[ListName];
SPQuery oQuery = new SPQuery();
oQuery.RowLimit = 3;
oQuery.Query = "<OrderBy>" +
"<FieldRef Name='Modified' Ascending='False' /></OrderBy>" +
"<Where>" +
"<Eq>" +
"<FieldRef Name='ContentType' />" +
"<Value Type='Choice'>Feature News Item</Value>" +
"</Eq>" +
"</Where>";
oQuery.ViewFields = string.Concat(
"<FieldRef Name='Feature_x0020_Image' />" +
"<FieldRef Name='Feature_x0020_Order' />");
image1 = new Image();
image2 = new Image();
image3 = new Image();
//For each item, extract image URL and assign to image object
SPListItemCollection items = oList.GetItems(oQuery);
foreach (SPListItem oListItem in items)
{
string url = oListItem["Feature_x0020_Image"].ToString();
url = url.Substring(url.IndexOf("/Lists"));
url = url.Remove(url.IndexOf(";#"));
switch (oListItem["Feature_x0020_Order"].ToString())
{
case "1":
image1.ImageUrl = url;
break;
case "2":
image2.ImageUrl = url;
break;
case "3":
image3.ImageUrl = url;
break;
default:
//ERROR
break;
}
}
if (!(Page.IsPostBack))
{
image1.Visible = true;
image2.Visible = false;
image3.Visible = false;
}
imageUpdatePanel.ContentTemplateContainer.Controls.Add(image1);
imageUpdatePanel.ContentTemplateContainer.Controls.Add(image2);
imageUpdatePanel.ContentTemplateContainer.Controls.Add(image3);
//Create animation for update panel
upAnimator = new UpdatePanelAnimationExtender();
upAnimator.ID = "upAnimator";
upAnimator.TargetControlID = imageUpdatePanel.ID;
const string xml = "<OnUpdating>" +
"<Parallel duration=\".25\" Fps=\"30\">" +
"<FadeOut AnimationTarget=\"updateContainer\" minimumOpacity=\".2\" />" +
"</OnUpdating>" +
"<OnUpdated>" +
"<FadeIn AnimationTarget=\"updateContainer\" minimumOpacity=\".2\" />" +
"</OnUpdated>";
Animation.Parse(xml, upAnimator);
this.Controls.Add(upAnimator);
Button b1 = new Button();
b1.ID = "b1i";
b1.Click += new EventHandler(b1_Click);
b1.Text = "Image 1";
Button b2 = new Button();
b2.ID = "b2i";
b2.Click += new EventHandler(b2_Click);
b2.Text = "Image 2";
Button b3 = new Button();
b3.ID = "b3i";
b3.Click += new EventHandler(b3_Click);
b3.Text = "Image 3";
this.Controls.Add(b1);
this.Controls.Add(b2);
this.Controls.Add(b3);
AsyncPostBackTrigger tr1 = new AsyncPostBackTrigger();
tr1.ControlID = b1.ID;
//tr1.EventName = "Click";
imageUpdatePanel.Triggers.Add(tr1);
AsyncPostBackTrigger tr2 = new AsyncPostBackTrigger();
tr2.ControlID = b2.ID;
//tr2.EventName = "Click";
imageUpdatePanel.Triggers.Add(tr2);
AsyncPostBackTrigger tr3 = new AsyncPostBackTrigger();
tr3.ControlID = b3.ID;
//tr3.EventName = "Click";
imageUpdatePanel.Triggers.Add(tr3);
}
}
catch (Exception ex)
{
HandleException(ex);
}
}
}
void b1_Click(object sender, EventArgs e)
{
image1.Visible = true;
image2.Visible = false;
image3.Visible = false;
}
void b2_Click(object sender, EventArgs e)
{
image1.Visible = false;
image2.Visible = true;
image3.Visible = false;
}
void b3_Click(object sender, EventArgs e)
{
image1.Visible = false;
image2.Visible = false;
image3.Visible = true;
}
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
}
protected override void Render(HtmlTextWriter writer)
{
base.Render(writer);
}
/// <summary>
/// Ensures that the CreateChildControls() is called before events.
/// Use CreateChildControls() to create your controls.
/// </summary>
/// <param name="e"></param>
protected override void OnLoad(EventArgs e)
{
if (!_error)
{
try
{
base.OnLoad(e);
this.EnsureChildControls();
// Your code here...
}
catch (Exception ex)
{
HandleException(ex);
}
}
}
/// <summary>
/// Clear all child controls and add an error message for display.
/// </summary>
/// <param name="ex"></param>
private void HandleException(Exception ex)
{
this._error = true;
this.Controls.Clear();
this.Controls.Add(new LiteralControl(ex.Message));
}
} }
Here's a related question though being asked in the context of SP 2010, it's still directly applicable given the solution.
We have a CQWP on our MOSS farm that does essentially the same thing: reads items from a list using jQuery and the SPServices plugin and animates slider changes. The most difficult part of the process is actually tweaking the look, if I remember correctly. Once you have the right pieces, putting it together is a snap.

WebControl button event

I've just made my first WebControl, but I'm having some troubles.
Here's a sample of what I have so far:
public class NotificationPopup : WebControl
{
public bool? IsAccepted { get; set; }
public void Show()
{
Panel root = new Panel();
Button b1 = new Button();
b1.Text = "Ok";
b1.Click += delegate
{
IsAccepted = true;
};
Button b2 = new Button();
b2.Text = "Cancel";
b2.Click += delegate
{
IsAccepted = false;
};
Controls.Add(root);
}
}
When I call Show the panel is displayed, but when I press the button the IsAccepted property is never changed. Can anyone tell me what I'm doing wrong?
Do you re-create your buttons by calling Show again ? If you don't, the buttons are not created and the event handlers will not fire.

Resources