I'm trying to set underline on UILabel of MvxTableViewCell.
[Register("KittenCell")]
public class KittenCell : MvxTableViewCell
{
private UIImageView MainImage;
private UILabel NameLabel;
private UILabel PriceValueLabel;
private UILabel PriceLabel;
public static readonly NSString Key = new NSString ("KittenCell");
private MvxImageViewLoader imageLoader;
public KittenCell ()
{
CreateLayout ();
InitializeBindings ();
}
public KittenCell(IntPtr handle)
: base(handle)
{
CreateLayout ();
InitializeBindings ();
}
void CreateLayout ()
{
MainImage = new UIImageView (new RectangleF (0, 0, 160, 100));
NameLabel = new UILabel (new RectangleF (168, 15, 144, 21));
NameLabel.TextAlignment = UITextAlignment.Left;
var attrs = new UIStringAttributes {
UnderlineStyle = NSUnderlineStyle.Single
};
NameLabel.AttributedText =new NSAttributedString(NameLabel.Text,attrs);
PriceLabel = new UILabel (new RectangleF (168, 59, 57, 21));
PriceLabel.Text = "Price:";
PriceLabel.TextAlignment = UITextAlignment.Left;
PriceValueLabel = new UILabel (new RectangleF (228, 59, 84, 21));
PriceValueLabel.TextAlignment = UITextAlignment.Left;
PriceValueLabel.TextColor = UIColor.Blue;
ContentView.AddSubviews (MainImage, NameLabel, PriceLabel, PriceValueLabel);
}
void InitializeBindings ()
{
imageLoader = new MvxImageViewLoader (() => this.MainImage);
this.DelayBind (() => {
var set = this.CreateBindingSet<KittenCell, Kitten> ();
set.Bind (NameLabel).To(kitten => kitten.Name);
set.Bind (PriceValueLabel).To(kitten => kitten.Price);
set.Bind (imageLoader).To(kitten => kitten.ImageUrl);
set.Apply ();
});
}
}
but when UILabel is shown there is no underline under it. My explanation is that underline is applied on text that is not already binded. But how is possible to set it after binding?
You could use a converter something along this:
public class UnderlineTextValueConverter : MvxValueConverter<string, NSAttributedString>
{
protected override NSAttributedString Convert(string value, Type targetType, object parameter, CultureInfo cultureInfo)
{
var attrs = new UIStringAttributes {
UnderlineStyle = NSUnderlineStyle.Single
};
return new NSAttributedString(value, attrs);
}
}
and then update your binding to this...
set.Bind (NameLabel).For(l => l.AttributedText).To(kitten => kitten.Name).WithConversion("UnderlineText", null);
The above code is untested, but it should work with no or little modification.
Related
I have a Xamarin.Forms app that displays a ViewFlipper (https://github.com/TorbenK/ViewFlipper) inside a CarouselView.
I would like the ViewFlipper to flip back to the front when changing pages inside the carousel. But I can't seem to figure out how to access the ViewFlipper.
I have the following working code:
public class CarouselContent
{
public string FrontImg { get; set; }
public string BackImg { get; set; }
}
public class MainPage : ContentPage
{
public MainPage()
{
var pages = new ObservableCollection<CarouselContent>();
var page1 = new CarouselContent();
page1.FrontImg = "page1Front";
page1.BackImg = "page1Back";
var page2 = new CarouselContent();
page2.FrontImg = "page2Front";
page2.BackImg = "page2Back";
pages.Add(page1);
pages.Add(page2);
var carouselView = new Carousel(pages);
Content = carouselView;
}
}
public class Carousel : AbsoluteLayout
{
private DotButtonsLayout dotLayout;
private CarouselView carousel;
public Carousel(ObservableCollection<CarouselContent> pages)
{
carousel = new CarouselView();
var template = new DataTemplate(() =>
{
//create page
var absLayout = new AbsoluteLayout();
//create images for the flipper
var frontImg = new Image
{
Aspect = Aspect.AspectFit
};
frontImg.SetBinding(Image.SourceProperty, "FrontImg");
var backImg = new Image
{
Aspect = Aspect.AspectFit
};
backImg.SetBinding(Image.SourceProperty, "BackImg");
//create flipper
var flipper = new ViewFlipper.FormsPlugin.Abstractions.ViewFlipper();
flipper.FrontView = frontImg;
flipper.BackView = backImg;
//Add flipper to page
absLayout.Children.Add(flipper);
return absLayout;
});
carousel.ItemsSource = pages;
carousel.ItemTemplate = template;
Children.Add(carousel);
}
}
I tried adding the ViewFlipper to the CarouselContent but I couldn't get that to work. Any ideas?
EDIT:
I tried creating an AbsoluteLayout with bindable items and bind the items created in CarouselContent in the datatemplate of the CarouselView, but the line '(b as BindableAbsLayout).Children.Add((View)v);' in BindableAbsLayout is never called. What am I doing wrong?
class BindableAbsLayout : AbsoluteLayout
{
public static readonly BindableProperty ItemsProperty =
BindableProperty.Create(nameof(Items), typeof(ObservableCollection<View>), typeof(BindableAbsLayout), null,
propertyChanged: (b, o, n) =>
{
(n as ObservableCollection<View>).CollectionChanged += (coll, arg) =>
{
switch (arg.Action)
{
case NotifyCollectionChangedAction.Add:
foreach (var v in arg.NewItems)
(b as BindableAbsLayout).Children.Add((View)v);
break;
case NotifyCollectionChangedAction.Remove:
foreach (var v in arg.NewItems)
(b as BindableAbsLayout).Children.Remove((View)v);
break;
}
};
});
public ObservableCollection<View> Items
{
get { return (ObservableCollection<View>)GetValue(ItemsProperty); }
set { SetValue(ItemsProperty, value); }
}
}
public class CarouselContent
{
private ViewFlipper.FormsPlugin.Abstractions.ViewFlipper _flipper;
private ObservableCollection<View> _items;
public ObservableCollection<View> Items
{
get { return _items; }
}
public CarouselContent(string frontImgStr, string backImgStr)
{
_items = new ObservableCollection<View>();
_flipper = new ViewFlipper.FormsPlugin.Abstractions.ViewFlipper();
var frontImg = new Image
{
Aspect = Aspect.AspectFit
};
frontImg.Source = frontImgStr;
var backImg = new Image
{
Aspect = Aspect.AspectFit
};
backImg.Source = backImgStr;
_flipper.FrontView = frontImg;
_flipper.BackView = backImg;
AbsoluteLayout.SetLayoutBounds(_flipper, new Rectangle(0.5, 0.05, 0.85, 0.85));
AbsoluteLayout.SetLayoutFlags(_flipper, AbsoluteLayoutFlags.All);
Items.Add(_flipper);
}
}
public class Carousel : AbsoluteLayout
{
private DotButtonsLayout dotLayout;
private CarouselView carousel;
public Carousel(ObservableCollection<CarouselContent> pages)
{
carousel = new CarouselView();
var template = new DataTemplate(() =>
{
var absLayout = new BindableAbsLayout();
absLayout.BackgroundColor = Color.FromHex("#68BDE4");
absLayout.SetBinding(BindableAbsLayout.ItemsProperty,"Items");
return absLayout;
});
carousel.ItemsSource = pages;
carousel.ItemTemplate = template;
Children.Add(carousel);
}
}
Not sure what the best practice is here, but you could try accessing it via the ItemSelected Event (which fires every time you change back and forth in the carouselview)
Wire it up
carousel.ItemSelected += carouselOnItemSelected;
Get your ViewFlipper
private void carouselOnItemSelected(object sender, SelectedItemChangedEventArgs selectedItemChangedEventArgs)
{
CarouselContent carouselContent = selectedItemChangedEventArgs.SelectedItem;
ViewFlipper viewFlipper = carouselContent.Children[0];
viewFlipper.FlipState = ViewFlipper.FrontView;
}
Sample Class:
public abstract class SomeBase
{
protected int _x = 100;
public abstract int X { get; }
protected int _y = 200;
public abstract int Y { get; }
}
public class SomeBody : SomeBase
{
public override int X { get { return _x + 10; } }
public override int Y { get { return _y + 20; } }
private int _z = 300;
public int Z { get { return _z + 30; } }
}
public class SomeOne : SomeBase
{
public override int X { get { return _x - 10; } }
public override int Y { get { return _y - 20; } }
private int _a = 300;
public int A { get { return _a - 30; } }
}
Object to ExpandoObject Method:
public static ExpandoObject ToExpandoObject<T>(this T target)
{
var jsonSerializerSettings = new JsonSerializerSettings();
jsonSerializerSettings.Converters.Add(new StringEnumConverter());
var json = JsonConvert.SerializeObject(target, Formatting.Indented, jsonSerializerSettings);
var expandoObject = JsonConvert.DeserializeObject<ExpandoObject>(json, new ExpandoObjectConverter());
return expandoObject;
}
Convert ExpandoObject to abstract object:
//someBase
//X = 110, Y = 220, Z = 330
SomeBase someBase = new SomeBody();
//someOne
//X = 90, Y = 180, A = 270
dynamic someOne = new SomeOne().ToExpandoObject();
Mapper.Initialize(cfg =>
{
cfg.CreateMap<SomeBase, SomeBase>();
});
//I want
//someBase
//X = 90, Y = 180, A = 270
Mapper.Map<ExpandoObject, SomeBase>(someOne, someBase);
But error occurs.
Instances of abstract classes can not be created
How can we handle this problem?
AutoMapper version is 6.02
*Please consider using Google translator because English is immature.
UPDATE:
I know about abstract.
I just want to know if AutoMapper can do the following:
SomeBody someBody = new SomeBody();
//someBase
//X = 110, Y = 220, Z = 330
SomeBase someBase = someBody;
SomeOne someOne = new SomeOne();
//someBase
//X = 90, Y = 180, A = 270
someBase = someOne;
UPDATE Again...
TestClass
public class TestClass
{
public int IntValue { get; set; }
public SomeBase SomeBase { get; set; }
}
My final goal is :
var testClass = new TestClass();
testClass.IntValue = 10;
testClass.SomeBase = new SomeBody();
dynamic expandoObject = testClass.ToExpandoObject();
expandoObject.SomeBase = new SomeOne().ToExpandoObject();
Mapper.Initialize(cfg =>
{
cfg.CreateMap<TestClass, TestClass>();
});
///Mapping the expandoObject object that changed the property to the testClass object again
///My expectation is that the type of SomeBase Property in testClass is SomeOne.
Mapper.Map<ExpandoObject, TestClass>(expandoObject, testClass);
Thank you very much for helping me with insufficient English and insufficient explanation.
My solution
var testClass = new TestClass();
testClass.IntValue = 10;
testClass.SomeBase = new SomeBody();
dynamic expandoObject = testClass.ToExpandoObject();
expandoObject.SomeBase = new SomeOne().ToExpandoObject();
Mapper.Initialize(cfg =>
{
cfg.CreateMap<ExpandoObject, SomeBase>().ConvertUsing(new SomeBaseConverter());
cfg.CreateMap<FirstItem, FirstItem>();
});
Mapper.Map<ExpandoObject, TestClass>(expandoObject, testClass);
Debug.WriteLine(testClass.SomeBase.GetType().ToString());
///"Sample.Common.Models.SomeOne"
SomeBaseConverter:
public class SomeBaseConverter : ITypeConverter<object, SomeBase>
{
public SomeBase Convert(dynamic source, SomeBase destination, ResolutionContext context)
{
var dictionary = source as IDictionary<string, object>;
if (dictionary.ContainsKey("Z"))
{
var someBody = new SomeBody();
var config = new MapperConfiguration(cfg => cfg.CreateMap<ExpandoObject, SomeBody>());
config.CreateMapper().Map(source, someBody);
destination = someBody;
}
else
{
var someOne = new SomeOne();
var config = new MapperConfiguration(cfg => cfg.CreateMap<ExpandoObject, SomeOne>());
config.CreateMapper().Map(source, someOne);
destination = someOne;
}
return destination;
}
}
See the MSDN article re abstract classes.
The important part for you is:
An abstract class cannot be instantiated.
You need to map to one of the derived classes, or remove the abstract modifier from the base class.
AutoMapper is great if you have statically-typed objects. It handles polymorphism very well:
Mapper.CreateMap<SomeBase1, SomeBase2>()
.Include<SomeBody1, SomeBody2>()
.Include<SomeOne1, SomeOne2>();
Mapper.CreateMap<SomeBody1, SomeBody2>();
Mapper.CreateMap<SomeOne1, SomeOne2>();
// for a single object:
SomeBase1 source = GetDatum();
SomeBase2 = Mapper.Map<SomeBase1, SomeBase2>();
// for an IEnumerable:
IEnumerable<SomeBase1> source = GetData();
IEnumerable<SomeBase2> = Mapper.Map<IEnumerable<SomeBase1>, IEnumerable<SomeBase2>>(source);
But you're using ExpandoObject, so it's more difficult. If you can differentiate which class you need by the data in the ExpandoObject, you could try something like this:
Mapper.CreateMap<ExpandoObject, SomeBase>()
.ConstructUsing((ExpandoObject input) => {
if (input.X == 5)
{
return new SomeOne();
}
else
{
return new SomeBody();
}
});
and then the code you were using before Mapper.Map<Expandoobject, SomeBase>(...) will work. Otherwise, you could specifically tell it which type to map to: Mapper.DynamicMap<SomeBody>(someOne);
I was profiling a WPF application that uses Catel as MVVM Framework and I've seen that in a ViewModel I've got 2 retention path as
Now I create such RadMenuItem in a behavior I attach to the context menu and they're defined as
protected virtual IEnumerable<RadMenuItem> GetRowMenuItems(RadContextMenu contextMenu)
{
var rowItems = new List<RadMenuItem>();
RadMenuItem saveSettings = new RadMenuItem
{
Tag = "force",
Header = CoreResources.LBL_SAVE_SETTINGS,
Command = DefaultRtViewContextMenuCommands.SaveLayoutDataCommand,
CommandParameter = AssociatedObject,
Icon = new Image { Source = new BitmapImage(new Uri("pack://application:,,,/IF.Tesoreria.Client.WPF.Core;component/Media/save.png")) }
};
rowItems.Add(saveSettings);
RadMenuItem loadSettings = new RadMenuItem
{
Tag = "force",
Header = CoreResources.LBL_LOAD_SETTINGS,
Command = DefaultRtViewContextMenuCommands.LoadLayoutDataCommand,
CommandParameter = AssociatedObject,
Icon = new Image { Source = new BitmapImage(new Uri("pack://application:,,,/IF.Tesoreria.Client.WPF.Core;component/Media/load.png")) }
};
Now The commands are defined in
public class DefaultRtViewContextMenuCommands
{
public static Command<FlexGridCommandParameter> SaveLayoutDataCommand { get; private set; }
public static Command<FlexGridCommandParameter> LoadLayoutDataCommand { get; private set; }
private static void OnLoadLayoutCommandExecute(FlexGridCommandParameter grid)
{
Argument.IsNotNull(() => grid);
var dependencyResolver = DependencyResolverManager.Default;
var openFileService = dependencyResolver.DefaultDependencyResolver.Resolve<IOpenFileService>();
openFileService.Filter = "Gridview setting file|*.flexgrid";
if (openFileService.DetermineFile())
{
// User selected a file
using (var fs = File.OpenRead(openFileService.FileName))
{
GridViewPersistenceHelper.LoadLayout(grid.Grid, fs, null);
}
}
}
private static void OnSaveLayoutCommandExecute(FlexGridCommandParameter grid)
{
Argument.IsNotNull(() => grid);
var dependencyResolver = DependencyResolverManager.Default;
var saveFileService = dependencyResolver.DefaultDependencyResolver.Resolve<ISaveFileService>();
saveFileService.Filter = "Gridview setting file|*.flexgrid";
if (saveFileService.DetermineFile())
{
// User selected a file
using (var fs = File.OpenWrite(saveFileService.FileName))
{
GridViewPersistenceHelper.SaveLayout(grid.Grid, fs);
}
}
}
static DefaultRtViewContextMenuCommands()
{
viewModelFactory = ServiceLocator.Default.ResolveType<IViewModelFactory>();
portfolioService = ServiceLocator.Default.ResolveType<IPortfoliosService>();
pkInstrumentsService = ServiceLocator.Default.ResolveType<IPkInstrumentsService>();
SaveLayoutDataCommand = new Command<FlexGridCommandParameter>(OnSaveLayoutCommandExecute,_=>true);
LoadLayoutDataCommand = new Command<FlexGridCommandParameter>(OnLoadLayoutCommandExecute,_=>true);
}
What am I doing wrong?
Thanks
radMenuItem.Command = null;
Works for me. You can decompile and see that when you do it, the menu item unregisters himself from the Command’s CanExecuteChanged
I would like to display two section tableviewcontroller. I have two urls to call to get json object and tabulate them in tableviewcontroller. I could not able to figure out how to Create a single TableSource that can handle two different instances of List.
I am posting here full source code here. I will be glad if any one able to help me out in this problem, either share a link that would be useful, or share the code.
public override nint RowsInSection(UITableView tableview, nint section)
returns me an "object reference not set" error. It seems to me that once I fecth data from the first url and it tries to tabulate tableview, however, the other URL data at that time may not be ready.
namespace TPM
{
partial class IViewController : UIViewController
{
public List<HumanTask> cTasks;
public List<HumanTask> aTasks;
public InboxViewController (IntPtr handle) : base (handle)
{
this.Title = "Inside";
}
public override void ViewDidLoad()
{
base.ViewDidLoad ();
GInbox ();
CInbox ();
}
public void CInbox()
{
var client = new RestClient ("URL");
client.Authenticator = new HttpBasicAuthenticator ("admin", "admin");
var request = new RestRequest ("other part URL");
request.AddHeader ("Accept", "application/json");
request.AddHeader ("Content-Type", "application/json");
client.ExecuteAsync (request, response => {
cTasks = Newtonsoft.Json.JsonConvert.DeserializeObject<List<HTask>> (response.Content);
InvokeOnMainThread (() => {
TableView.Source= new TableSource(cTasks,this,0);
TableView.ReloadData();
});
});
}
public void GInbox()
{
var client = new RestClient ("URL");
client.Authenticator = new HttpBasicAuthenticator ("admin", "admin");
var request = new RestRequest ("the rest URL");
request.AddHeader ("Accept", "application/json");
request.AddHeader ("Content-Type", "application/json");
client.ExecuteAsync (request, response => {
aTasks = Newtonsoft.Json.JsonConvert.DeserializeObject<List<HTask>> (response.Content);
InvokeOnMainThread (() => {
TableView.Source= new TableSource(aTasks,this,1);
TableView.ReloadData();
});
});
}
public class TableSource:UITableViewSource{
List<HTask>cTableItems;
List<HTask>aTableItems;
int defi;
string cellIdentifier="TableCell";
private IViewController iv;
public TableSource (List<HTask>items, IViewController vc, int def)
{
if(def==0)
{
cTableItems=items;
}
else if(def==1)
{
aTableItems=items;
}
iv=vc;
defi=def;
}
public override nint NumberOfSections (UITableView tableView)
{
return 2;
}
public override nfloat GetHeightForHeader (UITableView tableView, nint section)
{
if(section==0){
return 40;
}
if(section == 1) {
return 40;
}
return 40;
}
public override UIView GetViewForHeader(UITableView tableView, nint section)
{
UIView headerView = new UIView(new RectangleF (0, 0, (float)UIScreen.MainScreen.Bounds.Width, (float)tableView.SectionHeaderHeight));
headerView.BackgroundColor = UIColor.Black;
UILabel sectionTitle = new UILabel( new RectangleF(10, (float)((headerView.Frame.Height - 22) / 2), 200, 24));
sectionTitle.Font = UIFont.BoldSystemFontOfSize(22);
sectionTitle.TextColor = UIColor.White;
sectionTitle.TextAlignment = UITextAlignment.Right;
if (section == 0) {
sectionTitle.Text = "Cmed";
}
else if (section == 1) {
sectionTitle.Text = "Asy";
}
headerView.AddSubview(sectionTitle);
return headerView;
}
public override nint RowsInSection(UITableView tableview, nint section)
{
if (section == 0)
return cTableItems.Count;
else
return aTableItems.Count;
}
public override UITableViewCell GetCell (UITableView tableView, Foundation.NSIndexPath indexPath)
{
UITableViewCell cell = tableView.DequeueReusableCell(cellIdentifier);
if (cell == null)
cell = new UITableViewCell(UITableViewCellStyle.Subtitle, cellIdentifier);
if (indexPath.Section == 0) {
cell.TextLabel.Text = cTableItems [indexPath.Row].displayName;
cell.DetailTextLabel.Lines = 3;
cell.DetailTextLabel.Text = "Process ID:" + cTableItems [indexPath.Row].processInstanceId + "\n" + DateTime.Parse (Convert.ToDateTime (cTableItems [indexPath.Row].createdOn).ToShortTimeString ());
if (cTableItems [indexPath.Row].priority == 0) {
cell.ImageView.Image = UIImage.FromFile ("Images/green.png");
}
else if (cTableItems [indexPath.Row].priority == 1) {
cell.ImageView.Image = UIImage.FromFile ("Images/yellow.png");
}
else if (cTableItems [indexPath.Row].priority == 2) {
cell.ImageView.Image = UIImage.FromFile ("Images/red.png");
}
}
else if (indexPath.Section == 1) {
cell.TextLabel.Text = assignTableItems [indexPath.Row].displayName;
cell.DetailTextLabel.Lines = 3;
cell.DetailTextLabel.Text = "Process ID:" + aTableItems [indexPath.Row].processInstanceId + "\n" + DateTime.Parse (Convert.ToDateTime (aTableItems [indexPath.Row].createdOn).ToShortTimeString ());
if (aTableItems [indexPath.Row].priority == 0) {
cell.ImageView.Image = UIImage.FromFile ("Images/green.png");
}
else if (aTableItems [indexPath.Row].priority == 1) {
cell.ImageView.Image = UIImage.FromFile ("Images/yellow.png");
}
else if (aTableItems [indexPath.Row].priority == 2) {
cell.ImageView.Image = UIImage.FromFile ("Images/red.png");
}
}
cell.Accessory = UITableViewCellAccessory.DisclosureIndicator;
return cell;
}
public override nfloat GetHeightForRow (UITableView tableView, Foundation.NSIndexPath indexPath)
{
return 60;
}
}
}
}
Based on Jason answer: I am getting the following error:
Second update based on Jason answer:
Third update based on Jason answer:
Instead of passing the two sets of data in the constructor, pass them as properties - this allows you to set them after the Source has been created, which is useful since you are getting the data asynchronously.
public class TableSource:UITableViewSource{
public List<HTask> cTableItems;
public List<HTask> aTableItems;
string cellIdentifier="TableCell";
private IViewController iv;
public TableSource (IViewController vc)
{
aTableItems = new List<HTask>();
cTableItems = new List<HTask>();
iv=vc;
}
Then create your Source once when you create the VC
public override void ViewDidLoad()
{
base.ViewDidLoad ();
TableView.Source = new TableSource(this);
GInbox ();
CInbox ();
}
Finally, when you get the data don't recreate your Source, just update it with the data: (repeat the same thing for your other dataset)
public void CInbox()
{
var client = new RestClient ("URL");
client.Authenticator = new HttpBasicAuthenticator ("admin", "admin");
var request = new RestRequest ("other part URL");
request.AddHeader ("Accept", "application/json");
request.AddHeader ("Content-Type", "application/json");
//request.Method = (string)"GET";
client.ExecuteAsync (request, response => {
cTasks = Newtonsoft.Json.JsonConvert.DeserializeObject<List<HTask>> (response.Content);
InvokeOnMainThread (() => {
((TableSource)this.TableView.Source).cTableItems = cTasks;
TableView.ReloadData();
});
});
I have been trying to change the color of UItextfield placeholder and I have had no luck. I have tried sub classing, and I have tried modifying the Attributed string but nothing worked.
This is the subclass I tried.
public class CustomTextbox : UITextField
{
private string placeholder{ get; set; }
public CustomTextbox ()
{
}
public CustomTextbox(string theString)
{
this.placeholder = theString;
}
public override void DrawPlaceholder (RectangleF rect) {
using (UIFont font = UIFont.SystemFontOfSize (16))
using (UIColor col = new UIColor (UIColor.Blue.CGColor)) {
col.SetFill (); col.SetStroke (); col.SetColor (); base.DrawString (base.Placeholder,rect, font); } }
}
This is the attributed string method I tried:
var textat = new NSMutableAttributedString ("Email", new CTStringAttributes () {
ForegroundColor = UIColor.White.CGColor,StrokeColor = UIColor.White.CGColor,
StrokeWidth = 5.0f
});
this.emailtextbox.AttributedPlaceholder = textat;
Just simplify what you already have.
This works on iOS7:
var t = new UITextField()
{
AttributedPlaceholder = new NSAttributedString("some placeholder text", null, UIColor.Red)
}
The monotuch way to do this is (the answer is found here)
myLogin.AttributedPlaceholder = new NSAttributedString (
"Enter your credentials",
font: UIFont.FromName ("HoeflerText-Regular", 24.0f),
foregroundColor: UIColor.Red,
strokeWidth: 4
);
Try this one:
[yourtextField setValue:[UIColor blueColor] forKeyPath:#"_placeholderLabel.textColor"];