How to set properties of custom controls xamarin forms in xaml - xamarin.forms

My goal is to set the properties of custom controls from a Page using xaml. I'm attempting to create a custom set of menu items, that all look the same but each one contains a different title. How could I set the title of each menu item from Xaml?
For Example sake, Ive simplified my actual code from the project to something simple.
What I want to do is something like this:
<local:CustomControl someCustomAccessor="some text">
While setting the property for the custom control like this:
class CustomControl: ContentView{
private string someText { get; set; }
public static BindableProperty TitleProperty = BindableProperty.CreateAttached("someCustomAccessor", typeof(string), typeof(CustomControl), null, BindingMode.TwoWay);
public CustomControl()
{
Content = new Label
{
Text = someText
};
}
private string someCustomAccessor
{
get { return someText; }
set { someText = value; }
}
}
I've looked everywhere for something like this and have come up short. Please help.

It's been a while since I've done something similar to this, but drawing on my Silverlight experience...
The .CreateAttached("someCustomAccessor" ....
Tells the binding engine to look for a Public property called someCustomAccessor, yours is currently private and will need to be Public. Also change the casing to be SomeCustomAccessor.
Also, the Binder doesn't know that it's a string, so it will need to be cast and set appropriately in the get;set;
public string SomeCustomAccessor
{
get { (string)GetValue(TitleProperty); }
set { SetValue(TitleProperty, value); }
}
Also the binding in your example is TwoWay, it may only need to be OneWay, but you can change that once you've got it working.

Related

Telerik PersistenceFramework: RadGridView PersistenceManager.StorageId

I'm trying to use telerik:PersistenceManager.StorageId property on RadGridView to persist the component status in the local storage.
If I set the property like this:
telerik:PersistenceManager.StorageId="rgvItems"
all works fine but I would like to set the StorageId dynamically using binding.
To do that, I've tried to set the property like this:
telerik:PersistenceManager.StorageId="{Binding Path=StorageId}"
where StorageId is a DependecyProperty defined in the component xaml.cs file:
public string StorageId
{
get
{
return (string) GetValue(StorageIdProperty);
}
set
{
SetValue(StorageIdProperty, value);
}
}
public static readonly DependencyProperty StorageIdProperty =
DependencyProperty.Register("StorageId", typeof(string), typeof(vGridContainer));
and set in the component constructor like this:
public vGridContainer(string storageId)
{
InitializeComponent();
DataContext = this;
StorageId = ConfigurationManager.AppSettings["PersistenceManager.StorageId"]
[...]
}
With that code the grid view status is not persisted.
Am I missing something?
Thank you all in advance :)
I've tried everything about binding property from xaml but nothing worked.
Finally I solved that issues setting the attached dependency property from code like this:
rgvCheckIn.SetValue(Telerik.Windows.Persistence.PersistenceManager.StorageIdProperty, ConfigurationManager.AppSettings["PersistenceManager.StorageId"]);
Now it works fine.
Hope that helps anyone that is experiencing the same issue :)

C# ASP.NET - Controlling/updating a textbox.text value through a class

Newbie here, I need help with a website I'm creating.
I have a class that does some analysis on some text that is input by the user, the class then finds an appropriate answer and sends it back to the textbox. (in theory)
Problem is I don't know how I can control and access the textbox on the default.aspx page from a class, all I get is "object reference is required non static field".
I made the textbox public in the designer file yet still no joy. :(
I've also read this: How can I access the controls on my ASP.NET page from a class within the solution? , which I think is along the lines of what I'm trying to achieve but I need clarification/step by step on how to achieve this.
Hope someone can point me in the right direction.
Many thanks,
Kal
This is the code I have added to the designer.cs file:
public global::System.Web.UI.WebControls.TextBox TextBox3;
public string MyTextBoxText
{
get
{
return TextBox3.Text;
}
set
{
TextBox3.Text = value;
}
}
This is the class method i have created:
public static cleanseMe(string input)
{
string utterance = input;
string cleansedUtt = Regex.Replace(utterance, #"[!]|[.]|[?]|[,]|[']", "");
WebApplication1._Default.TextBox3.text = cleansedUtt;
}
I could just return the cleansedUtt string i know, but is it possible for me to just append this string to the said textbox from this method, within this class?
I also tried it this way, i wrote a class that takes in the name of the textbox and string to append to that textbox. it works BUT only on the default.aspx page and does not recognise the textbox names within the difference classes. The code is as follows:
public class formControl
{
public static void ModifyText(TextBox textBox, string appendthis)
{
textBox.Text += appendthis + "\r\n";
}
I would suggest you that do not access the Page Controls like TextBox in your class. It will be more useful and a good practice that whatever functionality your class does, convert them into function which accept the parameters and returns some value and then on the basis of that value you can set the controls value.
So now you have reusable function that you can use from any of the page you want. You do not need to write it for every textbox.
Here I am giving you a simple example
public class Test
{
public bool IsValid(string value)
{
// Your logic
return true;
}
}
Now you can use it simple on your page like this
Test objTest = new Test();
bool result=objTest.IsValid(TextBox1.Text);
if(result)
{
TextBox1.Text="Everything is correct";
}
else
{
TextBox1.Text="Something went wrong";
}
If you have your class in the same project (Web Project) the following will work:
public class Test
{
public Test()
{
//
// TODO: Add constructor logic here
//
}
public static void ValidateTextBox(System.Web.UI.WebControls.TextBox txt)
{
//validation logic here
if (txt != null)
txt.Text = "Modified from class";
}
}
You can use this from your webform like this:
protected void Page_Load(object sender, EventArgs e)
{
Test.ValidateTextBox(this.txt);
}
If your class is in a different (class project), you would need to add a reference to System.Web to your project.

How to access attributes of inner tags in custom controls in asp.net

I have a custom control for building forms to automatically generate a label-input field pair. But I need to be able to modify attributes of the generated label-input field pair in my vb code behind file. The problem is that the code behind file seems to be applied before the custom control. How do I work around this issue?
You could expose the inner controls as public properties of your custom control.
For example:
public class MyCustomControl : CustomControl
{
Label _label;
// initialize _label in OnInit() ...
public string LabelText { get { return _label.Text; } set { _label.Text = value; } }
}

is there a kind of property only set in a web control constructor?

I have a WebControl and it has a property. However, value of this property should not be changed once the control has been constructed... in other words, the property can be set only in some code like:
<ct:Acontrol ID="xxx" Aproperty="xxx" runat="server"></ct:Acontrol>
but not:
xxx.Aproperty=...
so what is the normal way to do that? Thanks!
The properties that you are using in markup must be public properties with a public getter and setter. There is no special syntax for "only set this once".
What you can do is check in the setter whether it was already set and if so, not set to the new value.
private string _aProperty;
public string Aproperty
{
get { return _aProperty;}
set
{
if(_aProperty == null)
{
_aProperty = value;
}
}
}
You should be able to use
xxx.Attributes("Aproperty")
All ASP.NET markup attributes are set as properties after the constructor is executed. You can select specific read-only properties to be set only in the constructor by using sub-classes of the control.
<!-- Aproperty=xxx -->
<ct:Acontrolxxx ID="xxx" runat="server"></ct:Acontrolyyy>
<!-- Aproperty=yyy -->
<ct:Acontrolyyy ID="yyy" runat="server"></ct:Acontrolxxx>
public class Acontrolxxx : Acontrolbase
{
public Acontrolxxx () { base.Aproperty = xxx; }
}
The property is probably using a combination of the EditorBrowsable and DesignerSerializationVisibility attributes:
[EditorBrowsable(EditorBrowsableState.Never)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public string SomeProperty { get; set; }
The DesignerSerializationVisibility attribute shows the property in markup, and the EditorBrowsable attribute hides the property in code-behind.

Order of fields in Dynamic Data?

Does anybody know if it is possible to choose the order of the fields in Dynamic Data (of course, without customizing the templates of each table) ?
Thanks !
In .NET 4.0, using the 4.0 release of the Dynamic Data dll, you can set data annotations like so:
[Display(Name = " Mission Statement", Order = 30)]
public object MissionStatement { get; set; }
[Display(Name = "Last Mod", Order = 40)]
public object DateModified { get; private set; }
As per this thread - you can use the ColumnOrderAttribute in the dynamic data futures dll. You can grab the futures from codeplex.
You can do this by modifying the order of the public properties in your LINQ to SQL file.
For example, I went into Northwind.designer.cs which was my auto-generated LINQ to SQL file and moved the public property named Products above the public property CategoryName in the public partial class Category. Then I recompiled and the default template displayed the columns in my new order.
Of course, this means your editing auto-generated code and if you regenerate it, your changes are lost, so this technique is not without peril.
You have to create a custom page in DynamicData folder.
Here are the steps:
Create a folder that is the same name as your table name that you want to customize the ordering of columns under "DynamicData\CustomPages" folder
Create a custom page under "DynamicData\CustomPages\[folder with table name]" folder.
I just copy the existing "List.aspx" file from "DynamicData\PageTemplates" into the folder above.
Open the aspx file and modify GridView control to "AutoGenerateColumns='false'"
Inside columns section of GridView, add "DynamicControl" controls with the "DataField" attribute value to the name of your column in the order you want.
Here is a screencast from ScottHa:
http://www.asp.net/learn/3.5-SP1/video-293.aspx
GridView have ColumnsGenerator property, use it by implementing GenerateFields method of IAutoFieldGenerator interface in which you can set fields orders based on your custom rules (attributes, meta info, ...)
protected override void OnInit(EventArgs e)
{
...
this.gvItemsList.ColumnsGenerator = new EntityFieldsGenerator(CurrentDataSource.CurrentTableMetadata);
...
}
public class EntityFieldsGenerator : IAutoFieldGenerator {
...
public ICollection GenerateFields(Control control)
{
// based on entity meta info
var fields = from item in this.entityMetadata.Columns
where this.IncludeColumn(item.Value)
orderby item.Value.Order
select new DynamicField
{
DataField = item.Value.Column.Name,
HeaderText = item.Value.DisplayName,
DataFormatString = item.Value.DataFormatString,
UIHint = GetColumnUIHint(item.Value)
};
return fields.ToList();
} }
To avoid using the Dynamic Data futures dll, you can roll your own ColumnOrder attribute as follows:
[AttributeUsage(AttributeTargets.Property)]
public class ColumnOrderAttribute : Attribute
{
public int Order { get; private set; }
public ColumnOrderAttribute() { Order = int.MaxValue; }
public ColumnOrderAttribute(int order) { Order = order; }
public static ColumnOrderAttribute Default = new ColumnOrderAttribute();
}
and then in your class that implements IAutoFieldGenerator, you have
public static class ExtensionMethods
{
public static int GetOrder (this MetaColumn column)
{
var orderAttribute = column.Attributes.OfType<ColumnOrderAttribute>().DefaultIfEmpty(ColumnOrderAttribute.Default).Single();
return orderAttribute.Order;
}
}
public ICollection GenerateFields(Control control)
{
var fields = new List<DynamicField>();
var columns = _table.Columns.OrderBy(column => column.GetOrder());
foreach (var column in columns)
{
if (!column.Scaffold) { continue; }
fields.Add(new DynamicField {DataField = column.Name});
}
}
and finally your usage would look like
[MetadataType(typeof(CustomerMetadata))]
public partial class Customer {}
public class CustomerMetadata
{
[ColumnOrder(1)]
public object FirstName {get;set;}
[ColumnOrder(2)]
public object LastName {get;set;}
}
I'm answering an old question because it seems to me that the possible solution changed in newer versions of the framework.
It seems that the Display(Order) works now directly as asked (Visual Web Developer 2010 on .NET 4.0) without any particular workaround.
Example:
[Display(Order = 50)]
An important thing it's to check the correct object name to map the foreignkey:
in one project a field OperatoreID translated in the entity class as:
public object Operatore { get; set; }
being Operatore the source table of the foreignkey; for a second reference on the same table it will get something like 1 and so on.

Resources