I have created a custom server control with properties implementing the ITemplate interface. It is basically a custom panel box with a header, body & footer. Here is the code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
namespace ACME.Web.Controls
{
[ParseChildren(true)]
[DefaultProperty("Text")]
[ToolboxData("")]
public class Panel : WebControl, INamingContainer
{
private ITemplate _header = null;
private Control _headerControl = null;
private Control _headerContainerControl = null;
private ITemplate _content = null;
private Control _contentControl = null;
private Control _contentContainerControl = null;
private ITemplate _footer = null;
private Control _footerControl = null;
private Control _footerContainerControl = null;
[PersistenceMode(PersistenceMode.InnerProperty),
TemplateContainer(typeof(TemplateControl)),
TemplateInstance(TemplateInstance.Single)]
public ITemplate Header
{
get { return _header; }
set { _header = value; }
}
[PersistenceMode(PersistenceMode.InnerProperty),
TemplateContainer(typeof(TemplateControl)),
TemplateInstance(TemplateInstance.Single)]
public ITemplate Content
{
get { return _content; }
set { _content = value; }
}
[PersistenceMode(PersistenceMode.InnerProperty),
TemplateContainer(typeof(TemplateControl)),
TemplateInstance(TemplateInstance.Single)]
public ITemplate Footer
{
get { return _footer; }
set { _footer = value; }
}
protected override void CreateChildControls()
{
Controls.Clear();
if (this.ID == null) this.ID = "panel-" + Guid.NewGuid().ToString();
this.CssClass = "panel";
if (this.Header == null)
{
this.CssClass += " without-header";
}
else
{
this.CssClass += " with-header";
_headerControl = new System.Web.UI.WebControls.Panel { CssClass = "panel-header" };
_headerControl.Controls.Add(new System.Web.UI.WebControls.Panel { CssClass = "panel-header-l" });
_headerControl.Controls.Add(new System.Web.UI.WebControls.Panel { CssClass = "panel-header-c" });
_headerControl.Controls.Add(new System.Web.UI.WebControls.Panel { CssClass = "panel-header-r" });
_headerControl.Controls[1].Controls.Add(new System.Web.UI.WebControls.Panel { CssClass = "panel-header-wrapper" });
_headerControl.Controls[1].Controls[0].Controls.Add(new System.Web.UI.WebControls.Panel { CssClass = "wrapper" });
_headerContainerControl = new Control();
if (this.Header != null)
{
Header.InstantiateIn(_headerContainerControl);
}
else
{
_headerContainerControl.Controls.Add(new LiteralControl("Test"));
}
_headerControl.Controls[1].Controls[0].Controls[0].Controls.Add(_headerContainerControl);
Controls.Add(_headerControl);
}
_contentControl = new System.Web.UI.WebControls.Panel { CssClass = "panel-body" };
_contentControl.Controls.Add(new System.Web.UI.WebControls.Panel { CssClass = "panel-body-t" });
_contentControl.Controls[0].Controls.Add(new System.Web.UI.WebControls.Panel { CssClass = "panel-body-t-l" });
_contentControl.Controls[0].Controls.Add(new System.Web.UI.WebControls.Panel { CssClass = "panel-body-t-c" });
_contentControl.Controls[0].Controls.Add(new System.Web.UI.WebControls.Panel { CssClass = "panel-body-t-r" });
_contentControl.Controls.Add(new System.Web.UI.WebControls.Panel { CssClass = "panel-body-m" });
_contentControl.Controls[1].Controls.Add(new System.Web.UI.WebControls.Panel { CssClass = "panel-body-m-l" });
_contentControl.Controls[1].Controls.Add(new System.Web.UI.WebControls.Panel { CssClass = "panel-body-m-c" });
_contentControl.Controls[1].Controls.Add(new System.Web.UI.WebControls.Panel { CssClass = "panel-body-m-r" });
_contentControl.Controls[1].Controls[1].Controls.Add(new System.Web.UI.WebControls.Panel { CssClass = "panel-body-wrapper" });
_contentControl.Controls[1].Controls[1].Controls[0].Controls.Add(new System.Web.UI.WebControls.Panel { CssClass = "scroll-wrapper" });
_contentControl.Controls.Add(new System.Web.UI.WebControls.Panel { CssClass = "panel-body-b" });
_contentControl.Controls[2].Controls.Add(new System.Web.UI.WebControls.Panel { CssClass = "panel-body-b-l" });
_contentControl.Controls[2].Controls.Add(new System.Web.UI.WebControls.Panel { CssClass = "panel-body-b-c" });
_contentControl.Controls[2].Controls.Add(new System.Web.UI.WebControls.Panel { CssClass = "panel-body-b-r" });
_contentContainerControl = new Control();
if (this.Content != null)
{
Content.InstantiateIn(_contentContainerControl);
}
else
{
_contentContainerControl.Controls.Add(new LiteralControl("Test"));
}
_contentControl.Controls[1].Controls[1].Controls[0].Controls[0].Controls.Add(_contentContainerControl);
Controls.Add(_contentControl);
if (this.Footer == null)
{
this.CssClass += " without-footer";
}
else
{
this.CssClass += " with-footer";
_footerControl = new System.Web.UI.WebControls.Panel { CssClass = "panel-footer" };
_footerContainerControl = new Control();
if (this.Footer != null)
{
Footer.InstantiateIn(_footerContainerControl);
}
else
{
_footerContainerControl.Controls.Add(new LiteralControl("Test"));
}
_footerControl.Controls.Add(_footerContainerControl);
Controls.Add(_footerControl);
}
}
protected override HtmlTextWriterTag TagKey
{
get { return HtmlTextWriterTag.Div; }
}
}
}
It works perfectly but one cannot really access controls within the ITemplates from the code behind. I would like to be able to add and remove controls from the ITemplate regions of my custom control. What would be the best way to do this?
you can try container.findcontrol("")
Related
If I have an Entry in my Xamarin Forms project and I keep typing on it until it goes off the end of the viewable page the text does not horizontally scroll in iOS as it does on Android - is there a way to make it do this?
I've tried replacing it with an Editor, but that doesn't have a placeholder, which I need.
An Entry is rendered as a UITextField on iOS which does not support scrolling. An Editor is rendered as a UITextView which does support scrolling.
One option would be to create a custom editor that includes a placeholder.
I have code for this. It's not pretty but it works.
Here is the CustomEditor code including new bindable properties for placeholder text and color.
public class CustomEditor : Editor
{
public static readonly BindableProperty PlaceholderProperty =
BindableProperty.Create(nameof(Placeholder), typeof(string), typeof(CustomEditor), default(string));
public string Placeholder
{
get { return (string)GetValue(PlaceholderProperty); }
set { SetValue(PlaceholderProperty, value); }
}
public static readonly BindableProperty PlaceholderColorProperty =
BindableProperty.Create(nameof(PlaceholderColor), typeof(Color), typeof(CustomEditor), default(Color));
public Color PlaceholderColor
{
get { return (Color)GetValue(PlaceholderColorProperty); }
set { SetValue(PlaceholderColorProperty, value); }
}
public static readonly BindableProperty DisabledColorProperty =
BindableProperty.Create(nameof(DisabledColor), typeof(Color), typeof(CustomEditor), default(Color));
public Color DisabledColor
{
get { return (Color)GetValue(DisabledColorProperty); }
set { SetValue(DisabledColorProperty, value); }
}
}
Here is the iOS custom renderer
[assembly: ExportRenderer(typeof(CustomEditor), typeof(CustomEditorRenderer))]
namespace Test.iOS.CustomRenderers
{
public class CustomEditorRenderer : EditorRenderer
{
private UILabel PlaceholderLabel { get; set; }
protected override void OnElementChanged(ElementChangedEventArgs<Editor> e)
{
base.OnElementChanged(e);
if (Control == null) return;
Control.Layer.BorderWidth = 0.5f;
Control.Layer.CornerRadius = 8;
Control.Layer.BorderColor = Color.FromHex("CDCDCD").ToCGColor();
if (PlaceholderLabel != null) return;
var element = Element as CustomEditor;
PlaceholderLabel = new UILabel
{
Text = element?.Placeholder,
TextColor = element?.PlaceholderColor.ToUIColor(),
BackgroundColor = UIColor.Clear
};
var edgeInsets = Control.TextContainerInset;
var lineFragmentPadding = Control.TextContainer.LineFragmentPadding;
Control.AddSubview(PlaceholderLabel);
var vConstraints = NSLayoutConstraint.FromVisualFormat(
"V:|-" + edgeInsets.Top + "-[PlaceholderLabel]-" + edgeInsets.Bottom + "-|", 0, new NSDictionary(),
NSDictionary.FromObjectsAndKeys(
new NSObject[] { PlaceholderLabel }, new NSObject[] { new NSString("PlaceholderLabel") })
);
var hConstraints = NSLayoutConstraint.FromVisualFormat(
"H:|-" + lineFragmentPadding + "-[PlaceholderLabel]-" + lineFragmentPadding + "-|",
0, new NSDictionary(),
NSDictionary.FromObjectsAndKeys(
new NSObject[] { PlaceholderLabel }, new NSObject[] { new NSString("PlaceholderLabel") })
);
PlaceholderLabel.TranslatesAutoresizingMaskIntoConstraints = false;
Control.AddConstraints(hConstraints);
Control.AddConstraints(vConstraints);
PlaceholderLabel.Hidden = Element.Text.NotEmpty();
}
protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == "Text")
{
PlaceholderLabel.Hidden = Control.Text.NotEmpty();
}
if (e.PropertyName == VisualElement.IsEnabledProperty.PropertyName)
{
var element = Element as CustomEditor;
SetTextColor(element);
}
}
private void SetTextColor(CustomEditor element)
{
Control.TextColor = element.IsEnabled ? element.TextColor.ToUIColor() : element.DisabledColor.ToUIColor();
}
}
}
I took from a GitHub TkCustomMap project TK.CustomMap, and I want to call my custom service, to fill my custom list, and on ItemSelected event, from autocomplete searchBar to MapCenter it with Coordinates from my list model.
I've tried and I stopped at binding and on ItemSelect event.
Here is my MapPage:
using Xamarin.Forms;
using Xamarin.Forms.Maps;
namespace TK.CustomMap.Sample
{
public partial class SamplePage : ContentPage
{
public SamplePage()
{
//InitializeComponent();
this.CreateView();
this.BindingContext = new SampleViewModel();
}
private async void CreateView()
{
var autoComplete = new PlacesAutoComplete { ApiToUse = PlacesAutoComplete.PlacesApi.CustomList };
autoComplete.SetBinding(PlacesAutoComplete.MapSelectedCommandProperty, "MapCenter");
var newYork = new Position(40.7142700, -74.0059700);
var mapView = new TKCustomMap(MapSpan.FromCenterAndRadius(newYork, Distance.FromKilometers(2)));
mapView.IsShowingUser = true;
mapView.SetBinding(TKCustomMap.CustomPinsProperty, "Pins");
mapView.SetBinding(TKCustomMap.MapClickedCommandProperty, "MapClickedCommand");
mapView.SetBinding(TKCustomMap.MapLongPressCommandProperty, "MapLongPressCommand");
mapView.SetBinding(TKCustomMap.MapCenterProperty, "MapCenter");
mapView.SetBinding(TKCustomMap.PinSelectedCommandProperty, "PinSelectedCommand");
mapView.SetBinding(TKCustomMap.SelectedPinProperty, "SelectedPin");
mapView.SetBinding(TKCustomMap.RoutesProperty, "Routes");
mapView.SetBinding(TKCustomMap.PinDragEndCommandProperty, "DragEndCommand");
mapView.SetBinding(TKCustomMap.CirclesProperty, "Circles");
mapView.SetBinding(TKCustomMap.CalloutClickedCommandProperty, "CalloutClickedCommand");
mapView.SetBinding(TKCustomMap.PolylinesProperty, "Lines");
mapView.SetBinding(TKCustomMap.PolygonsProperty, "Polygons");
mapView.SetBinding(TKCustomMap.MapRegionProperty, "MapRegion");
mapView.SetBinding(TKCustomMap.RouteClickedCommandProperty, "RouteClickedCommand");
mapView.SetBinding(TKCustomMap.RouteCalculationFinishedCommandProperty, "RouteCalculationFinishedCommand");
mapView.SetBinding(TKCustomMap.TilesUrlOptionsProperty, "TilesUrlOptions");
mapView.SetBinding(TKCustomMap.MapFunctionsProperty, "MapFunctions");
mapView.IsRegionChangeAnimated = true;
autoComplete.SetBinding(PlacesAutoComplete.BoundsProperty, "MapRegion");
RelativeLayout _baseLayout = new RelativeLayout();
_baseLayout.Children.Add(
mapView,
Constraint.RelativeToView(autoComplete, (r, v) => v.X),
Constraint.RelativeToView(autoComplete, (r, v) => autoComplete.HeightOfSearchBar),
heightConstraint: Constraint.RelativeToParent((r) => r.Height - autoComplete.HeightOfSearchBar),
widthConstraint: Constraint.RelativeToView(autoComplete, (r, v) => v.Width));
_baseLayout.Children.Add(
autoComplete,
Constraint.Constant(0),
Constraint.Constant(0));
Content = _baseLayout;
}
}
}
Here is my PlacesAutoComplete class:
using System;
using System.Collections.Generic;
using System.Linq;
using TK.CustomMap.Api;
using TK.CustomMap.Api.Google;
using TK.CustomMap.Api.OSM;
using Xamarin.Forms;
using Xamarin.Forms.Maps;
using static TK.CustomMap.Sample.SearchBarModel;
namespace TK.CustomMap.Sample
{
public class SearchBarModel : IPlaceResult
{
public string Subtitle { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public double Latitude { get; set; }
public double Longitude { get; set; }
}
public class PlacesAutoComplete : RelativeLayout
{
public static BindableProperty BoundsProperty = BindableProperty.Create<PlacesAutoComplete, MapSpan>(
p => p.Bounds,
default(MapSpan));
// TODO: SUMMARIES
public enum PlacesApi
{
//Google,
//Osm,
//Native,
//THIS IS MY LIST!
CustomList
}
private readonly bool _useSearchBar;
private bool _textChangeItemSelected;
private SearchBar _searchBar;
private Entry _entry;
private ListView _autoCompleteListView;
private IEnumerable<IPlaceResult> _predictions;
public PlacesApi ApiToUse { get; set; }
public static readonly BindableProperty MapSelectedCommandProperty =
BindableProperty.Create<PlacesAutoComplete, Command<Position>>(
p => p.SetMap, null);
public List<SearchBarModel> myList = new List<SearchBarModel>();
public Command<Position> SetMap
{
get { return (Command<Position>)this.GetValue(MapSelectedCommandProperty); }
set { this.SetValue(MapSelectedCommandProperty, value); }
}
public double HeightOfSearchBar
{
get
{
return this._useSearchBar ? this._searchBar.Height : this._entry.Height;
}
}
private string SearchText
{
get
{
return this._useSearchBar ? this._searchBar.Text : this._entry.Text;
}
set
{
if (this._useSearchBar)
this._searchBar.Text = value;
else
this._entry.Text = value;
}
}
public new MapSpan Bounds
{
get { return (MapSpan)this.GetValue(BoundsProperty); }
set { this.SetValue(BoundsProperty, value); }
}
public PlacesAutoComplete(bool useSearchBar)
{
this._useSearchBar = useSearchBar;
this.Init();
}
public string Placeholder
{
get { return this._useSearchBar ? this._searchBar.Placeholder : this._entry.Placeholder; }
set
{
if (this._useSearchBar)
this._searchBar.Placeholder = value;
else
this._entry.Placeholder = value;
}
}
public PlacesAutoComplete()
{
this._useSearchBar = true;
this.Init();
}
private void Init()
{
OsmNominatim.Instance.CountryCodes.Add("de");
this._autoCompleteListView = new ListView
{
IsVisible = false,
RowHeight = 40,
HeightRequest = 0,
BackgroundColor = Color.White
};
this._autoCompleteListView.ItemTemplate = new DataTemplate(typeof(MapSearchCell));
View searchView;
if (this._useSearchBar)
{
this._searchBar = new SearchBar
{
Placeholder = "Search for address..."
};
this._searchBar.TextChanged += SearchTextChanged;
this._searchBar.SearchButtonPressed += SearchButtonPressed;
searchView = this._searchBar;
}
else
{
this._entry = new Entry
{
Placeholder = "Sarch for address"
};
this._entry.TextChanged += SearchTextChanged;
searchView = this._entry;
}
this.Children.Add(searchView,
Constraint.Constant(0),
Constraint.Constant(0),
widthConstraint: Constraint.RelativeToParent(l => l.Width));
this.Children.Add(
this._autoCompleteListView,
Constraint.Constant(0),
Constraint.RelativeToView(searchView, (r, v) => v.Y + v.Height));
this._autoCompleteListView.ItemSelected += ItemSelected;
this._textChangeItemSelected = false;
}
private void SearchButtonPressed(object sender, EventArgs e)
{
if (this._predictions != null && this._predictions.Any())
this.HandleItemSelected(this._predictions.First());
else
this.Reset();
}
private void SearchTextChanged(object sender, TextChangedEventArgs e)
{
if (this._textChangeItemSelected)
{
this._textChangeItemSelected = false;
return;
}
this.SearchPlaces();
}
private async void SearchPlaces()
{
try
{
if (string.IsNullOrEmpty(this.SearchText))
{
this._autoCompleteListView.ItemsSource = null;
this._autoCompleteListView.IsVisible = false;
this._autoCompleteListView.HeightRequest = 0;
return;
}
IEnumerable<IPlaceResult> result = null;
if (this.ApiToUse == PlacesApi.CustomList)
{
myList.Add(new SearchBarModel
{
Name = "Test1",
Description = "On item select, show me on map!",
Longitude = 20.4680701,
Latitude = 44.8152658
});
myList.Add(new SearchBarModel
{
Name = "Test2",
Description = "On item select, show me on map!",
Longitude = 20.4233035,
Latitude = 44.805651,
});
myList.Add(new SearchBarModel
{
Name = "Test3",
Description = "On item select, show me on map!",
Longitude = 20.456054,
Latitude = 44.8839925
});
myList.Add(new SearchBarModel
{
Name = "Test4",
Description = "On item select, show me on map!",
Longitude = 20.4328035,
Latitude = 44.8071928,
});
result = myList.OfType<IPlaceResult>().ToList<IPlaceResult>();
}
else
{
result = await OsmNominatim.Instance.GetPredictions(this.SearchText);
}
if (result != null && result.Any())
{
this._predictions = result;
this._autoCompleteListView.HeightRequest = result.Count() * 40;
this._autoCompleteListView.IsVisible = true;
this._autoCompleteListView.ItemsSource = this._predictions;
}
else
{
this._autoCompleteListView.HeightRequest = 0;
this._autoCompleteListView.IsVisible = false;
}
}
catch (Exception x)
{
// TODO
}
}
//From here my code partially works
private void ItemSelected(object sender, SelectedItemChangedEventArgs e)
{
if (e.SelectedItem == null) return;
var prediction = (IPlaceResult)e.SelectedItem;
this.HandleItemSelected(prediction);
}
private void HandleItemSelected(IPlaceResult prediction)
{
if (this.SetMap != null && this.SetMap.CanExecute(this))
{
this.SetMap.Execute(prediction);
}
this._textChangeItemSelected = true;
this.SearchText = prediction.Description;
this._autoCompleteListView.SelectedItem = null;
this.Reset();
}
private void Reset()
{
this._autoCompleteListView.ItemsSource = null;
this._autoCompleteListView.IsVisible = false;
this._autoCompleteListView.HeightRequest = 0;
if (this._useSearchBar)
this._searchBar.Unfocus();
else
this._entry.Unfocus();
}
}
}
New at Xamarin and Xamarin.Forms.
I can't find any documentation on EntryCell.ClearValue(BindableProperty p)
I want to clear the second EntryCell when a user goes into the first EntryCell
firstcellEntryCell.Tapped += (sender, e) => secondEntryCell.ClearValue(EntryCell.TextProperty);
Does this make sense, or is this not the intended usage for EntryCell.ClearValue?
I have used the tableview example in the Xamarin Forms documentation for simplicity:
namespace EntryCellTest
{
public class EntryCellTestView : ContentPage
{
public EntryCellTestView ()
{
this.BindingContext = new EntryCellTestViewModel ();
Label header = new Label {
Text = "EntryCell",
Font = Font.BoldSystemFontOfSize (50),
HorizontalOptions = LayoutOptions.Center
};
var entryCell1 = new EntryCell {
Label = "EntryCell1:",
Placeholder = "Type Text Here"
};
entryCell1.SetBinding(EntryCell.TextProperty, new Binding("EntryText1", BindingMode.TwoWay));
var entryCell2 = new EntryCell {
Placeholder = "Type Text Here"
};
// entryCell2.SetBinding (EntryCell.TextProperty, "EntryText2",BindingMode.TwoWay);
entryCell2.SetBinding(EntryCell.TextProperty, new Binding("EntryText2", BindingMode.TwoWay));
entryCell2.SetBinding (EntryCell.LabelProperty, "EntryTextLabelProperty");
TableView tableView = new TableView {
Intent = TableIntent.Form,
Root = new TableRoot {
new TableSection {
entryCell1,
entryCell2
}
}
};
// Accomodate iPhone status bar.
this.Padding = new Thickness (10, Device.OnPlatform (20, 0, 0), 10, 5);
// Build the page.
this.Content = new StackLayout {
Children = {
header,
tableView
}
};
}
}
public class EntryCellTestViewModel : INotifyPropertyChanged
{
public EntryCellTestViewModel ()
{
this.EntryTextLabelProperty = "Just a test";
}
private string entryTextLabelProperty;
public string EntryTextLabelProperty {
get {
return entryTextLabelProperty;
}
set {
entryTextLabelProperty = value;
OnPropertyChanged ("EntryTextLabelProperty");
}
}
private string entryText1;
public string EntryText1 {
get {
return entryText1;
}
set {
entryText1 = value;
OnPropertyChanged ("EntryText1");
}
}
private string entryText2;
public string EntryText2 {
get {
return entryText2;
}
set {
entryText2 = value;
this.EntryText1 = "";
OnPropertyChanged ("EntryText2");
}
}
#region INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged ([CallerMemberName]string propertyName = null)
{
if (PropertyChanged != null) {
PropertyChanged (this, new PropertyChangedEventArgs (propertyName));
}
}
#endregion
}
}
Obviously you change around the bindings and setter logic to achieve the desired result.
I have created a server control and calling it on a page two times.
below is the code
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
namespace DNWebComponent {
[DefaultProperty("Text")]
[ToolboxData("<{0}:DNdropdown runat=server></{0}:DNdropdown>")]
public class DNdropdown : WebControl, IDNComponent {
private string _label;
private TextBox _txtBox;
public String _ConnectedField;
private string _connectedField;
private string _MultiSeekField;
private List<String> _selectedValue;
private string _InputTable;
private CheckBoxList _Checkbox;
Panel div;
public String ConnectedField {
get { return _connectedField; }
set { _connectedField = value; }
}
public DNdropdown(string label)
: this() {
this._label = label;
}
public String Label {
get { return _label; }
set { _label = value; }
}
public DNdropdown() {
_selectedValue = new List<string>();
_txtBox = new TextBox();
_Checkbox = new CheckBoxList();
div = new Panel();
}
public String InputTable {
get { return _InputTable; }
set { _InputTable = value; }
}
public String MultiSeekField {
get { return _MultiSeekField; }
set { _MultiSeekField = value; }
}
public CheckBoxList AspChekcBoxes {
get { return _Checkbox; }
set { _Checkbox = value; }
}
public List<String> SelectedValue {
get {
foreach (ListItem item in _Checkbox.Items) {
if (item.Selected)
_selectedValue.Add(item.Value);
}
return _selectedValue;
}
set {
if (value != null) {
_selectedValue = value;
}
}
}
public string DivCss { get; set; }
protected List<String> GetPropertyValue<v>(string SelectedValue, List<String> nullValue) {
if (ViewState[SelectedValue] == null) {
return nullValue;
}
return (List<String>)ViewState[SelectedValue];
}
protected override void OnInit(EventArgs e) {
div = new Panel { CssClass = DivCss };
FillControl();
div.Controls.Add(new Literal { Text = Label + ": " });
Panel dvTxtBox = new Panel { CssClass = "dt" };
_txtBox.Text = "Select";
_txtBox.ReadOnly = true;
dvTxtBox.Controls.Add(_txtBox);
Panel dvChkBox = new Panel { CssClass = "divco" };
dvTxtBox.Style.Add("float", "right;");
dvTxtBox.Style.Add("margin-right", "700px;");
dvChkBox.Style.Add("margin-right", "700px;");
dvChkBox.Style.Add("float", "right;");
dvChkBox.Controls.Add(_Checkbox);
div.Controls.Add(dvTxtBox);
div.Controls.Add(dvChkBox);
Controls.Add(div);
}
protected override void RenderContents(HtmlTextWriter output) {
div.RenderControl(output);
}
public bool FillControl() {
_Checkbox.Items.Add("a");
_Checkbox.Items.Add("b");
return true;
}
}
}
<asp:PlaceHolder ID="Place1" runat="server">
<div id="DivDrop" runat="server">
</div>
<div id="divbtn">
<div><cc:DNdropdown ID="dropNew" runat="server" Label="DropDown" />
<cc:DNdropdown ID="newcontrol" runat="server" Label="New Dropdown"/></div>
<div ><asp:Button ID="btnSave" Text="Save" runat="server" OnClick="btnSave_Clicked" /></div> </div>
</asp:PlaceHolder>
I registered this conrol in a Sample.aspx page as above and I am using this control over there.dropNew control is working fine but whenever i add a newcontrol to Sample.aspx page Problem starts.I click on one dropdown second one automatically opens
I am creating custom server controls.I created a textbox in this used this control in my page.But when page is posted back(postback) the value of textbox gets omitted..I thought of using viewstate here but m nt getting textbox value .May be m using in wrong way help me plz
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Reflection;
namespace DNWebComponent {
[DefaultProperty("Text")]
[ToolboxData("<{0}:DNTextBox runat=server></{0}:DNTextBox>")]
public class DNTextBox : WebControl, IDNComponent {
public String _ConnectedField;
private string _label;
private TextBox _txtBox;
private string _connectedField;
private string _MultiSeekField;
private string _InputTable;
public string ControlClientID;
public DNTextBox() {
_txtBox = new TextBox();
}
[PersistToViewState]
[Bindable(true)]
[Category("Appearance")]
[DefaultValue("")]
[Localizable(true)]
public string Text {
get {
String s = (String)ViewState["Text"];
return ((s == null) ? "[" + AspTextBox.Text + "]" : s);
}
set {
ViewState["Text"] = value;
}
}
public DNTextBox(string label)
: this() {
this._label = label;
}
public String Label {
get { return _label; }
set { _label = value; }
}
public String ConnectedField {
get { return _connectedField; }
set { _connectedField = value; }
}
public String MultiSeekField {
get { return _MultiSeekField; }
set { _MultiSeekField = value; }
}
public String InputTable {
get { return _InputTable; }
set { _InputTable = value; }
}
public TextBox AspTextBox {
get { return _txtBox; }
set { _txtBox = value; }
}
public string DivCss { get; set; }
protected override void RenderContents(HtmlTextWriter output) {
output.Write("<div class=\"" + DivCss + "\" >");
output.Write(Text);
output.Write(_label + ": ");
_txtBox.RenderControl(output);
output.Write("</div>");
}
public bool FillControl() {
return false;
}
protected override void LoadViewState(object savedState) {
base.LoadViewState(savedState);
PropertyInfo[] properties = GetType().GetProperties();
foreach (PropertyInfo property in properties) {
object[] attributes = property.GetCustomAttributes(typeof(PersistToViewState), true);
if (attributes.Length > 0) {
if (ViewState[property.Name] != null)
property.SetValue(this, ViewState[property.Name], null);
}
}
}
protected override object SaveViewState() {
ViewState["Text"] = AspTextBox.Text;
//PropertyInfo[] properties = GetType().GetProperties();
//foreach (PropertyInfo property in properties) {
// object[] attributes = property.GetCustomAttributes(typeof(PersistToViewState), true);
// if (attributes.Length > 0)
// ViewState[property.Name] = property.GetValue(this, null);
//}
return base.SaveViewState();
}
[AttributeUsage(AttributeTargets.Property)]
public class PersistToViewState : Attribute {
}
}
}
This is another way to achieve what you are trying to do that will handle all the events and viewstate information:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Reflection;
namespace DNWebComponent {
[DefaultProperty("Text")]
[ToolboxData("<{0}:DNTextBox runat=server></{0}:DNTextBox>")]
public class DNTextBox : WebControl, IDNComponent {
public String _ConnectedField;
private string _label;
private TextBox _txtBox;
private string _connectedField;
private string _MultiSeekField;
private string _InputTable;
public string ControlClientID;
public DNTextBox() {
_txtBox = new TextBox();
}
[Bindable(true)]
[Category("Appearance")]
[DefaultValue("")]
[Localizable(true)]
public string Text {
get {
String s = (String)ViewState["Text"];
return ((s == null) ? "[" + AspTextBox.Text + "]" : s);
}
set {
ViewState["Text"] = value;
}
}
public DNTextBox(string label)
: this() {
this._label = label;
}
public String Label {
get { return _label; }
set { _label = value; }
}
public String ConnectedField {
get { return _connectedField; }
set { _connectedField = value; }
}
public String MultiSeekField {
get { return _MultiSeekField; }
set { _MultiSeekField = value; }
}
public String InputTable {
get { return _InputTable; }
set { _InputTable = value; }
}
public TextBox AspTextBox {
get { return _txtBox; }
set { _txtBox = value; }
}
public string DivCss { get; set; }
protected override void OnInit(EventArgs e) {
var div = new Panel{ CssClass = DivCss };
div.Controls.Add(new Literal{ Text = Text });
div.Controls.Add(new Literal{ Text = _label + ":" });
div.Controls.Add(_txtBox);
Controls.Add(div);
}
public bool FillControl() {
return false;
}
}
}
This is happening because you have not added the child text box control to your control - because the text-box is not part of control tree, it will not retain its value (or other properties).
You should derive from CompositeControl (or develop UserControl) instead. For example,
...
public class DNTextBox : CompositeControl, IDNComponent {
private TextBox _txtBox;
protected override void CreateChildControls()
{
_txtBox = new TextBox();
_txtBox.ID = "T";
this.Controls.Add(_textBox);
}
public TextBox AspTextBox
{
get { EnsureChildControls(); return _txtBox; }
}
protected override void RenderContents(HtmlTextWriter output)
{
output.Write("<div class=\"" + DivCss + "\" >");
output.Write(Text);
output.Write(_label + ": ");
base.RenderContents(output); // this will create html for child controls
output.Write("</div>");
}
}
Disclaimer: illustrative code, not tested
Whenever, you need to refer to the text-box, make sure that you call EnsureChildControls as shown in AspTextBox property.
This code worked for me.I added a method add attribute
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
namespace DNWebComponent {
[DefaultProperty("Text")]
[ToolboxData("<{0}:DNTextBox runat=server></{0}:DNTextBox>")]
public class DNTextBox : TextBox, IDNComponent {
public String _ConnectedField;
private string _label;
private TextBox _txtBox;
private string _connectedField;
private string _MultiSeekField;
private string _InputTable;
public string ControlClientID;
public DNTextBox() {
_txtBox = this;
}
public DNTextBox(string label)
: this() {
this._label = label;
}
public String Label {
get { return _label; }
set { _label = value; }
}
public String ConnectedField {
get { return _connectedField; }
set { _connectedField = value; }
}
public String MultiSeekField {
get { return _MultiSeekField; }
set { _MultiSeekField = value; }
}
public String InputTable {
get { return _InputTable; }
set { _InputTable = value; }
}
public TextBox AspTextBox {
get { return this; }
set { _txtBox = value; }
}
public string DivCss { get; set; }
[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand,
Name = "FullTrust")]
protected override void AddAttributesToRender(HtmlTextWriter writer) {
writer.AddAttribute("Label", Label);
writer.AddAttribute("Text", Text);
base.AddAttributesToRender(writer);
}
protected override void RenderContents(HtmlTextWriter output) {
output.Write("<div class=\"" + DivCss + "\" >");
output.Write(_label + ": ");
output.Write("</div>");
}
public bool FillControl() {
return false;
}
}
}