asp.net user control binding - asp.net

i created a user control with a custom property in the asp.net like the following. In the aspx page that uses this user control i have something like the following. The user control is in a FormView's EditItemTemplate
<uc1:MyControl ID="c1" runat="server" CountryCode='<%# this.DropDownCountry.SelectedValue %>' Value1='<%# Bind("Value1Col") %>' />
I am trying to use the CountryCode in the Page_Load method of the user control, but the value has not be populated.
My question is at which stage in the control's life cycle does the bounded value gets populated? I tried assigning value directly like the following and it does get its value at the Page_Load method.
<uc1:MyControl ID="c1" runat="server" CountryCode="CA" Value1='<%# Bind("Value1Col") %>' />
thanks,
the uc1:MyControl has the following property:
[Browsable(true)]
[Bindable(true, BindingDirection.TwoWay)]
[DefaultValue(0)]
[PersistenceMode(PersistenceMode.Attribute)]
public string CountryCode
{
get { return _countryCode; }
set { _countryCode = value; }
}

Since you're using databinding syntax you need to call DataBind method on your control - you can add this to the Page_Load method of the aspx page like so:
protected void Page_Load(object sender, EventArgs e)
{
c1.DataBind();
}

Related

How to hide link button based on a result returned by a class ?

I am bit new to C# and got a question.
I have a class as below that simply return false ( this is just to test)
public class SetAuthority
{
public SetAuthority()
{
//
// TODO: Add constructor logic here
//
}
public static Boolean AuthorizedToAddEdit()
{
return false;
}
}
I have a DetailsView with two link buttons to Edit and add New record. I want to hide the link buttons based on the above class method returning value.
<ItemTemplate>
<asp:LinkButton ID="LinkButton1" runat="server" CausesValidation="False" visible='<%# SetAuthority.AuthorizedToAddEdit() %>'
CommandName="Edit" Text="Edit"></asp:LinkButton>
<asp:LinkButton ID="LinkButton2" runat="server" CausesValidation="False" visible='<%# SetAuthority.AuthorizedToAddEdit() %>'
CommandName="New" Text="New"></asp:LinkButton>
</ItemTemplate>
Above works file and Edit and New link buttons are hidden when I run the program.
But the question is, I have a separate link button outside of the DetailsView. It is just a link to navigate to another page. I want to hide this in similar way using the same logic. I have the below code in my webform.
<asp:LinkButton ID="LinkButton5" runat="server" CausesValidation="False" visible='<%# SetAuthority.AuthorizedToAddEdit() %>'
CommandName="OpenAdminPage" Text="Open Admin Page"></asp:LinkButton>
But the link button is always visible and seems it is not calling the class and not getting the value back. It appeared to be the class not return any value and can someone help me to identify what is the different between having this and working in DetailsView and not working for a simple link button.
Note: have a workaround where I can call the same method in Page Load event that works fine without any issue. Code is below
protected void Page_Load(object sender, EventArgs e)
{
Boolean myAllowAdd;
myAllowAdd = SetAuthority.AuthorizedToAddEdit();
if (myAllowAdd == false)
{
LinkButton1.Visible = false;
}
}
The reason is that this is for databinding expressions only: <%# Since the DetailsView is databound it works there.
If you would DataBind the page it worked also for the LinkButton outside of the DetailsView:
protected void Page_Load(object sender, EventArgs e)
{
Page.DataBind();
}
inline asp.net tags... sorting them all out (<%$, <%=, <%, <%#, etc.)
Side-note: be careful with static in ASP.NET. The static method does not yet hurt. But if you'd also use static fields you'd enter a minefield since it would be shared across all requests. Your current code-behind "work-around" is the better approach anyway.

Initialize User Control property value with inline tag

I've just written a ASP .NET wrapper for jQuery UI control as user control. It can be used like this:
<ui:DatePicker ID="startDate" runat="server" LabelText="Start Date:" />
Currently I set initial value of this control in Page_Load handler, just like this:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
startDate.Value = DateTime.Now.AddMonths(-2);
}
}
But I thought that it would be nice to move initialization code to markup. Yet I can't work out is how to set initial value of this control using inline tag, for instance:
<ui:DatePicker ID="startDate" Value='<%= DateTime.Now.AddMonths(-2) %>' runat="server" LabelText="Start Date:" />
I have a property:
public DateTime? Value
{
get
{
DateTime result;
if (DateTime.TryParse(dateBox.Text, out result))
{
return result;
}
return null;
}
set
{
dateBox.Text = value != null ? value.Value.ToShortDateString() : "";
}
}
I've tried different inline tags combinations, and I always get a compilation error. Is there a way to achieve it with inline tags?
You will need to put the actual date representation in the property. The reason is that some properties of Asp.Net controls also behave like that e.g. the visible property of a TextBox cannot be set like <asp:TextBox runat="server" Visible='<%= true %>'></asp:TextBox>
<ui:DatePicker ID="startDate" Value='20/10/2012' runat="server" LabelText="Start Date:" />
Or set the value from your Page_Load
protected void Page_Load(object sender, EventArgs e)
{
if(!Page.IsPostBack)
{
startDate.Value = DateTime.Now; //initialize DatePicker
}
}
I found these link:
Why will <%= %> expressions as property values on a server-controls lead to a compile errors?
Set Visible property with server tag <%= %> in Framework 3.5

ListView + ObjectDataSource SelectMethod called twice when EnableViewState="false"

Note: This question has been completely modified now that I have a simpler example.
I have set up a sample page which only has a ListView and ObjectDataSource. The first time the page comes up (!IsPostBack), my GetList method is called once. After paging (IsPostBack), the GetList method is called twice--the first time with the old paging values and the second time with the new values.
If I set EnableViewState="true" on the ListView, then the GetList method is only called once. It seems to me that the ListView wants an "initial state", which it either gets from ViewState or by re-running the method.
Is there any way to disable ViewState on the ListView and also prevent SelectMethod from being called twice?
ASPX page:
<asp:ListView ID="TestListView" runat="server" DataSourceID="ODS" EnableViewState="false">
<LayoutTemplate>
<asp:PlaceHolder ID="itemPlaceHolder" runat="server" />
<asp:DataPager ID="TestPager" runat="server" PageSize="10">
<Fields>
<asp:NumericPagerField />
</Fields>
</asp:DataPager>
</LayoutTemplate>
<ItemTemplate>
<div><%# Eval("Title") %></div>
</ItemTemplate>
</asp:ListView>
<asp:ObjectDataSource ID="ODS" runat="server" SelectMethod="GetList" SelectCountMethod="GetListCount"
TypeName="Website.Test" EnablePaging="true" />
ASPX code-behind:
namespace Website
{
public partial class Test : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
public IList<DataItem> GetList(int maximumRows, int startRowIndex)
{
return GetListEnumerable().Skip(startRowIndex).Take(maximumRows).ToList();
}
public IEnumerable<DataItem> GetListEnumerable()
{
for (int i = 0; i < 100; i++)
{
yield return new DataItem { Title = i.ToString() };
}
}
public int GetListCount()
{
return 100;
}
}
public class DataItem
{
public string Title { get; set; }
}
}
Either turn ODS caching on.
<asp:ObjectDataSource ID="ODS" ... EnableCaching="true" />
This way the GetList will be called only when new data is needed. Post backs to pages that already had data retrieved will use the cached version and not call the GetList.
Or move your DataPager out of the ListView and set the PagedControlID property.
Actually you should be using the OnSelecting event.
What happens is that ObjectDataSource calls the method SelectMethod twice
First time it gets the data.
Next time it gets the count.
So I think you have to implement the OnSelecting event
<asp:ObjectDataSource ID="ODS" runat="server" SelectMethod="GetList" SelectCountMethod="GetListCount"
OnSelecting="ods_Selecting">
TypeName="Website.Test" EnablePaging="true" />
and then cancel the event when the ObjectDataSource tries to call the count method.
protected void ods_Selecting(object sender,
ObjectDataSourceSelectingEventArgs e)
{
if (e.ExecutingSelectCount)
{
//Cancel the event
return;
}
}
You can look for full implementation as mentioned in the link below
http://www.unboxedsolutions.com/sean/archive/2005/12/28/818.aspx
Hope this helps.
I had a similar problem where it worked different depending on browser. IE one way and all other browsers one way.. Might not be the same issue as you have.
I solved it this way:
protected void DropDownDataBound(object sender, EventArgs e)
{
// Issue with IE - Disable ViewState for IE browsers otherwhise the dropdown will render empty.
DropDownList DDL = (DropDownList)sender;
if (Request.Browser.Browser.Equals("IE", StringComparison.CurrentCultureIgnoreCase))
DDL.ViewStateMode = System.Web.UI.ViewStateMode.Disabled;
else
DDL.ViewStateMode = System.Web.UI.ViewStateMode.Inherit;
}

Set Custom ASP.NET UserControl variables when its in a Repeater

<%# Register Src="~/Controls/PressFileDownload.ascx" TagName="pfd" TagPrefix="uc1" %>
<asp:Repeater id="Repeater1" runat="Server" OnItemDataBound="RPTLayer_OnItemDataBound">
<ItemTemplate>
<asp:Label ID="LBLHeader" Runat="server" Visible="false"></asp:Label>
<asp:Image ID="IMGThumb" Runat="server" Visible="false"></asp:Image>
<asp:Label ID="LBLBody" Runat="server" class="layerBody"></asp:Label>
<uc1:pfd ID="pfd1" runat="server" ShowContainerName="false" ParentContentTypeId="55" />
<asp:Literal ID="litLayerLinks" runat="server"></asp:Literal>
</ItemTemplate>
</asp:Repeater>
System.Web.UI.WebControls.Label lbl;
System.Web.UI.WebControls.Literal lit;
System.Web.UI.WebControls.Image img;
System.Web.UI.WebControls.HyperLink hl;
System.Web.UI.UserControl uc;
I need to set the ParentItemID variable for the uc1:pdf listed inside the repeater.
I thought I should be able to find uc by looking in the e.Item and then setting it somehow. I think this is the part where I'm missing something.
uc = (UserControl)e.Item.FindControl("pfd1");
if (uc != null) { uc.Attributes["ParentItemID"] = i.ItemID.ToString(); }
Any thoughts would be appreciated.
Also tried this with similar results... when I debug inside my usercontrol (pfd1) the parameters I am trying to set have not been set.
uc = (UserControl)e.Item.FindControl("pfd1");
if (uc != null)
{
uc.Attributes.Add("ContainerID", _cid.ToString());
uc.Attributes.Add("ParentItemId", i.ItemID.ToString());
}
UPDATE: It looks like my controls are not connected by a namespace. I've wrapped by the parent control (Layer) and the PressFileDownlad control in a namespace "MyControls". Also updated their Inherits reference on the aspx to read "MyControls.xxxxx". I'm able to type "MyControls.Layer" inside the code on layer.aspx.cs but I'm not able to get "MyControls.PressFileDownload"
If you implement ParentItemID as a public property in your user control, then you should be able to set it declaratively, e.g:
<asp:Repeater id="Repeater1" ...>
<ItemTemplate>
<uc1:pfd ID="pfd1" runat="server" ParentItemId='<%# Eval("ItemID") %>' ... />
Martin is right you should be able to set it in declarative way (in case your property is public) .
But your way should also work (just cast it properly)
((PressFileDownload)e.Item.FindControl("pfd1")).ParentItemId = 0;
The best way is to implement the OnDataBinding event for the user control. I try to stay away from putting code inline in the aspx using webforms if possible.
When the repeater gets bound, for each item that is bound, the OnDataBinding will fire for your user control and your handler can do what it needs. You don't have to go searching for the controls.
Here is an example:
// in your aspx
<uc1:pfd ID="pfd1" runat="server" ShowContainerName="false" ParentContentTypeId="55"
OnDataBinding="pfd1_DataBinding" />
// in your codebehind implement the OnDataBinding event
protected void pfd1_DataBinding(object sender, System.EventArgs e)
{
pfd uc = (pfd)(sender);
uc.ContainerID = _containerID.ToString();
uc.ParentItemID = Eval("ItemID");
// Here you can do more like access other items like hidden fields
// or cached objects or even other controls etc... Skys the limit.
}
EDIT: Notice from your comment you require more data than what is found in the datasource. In this case what I usually do is just make private member variables in the .cs that I store data in. So when you have the container ID just store it in a variable that will be accessible.
Eg in your .cs for your page:
public partial class _TestPage : System.Web.UI.Page
{
private int _containerID { get; set; }
Then when you load the data just set the _containerID property and it will be accessible in the OnDataBinding event. Just make sure you are binding after you have set the _containerID.

hidden field is null on !IsPostBack and not null on IsPostBack

First I'll apologize for the unclear title of my question. I wasn't sure how to succinctly describe my problem in a title.
I have a hidden field in my .aspx
<input type="hidden" name="hid1" value="0" />
I want to set the value of this field during the page load event, and if it is not a postback.
protected void Page_Load(object sender, EventArgs e) {
if (!Page.IsPostBack) {
// This doesn't work!
Request.Form["hid1"] = "1";
}
if (Page.IsPostBack) {
// This DOES work!
Request.Form["hid1"] = "1";
}
}
The problem is that the Request doesn't contain the hidden field in the Form array during the page load event when it's not a postback (ie - the first time the page is hit). Subsequent hits to the page (ie - postbacks) result in the Form array containing the hidden field.
I'm sure that it has to do with the lifecycle of the page, but what I really need to know is how do I set the hidden field during the page load event and when it is not a postback?
EDIT:
I really, really don't want to incorporate the runat="server" attribute!
You could define a property in your page class and then modify the property value in your code:
protected string HiddenFieldValue { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
HiddenFieldValue = "postback";
else
HiddenFieldValue = "not postback";
}
Then define the hidden form field like this so that it's value is set to the property value:
<input type='hidden' id='hidden1' value='<%=HiddenFieldValue %>' />
If you only want to set the value form the property during a postback or non-postback you could add the condition as well:
<input type='hidden' id='hidden1' value='<% if(IsPostBack) { %> <%=HiddenFieldValue%> <% } %>' />
Try converting the input into a HiddenField control (or, at least, a runat="server" input), and reference it by it's ID, rather than through Request.Form.
Instead of:
<input type="hidden" name="hid1" value="0" />
try this:
<asp:HiddenField runat="server" ID="hid1" />
Then in your Page_Load()
hid1.Value = "whatever...";
It will be visible both before and after postback when you declare it in this manner.
Why don't you make it a server control by setting 'runat="server"' on the input control? Then it will be accessible from your code behind, and you will be able to set the value during the first page load.
why dont you access that field through a style class and use runat server=?

Resources