I have created simple controls that are based on dot net controls . For example there is a simple GridView control that is based on dot net GridView control , I just set some setting in my control to use it in my .aspx pages , for example I set the Width of GridView in the constructor method :
// constructor of my custom class
public GridView(): base()
{
this.Width = new Unit(100, UnitType.Percentage);
}
and also I've added some custom properties :
public int SelectedID
{
get
{
if (ViewState["SelectedID" + this.ID] == null)
ViewState["SelectedID" + this.ID] = "-1";
return Convert.ToInt32(ViewState["SelectedID" + this.ID]);
}
set
{
ViewState["SelectedID" + this.ID] = value;
}
}
The *Problem* : when I use Tools>Generate Local Resource in VS2010
the aspx markup before I use this tool is like this :
<RPC:GridView ID="grdData" runat="server" onrowcommand="grdData_RowCommand">
but this tool adds any public property or any setting to my aspx markup , like this :
<RPC:GridView ID="grdData" runat="server" onrowcommand="grdData_RowCommand"
meta:resourcekey="grdDataResource1" SelectedID="-1" Width="100%">
I don't like VS2010 add my settings (like width) and my custom properties (like SelectedID) to aspx markup , this prevent me having the ability of changing my custom control code and reflect changes in all aspx pages that include this control , for example if
I change the width of my control to 50% , it doesn't reflect to any pages
Please tell me what should I do to fix my problem
Thank you very much for your feedbacks
This is a slightly complicated topic to address in one answer here to be honest! There are more than one approaches you can take to resolve this problem. It all depends on the kind of properties your control has and if it is a templated control or not. As a quick fix try decorating your public properties with the following attribute
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
or if you don't want the user to be able to set the public property at all via HTML markup then use
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
another attribute declaration which will be helpful with
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
is
PersistenceMode(PersistenceMode.Attribute)
I've found doing any initialisation in the ctor causes major headaches for local resource generation (even corruption). Use the DefaultValue attribute on properties and/or use OnLoad if possible. (As a side note use CSS rather than explicitly setting control width).
Related
I have a webuser control having repeater control inside it like below.
<asp:Repeater ID="repeaterInvoicesPaid" runat="server">
</asp:Repeater>
I just dragged it to my data.aspx page.Now i have a method inside data.cs C# file which is returning the data from table .i want to ask ,how to bind the repeater(which is inside the user control)?
it will be binded inside data.cs file or web user control's own C# file.?
And please tell me how to access the repeater id from user control inside data.cs file?
Thanks in advance.
As for question 1: You can either
expose the repeater (see question 3) or
expose the datasource
Personally I am in favour of the last option
For databinding options, you can choose to expose the built-in databind method or you can databind when the source is set.
Exposing the datasource could be done like this
public static object RepeaterDataSource {
get { return repeater.DataSource; }
set { repeater.DataSource = value; }
}
or make a method to set it, to allow manipulation upon setting, like databinding.
Question 2: The actual binding always happens where the repeater is. If you need an OnItemDataBound handler, then that one will be in the usercontrol's code-behind, regardless of where you bind it from. You can however expose that too, but I see no reason to do so.
Question 3: If you want the id, then I assume the client id. You can get that with something like this
public static string RepeaterClientID {
get { return theRepeater.ClientID; }
}
Although I'm not sure that's what you actually mean. If you want a reference instead, then
public static Repeater TheRepeater {
get { return theRepeater; }
set { theRepeater = value; }
}
Lastly, accept more answers to your questions, or delete them entirely. Your acceptance rate is very low.
Create object of user control
UserControl usr = Page.FindControl("usercontrolID");
Repeator rept = usr.FindControl("repeatorControlID");
rept.DataScourse= Datatbale;
rept.DataBind();
You could always make a public property in your user control that returns the repeater.
I have seen that BindableAttribute is used to decorate public properties in custom controls.
MSDN briefly mentions that it provides the ability to control the binding direction and whether binding is supported at design time.
public class MyControl : Panel
{
[Bindable(BindableSupport.No, BindingDirection.OneWay)]
public string MyString { get; set; }
}
var myControl = new MyControl();
var myString = myControl.MyString;
Questions:
1) I set BindableSupport to No, however I could still do this in markup (.aspx).
What does BindableSupport affect then? Does it hide the property in the toolbox?
<cc:MyControl runat="server" MyString="something" />
2) How does one-way binding and two-way binding work in the context of custom controls and ASP.NET?
Would appreciate any inputs.
I believe MSDN is clear enough about this. It may be brief in your eyes, but it's sufficient.
This attribute is used for BINDING. Assigning a string to your variable isn't considered a binding.
This is for instance binding:
myGridView.DataSource = myList;
myGridView.DataBind();
This isn't:
myGridView.ID = "blablabla";
Please, see this link for more info, don't see a reason to duplicate an existing learning source here...
http://msdn.microsoft.com/en-us/library/ms752347.aspx
UPDATE:
For asp.net this link may be more illustrative:
http://www.asp.net/ajaxlibrary/HOW%20TO%20Create%20an%20Editable%20View%20with%20Two-Way%20Data%20Binding.ashx
My findings so far:
1) BindableSupport is related to data-binding functionality provided by ASP.NET. E.g. Page.DataBind(), <%# Bind("MyProperty") %>, <%# Eval ("MyProperty") %> and so on.
+1 for #walther's answer.
2) Two-way binding in ASP.NET is the ability to retain modifications to data-bound values on postback. This SO thread provides more details. Bind is two-way, while Eval is one-way.
Im working with Sitefinity and I'm developing a Control Designer - however i dont think my question is specific to SiteFinity.
I have a class such as:
public class CaseStudyFeaturedItem : CaseStudySelectorControlDEsignerBase
The class it is inherriting from is itself inheriting from UserControl, like so:
public class CaseStudySelectorControlDesignerBase : System.Web.UI.UserControl {
Within CaseStudyFeaturedItem is it possible to load a template which is an embedded resource and then access the controls on that control?
So essentially, I have usercontrol.ascx which is an embedded resource so has a string like:
mynamespace.myclass.usercontrol.ascx;
And from within CaseStudyFeaturedItem I want to be able to load that usercontrol and then modify the controls (i.e. literals/labels) that are within it?
Is this possible?
Thanks
Al
We do this with every control in Sitefinity, but it would be a little complicated to do with your own custom controls (I assume you are using Sitefinity 3.7). The steps are the following:
- Implement a template container control, inheriting from GenericContainer:
protected class ItemListContainer : GenericContainer
{
public virtual Repeater RepeaterControl
{
get { return base.GetControl<Repeater>("repeater", true); }
}
}
- You need to get the template from the resource (use ControlUtils.GetTemplate method - Sitefinity does that for you):
public virtual ITemplate ItemListTemplate
{
get
{
if (itemListTemplate == null)
itemListTemplate = ControlUtils.GetTemplate(<virtual path to template>, <resource file name>,
<type to determine assembly for template>);
return itemListTemplate;
}
set
{
itemListTemplate = value;
}
}
- You need to call InstantiateIn method of the template, and pass it the container control
listContainer = new ItemListContainer();
ItemListTemplate.InstantiateIn(listContainer);
- Access all controls through the container
listContainer.RepeaterControl.DataBind();
In Sitefinity 4.0 we've included a base class for all controls, which will give you this functionality out of the box. In 3.7 though, you'll have to do all this by hand.
The ControlUtils class is in the Telerik.Framework.Web namespace. The code above is how this all is done in the ContentView control, you should probably make slight modifications depending on your case.
Cheers,
Slavo
The Sitefinity team # Telerik
Yes it is possible, but I'm not entirely sure what you're trying to accomplish based on your question. You can use LoadControl to dynamically load user controls. If you cast the result to the appropriate control type, you will then have access to all of its properties. From there, you can add it into whatever container you want to hold it. Is that the kind of thing you're trying to do?
If I put a control in a .aspx file like this;
<asp:TextBox ID="protectedTextBox" runat="server">Some info</asp:TextBox>
I get a declared control in the page's .aspx.designer.cs file;
protected global::System.Web.UI.WebControls.TextBox protectedTextBox;
But I'd like to change the access modifier of the control to public. Is there any attribute or similar that I can set to change the access modifier?
Here's why I want to do it. I am trying to have cross-page postbacks work nice and neatly. I have two pages:
FirstPage.aspx
MyTextBox : textbox
MyButton : button, #PostbackUrl=Secondpage
SecondPage.aspx
MyLabel : label
When the user clicks FirstPage.MyButton, I want to write the value of FirstPage.MyTextBox.Text into SecondPage.MyLabel.Text. I could do it with Page.FindControl, but this seems like a poor substitute to casting the previous page as a FirstPage object and referring directly to the MyTextBox control on it. Something like this;
// on the page_load of SecondPage.aspx;
var previousPage = this.PreviousPage as FirstPage;
this.MyLabel.Text = previousPage.MyTextBox.Text;
Is there any way to change the access modifier?
You can just delete the declaration from the designer and put it in your code behind.
The comments around the declaration say to do this.
/// To modify move field declaration from designer file to code-behind file.
One option I've considered is writing a public property which exposes the original page;
public TextBox PublicTextBox { get { return this.MyTextBox; } }
Which would get the job done, but seems hacky.
Steve, exposing that page's controls would make sense if you'd need to manipulate those controls, but in your case you just need to pass some data (that string) to the other handler, so I would expose that and not the control itself.
I'm having a Repeater used as a sort of Paging TagCloud. To do so, I've added simple properties to the Page's ViewState such as a Page, RowCount, etc...
I feel like it doesn't belong there but I had bad experiences with server controls, debugging, dll and deployment.
Could I just inherit the Repeater class, add a few ControlState/ViewState properties and be able to use it exactly as a Repeater dragged straight from the ToolBox?
Here, having the following simple class:
public class TagCloud : Repeater
{
public int selectedIndex;
public TagCloud()
{
selectedIndex = -1;
//
// TODO: Add constructor logic here
//
}
public int SelectedIndex
{
get { return selectedIndex; }
set { selectedIndex = value; }
}
}
Without creating a new WebControlLibrary project, could this cs file stands in the App_Code folder and work like expected?
Thanks.
Yes, there is no problem doing this. As long as you use the control's property syntax:
public int RowCount
{
get { return (int) (ViewState["RowCount"] ?? 0); }
set { ViewState["RowCount"] = value; }
}
Also, to make your properties look the same as the default ones you can add Description or DefaultValue attributes.
This works, and is one suggested way of building server controls. Try it and see.
Inheriting from the ASP Repeater is a completely valid approach, so long as the control you are building IS a repeater with additional properties.
If you feel the control you need is actually "something else" that happens to have a repeater as part of its control set, then you likely need to make a composite control which adds a repeater to its control collection, along with whatever other controls are needed.
For example, you might want to have a control that has a repeater, a label of search results, links to go to the top and the bottom of the repeater's contents, etc. This composite control is not a repeater, but does use a repeater.