I need advices! So I have a custom repeater where I write the footer in the Custom control here is the code :
[ParseChildren(true)]
[PersistenceMode(PersistenceMode.InnerProperty)]
[DefaultProperty("Text")]
[ToolboxData("<{0}:CustomRepeater runat=server></{0}:CustomRepeater>")]
public class CustomRepeater : Repeater
{
[PersistenceMode(PersistenceMode.InnerDefaultProperty),
TemplateContainer(typeof(GuessFooterTemplate))]
private ITemplate FooterTemp {get; set;}
protected override void InitializeItem(RepeaterItem item)
{
base.InitializeItem(item);
FooterTemp = new GFooterTemplate();
this.FooterTemplate = FooterTemp;
}
//Here I try to hide the footer template
[PersistenceMode(PersistenceMode.InnerDefaultProperty)]
public override ITemplate FooterTemplate
{
get
{
return base.FooterTemplate;
}
set
{
base.FooterTemplate = value;
}
}
}
internal class GFooterTemplate : ITemplate
{
PlaceHolder ph = new PlaceHolder();
public void InstantiateIn(Control Container)
{
ph.Controls.Add(new LiteralControl("Test for Footertemplate"));
Container.Controls.Add(ph);
}
}
So as the footer is writing programmatically, I would like to hide the FooterTemplate for somebody who use the custom repeater.. I was thinking [PersistenceMode(PersistenceMode.InnerDefaultProperty)] will do that but apparently not.. Have somebody an idea?
Thanks a lot
If I understand correctly, you don't want the users of your CustomRepeater to be able to modify the FooterTemplate...
I see 2 possible solutions:
Use the new modifier on your property to completely redefine it:
private new ITemplate FooterTemplate
{
get { return base.FooterTemplate; }
set { base.FooterTemplate = value; }
}
Or modify the setter to do nothing, thus preventing the modification:
public override ITemplate FooterTemplate
{
get
{
return base.FooterTemplate;
}
set
{
/* base.FooterTemplate = value; */
}
}
HTH
Related
Below is how I'm defining the property, it works for other types of property like string or bool but it won't work for the type Command:
public static readonly BindableProperty ClickedProperty = BindableProperty.Create(
nameof(Clicked),
typeof(Command),
typeof(MyCustomControl),
default(Command),
BindingMode.OneWay,
propertyChanging: (bindable, oldValue, newValue) => {
var control = bindable as MyCustomControl;
if (!control.GestureRecognizers.Contains(gesture))
{
control.GestureRecognizers.Add(gesture);
}
}
);
public Command Clicked
{
get { return (Command)GetValue(ClickedProperty); }
set { SetValue(ClickedProperty, value); }
}
I tried searching for how it's done for the class Xamarin.Forms.Button but it seems to use the IButtonController interface which is not for public use.
Update
I changed the property to event type, now the accessors are called when I bind the property from a XAML form, but neither propertyChanged nor propertyChanging is called.
public event EventHandler Clicked
{
add
{
lock (gesture)
{
gesture.Tapped += value;
}
}
remove
{
lock (gesture)
{
gesture.Tapped -= value;
}
}
}
I'd like to bind my dropdown to a generic list.
It seems really simple but I keep getting the error DataBinding: 'InternalPurchasingForms.Types.Item' does not contain a property with the name 'itemID'.
Here's my code for the class:
namespace InternalPurchasingForms.Types
{
public class Item
{
public int itemID;
public String name;
//...
}
}
Here's my dropdown databinding code:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
List<Item> allItems = DataAccessLayer.getAllItems();
uxDropDownItemList.DataSource = allItems;
uxDropDownItemList.DataValueField = "itemID";
uxDropDownItemList.DataTextField = "name";
uxDropDownItemList.DataBind();
}
}
I want to tell the dropdown that the "value" for each line is Item.itemID and that the "text" is Item.Name, but ASP.NET's telling me that those fields don't exist inside Item. I'm able to access Item's fields just fine elsewhere.
How do I do this correctly?
Make sure you are using a getter and setter in your Item class for itemID and name.
I am setting properties in this way and its working fine while binding with dropdown.
private int _itemid= 0;
private string _name = "";
public string name
{
set { _name = value; }
get { return _name ; }
}
public int itemID
{
set { _itemid= value; }
get { return _itemid; }
}
For example:
<uc:AdmiralAckbar runat="server" id="myCustomControl">
<Warning SomeAttribute="It's A Trap">
My Data
</Warning>
</uc:AdmiralAckbar>
I'm not sure how to add SomeAttribute. Any ideas?
Code without the attribute is:
private ITemplate warning = null;
[TemplateContainer(typeof(INamingContainer))]
[PersistenceMode(PersistenceMode.InnerProperty)]
public ITemplate Warning
{
get
{
return warning;
}
set
{
warning = value;
}
}
The answer is yes.
For this you should create a type which implements ITemplate interface and add a custom property/properties there (I added property Name in my example); also add a class which inherits from Collection<YourTemplate>.
Here is an example of doing that:
public class TemplateList : Collection<TemplateItem> { }
public class TemplateItem : ITemplate
{
public string Name { get; set; }
public void InstantiateIn(Control container)
{
var div = new HtmlGenericControl("div");
div.InnerText = this.Name;
container.Controls.Add(div);
}
}
and a control itself:
[ParseChildren(true, "Templates"), PersistChildren(false)]
public class TemplateLibrary : Control
{
public TemplateLibrary()
{
Templates = new TemplateList();
}
[PersistenceMode(PersistenceMode.InnerProperty)]
public TemplateList Templates { get; set; }
protected override void RenderChildren(HtmlTextWriter writer)
{
foreach (var item in Templates)
{
item.InstantiateIn(this);
}
base.RenderChildren(writer);
}
}
and finally an example of usage:
<my:TemplateLibrary runat="server">
<my:TemplateItem Name="hello" />
<my:TemplateItem Name="there" />
</my:TemplateLibrary>
BTW, you could also use it as:
<my:TemplateLibrary runat="server">
<Templates>
<my:TemplateItem Name="hello" />
<my:TemplateItem Name="there" />
</Templates>
</my:TemplateLibrary>
the effect will be the same.
I have a class UserControlBase that inherits System.Web.UI.UserControl and my user controls inherit UserControlBase class. UserControlBase has some common functions that are used in all user controls.
I want to put error display function to UserControlBase as well so that I may not have to declare and manage it in all user controls. Error will be displayed in some label in usercontrol. Issue is how to access label which is in usercontrol in UserControlBase in function ? I don't want to pass label as argument.
In your UserControl Base, expose the text value of the label only:
public abstract class UserControlBase : System.Web.UI.UserControl
{
private Label ErrorLabel { get; set; }
protected string ErrorMessage
{
get { return ErrorLabel.Text; }
set { ErrorLabel.Text = value; }
}
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
ErrorLabel = new Label();
Controls.Add(ErrorLabel);
}
//... Other functions
}
In your user controls that inherit this:
public partial class WebUserControl1 : UserControlBase
{
protected void Page_Load(object sender, EventArgs e)
{
try
{
}
catch (Exception)
{
ErrorMessage = "Error"; //Or whatever
}
}
}
I have a simple web control (TaskList) that can have children (Task) which inherit from LinkButton, that can be added declaratively or programatically. This works ok, but I can't get the onclick event of a Task to be fired in my code behind. The code ..
[ToolboxData("<{0}:TaskList runat=\"server\"> </{0}:TaskList>")]
[ParseChildren(true)]
[PersistChildren(false)]
public class TaskList : System.Web.UI.Control
{
//[DefaultProperty("Text")]
public TaskList()
{}
private List<Task> _taskList = new List<Task>();
private string _taskHeading = "";
public string Heading
{
get
{
return this._taskHeading;
}
set
{
this._taskHeading = value;
}
}
[NotifyParentProperty(true)]
[PersistenceMode(PersistenceMode.InnerProperty)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public List<Task> Tasks
{
get
{
return this._taskList;
}
set
{
this._taskList = value;
}
}
protected override void CreateChildControls()
{
foreach (Task task in this._taskList)
this.Controls.Add(task);
base.CreateChildControls();
}
protected override void Render(HtmlTextWriter writer)
{
writer.Write("<h2>" + this._taskHeading + "</h2>");
writer.Write("<div class='tasks_container'>");
writer.Write("<div class='tasks_list'>");
writer.Write("<ul>");
foreach (Task task in this._taskList)
{
writer.Write("<li>");
task.RenderControl(writer);
writer.Write("</li>");
}
writer.Write("</ul>");
writer.Write("</div>");
writer.Write("</div>");
}
}
public class Task : LinkButton
{
private string _key = "";
public string Key
{
get
{
return this._key;
}
set
{
this._key = value;
}
}
}
Markup:
<rf:TaskList runat="server" ID="tskList" Heading="Tasks">
<Tasks>
<rf:Task Key="ba" ID="L1" Text="Helllo" OnClick="task1_Click" runat="server" />
</Tasks>
</rf:TaskList>
The Onclick event task1_Click never fires when clicked (although a postback occurs).
TaskList needed to implement INamingContainer to correctly route the events of each Task.
You could also inherit from CompositeControl, which implements INamingContainer for you, instead of inheriting from Control.
Have you thought about INamingContainer.