Convert Xamarin.Forms.Binding into System.string - xamarin.forms

How would you convert a binding object into a string? I'm trying to bind text to a property using a bindable property, but I'm getting an error that says
cannot convert from Xamarin.Forms.Binding to System.string.
I assumed the BindableProperty returnType typeof(string) would have caught this.
Here's my front-end code (App.rug.Length is a string):
<local:MenuItem ItemTitle="Length" ItemImage="icons/blue/next" ItemSubText="{Binding App.rug.Length}" PageToo="{Binding lengthpage}"/>
Here's my back-end code:
public class MenuItem : ContentView
{
private string itemsubtext { get; set; }
public static BindableProperty SubTextProperty = BindableProperty.Create("ItemSubText", typeof(string), typeof(MenuItem), null, BindingMode.TwoWay);
public MenuItem()
{
var menuTapped = new TapGestureRecognizer();
menuTapped.Tapped += PushPage;
StackLayout Main = new StackLayout
{
Children = {
new SectionLine(),
new StackLayout {
Padding = new Thickness(10),
Orientation = StackOrientation.Horizontal,
HorizontalOptions = LayoutOptions.Fill,
Children = {
new Label {
Margin = new Thickness(10, 2, 10, 0),
FontSize = 14,
TextColor = Color.FromHex("#c1c1c1"),
HorizontalOptions = LayoutOptions.End,
Text = this.ItemSubText
}
}
}
}
};
Main.GestureRecognizers.Add(menuTapped);
Content = Main;
}
public string ItemSubText
{
get { return itemsubtext; }
set { itemsubtext = value; }
}
}
Here is the error:
Xamarin.Forms.Xaml.XamlParseException: Position 26:68. Cannot assign
property "ItemSubText": type mismatch between "Xamarin.Forms.Binding"
and "System.String"

the issue you are getting is probably caused by the binding you have used for the subtext property.
Your variable App.rug.Length is a static variable so therefore you will need to specify it in the binding like below
<local:MenuItem ItemTitle="Length" ItemImage="icons/blue/next" ItemSubText="{Binding Source={x:Static local:App.rug.Length}}" PageToo="{Binding lengthpage}"/>
where
xmlns:local="clr-namespace:{App Namespace here}"
Also fix up your property Accessors for ItemSubText property
public string ItemSubText
{
get { return (string)GetValue (SubTextProperty); }
set { SetValue (SubTextProperty, value); }
}

Related

How to set icon of a button in ViewModel?

I have an icon button and i need to change the icon once user presses the button. I used to change it in the content page before, now if i dont set the value at the top there is no icon what so ever and if i set it in my load method the picture wont check, but if i set it the the top i cant change it either.
private string _playPauseButton = IconsFont.Volume2;
public string PlayPauseButton
{
get { return _playPauseButton; }
set
{
_playPauseButton = value;
NotifyPropertyChanged(nameof(_playPauseButton));
}
}
public ViewModel()
: base(listenCultureChanges: true)
{
Task.Run(async () => await LoadAllDataForDictionary()).Wait();
PlayPauseCommand = new Command(() => StartOrStopPlaying());
}
private void StartOrStopPlaying()
{
if (!viewDisabled)
{
var paused = LangUpDictionaryPlayer.PlayPause();
if (paused)
{
LangUpDictionaryPlayer.SetTrack(_word.Id);
_playPauseButton = IconsFont.AudioPause;
}
else
{
_playPauseButton = IconsFont.Volume2;
}
}
}
Also
what difference would i make by doing this
public string PlayPauseButton
{
set
{
_playPauseButton = value;
NotifyPropertyChanged();
}
get => _playPauseButton;
}
INsted of what i have?
Solved it by using the Public in the code
PlayPauseButton = IconsFont.AudioPause;

mvvm Failed to create target binding for binding

I've read a lot of solutions on the current problem but none of them worked and I cannot
figure out how to do the following:
the converter
public class HexToUIColorValueConverter : MvxValueConverter<int, UIColor>
{
protected override UIColor Convert(int value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return UIColor.FromRGB(
(((float)((value & 0xFF0000) >> 16)) / 255.0f),
(((float)((value & 0xFF00) >> 8)) / 255.0f),
(((float)(value & 0xFF)) / 255.0f)
);
}
}
the binding
public SubtitleDetailViewCell(IntPtr handle)
: base(handle)
{
Initialize();
this.DelayBind(() =>
{
Accessory = UITableViewCellAccessory.DisclosureIndicator;
var set = this.CreateBindingSet<SubtitleDetailViewCell, ObservationMedicale>();
set.Bind(MainLbl).To(observation => observation.Texte).WithConversion(new ByteArrayToStringValueConverter(), null);
set.Bind(LeftDetailLbl).To(observation => observation.SaisieLe).WithConversion(new StringFormatValueConverter(), "d MMM, HH:mm");
set.Bind(RightDetailImgLbl.Label).SourceDescribed("PraticienNom + ' ' + PraticienPrenom");
set.Bind(Label.Color).To(observation => observation.ObsCategorieCouleur).WithConversion(new HexToUIColorValueConverter(), null);
set.Apply();
});
}
the binded object
using System;
using System.Drawing;
using MonoTouch.CoreGraphics;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
namespace Next.Client.Application.iOS.Views.UI
{
[Register("CellLabelView")]
public class CellLabelView : UIView
{
public UIColor Color { get; set; }
public CellLabelView()
{
Initialize();
}
public CellLabelView(IntPtr handle)
: base(handle)
{
}
public CellLabelView(RectangleF bounds)
: base(bounds)
{
Initialize();
}
void Initialize()
{
BackgroundColor = UIColor.Clear;
Opaque = false;
}
public override void Draw(RectangleF rect)
{
base.Draw(rect);
// get graphics context
using (CGContext gc = UIGraphics.GetCurrentContext())
{
// set up drawing attributes
gc.SetLineWidth(1);
_color.SetFill();
UIColor.Clear.SetStroke();
//create geometry
var path = new CGPath();
path.AddLines(new PointF[]{
new PointF (0, 0),
new PointF (0, 8),
new PointF (4, 4),
new PointF (8, 8),
new PointF (8, 0)
});
path.CloseSubpath();
//add geometry to graphics context and draw it
gc.AddPath(path);
gc.DrawPath(CGPathDrawingMode.FillStroke);
}
}
}
}
I don't understand how it fails to bind the color, the SET method on CellLabel is never called and so my Color in the Draw() method isn't a valid object.
Currently you are trying to bind the color object directly - rather than trying to bind the color property on your label.
Try:
set.Bind(Label).For(l => l.Color).To(observation => observation.ObsCategorieCouleur).WithConversion(new HexToUIColorValueConverter(), null);
For a breakdown on this fluent syntax, including For, see https://github.com/MvvmCross/MvvmCross/wiki/Databinding#fluent
Beyond this, you probably also should try to change your Color auto-property to a property with some code inside that requests a redraw via Invalidate whenever the color is changed.

Moq how to do a setup when the item could be any of a type but must have a particular property set

I'm trying to setup for a method which will run:
dataAccess.Setup(x => x.GetCars(It.IsAny<CarFilter>()));
Ok, so I'm saying to setup the method GetCars when it is passed any object of type CarFilter.
I want to make this a little more specific.
I want to make it so it will setup when it is passed any object of type CarFilter when the property on CarFilter Color = "Red".
Does anybody know how to write this?
You can put a condition on the match using It.Is(...)
public class Car {
public string Color { get; set; }
}
public interface IFoo {
void DoIt(Car car);
}
[TestMethod]
public void PassesWhenRed() {
var mockFoo = new Mock<IFoo>();
var redCar = new Car { Color = "Red" };
mockFoo.Object.DoIt(redCar);
mockFoo.Verify(mk=>mk.DoIt(It.Is<Car>(car => car.Color == "Red"))); // Passes
}
[TestMethod]
public void FailsWhenNotRed() {
var mockFoo = new Mock<IFoo>();
var blueCar = new Car { Color = "Blue" };
mockFoo.Object.DoIt(blueCar);
mockFoo.Verify(mk=>mk.DoIt(It.Is<Car>(car => car.Color == "Red"))); // Fails
}
Ended up needing:
dataAccess.Setup(x => x.GetCars(It.Is<CarFilter>(z => z.Color == "Red")));

Enable Always on Top For Caliburn Managed Window

I have the following ViewModel and I am using Caliburn Micro. The IWindowManager instance is properly resolved and all of the code works. As indicated by the TODO comment, I need to get a reference to the current window so I can toggle the AlwaysOnTop attribute. How can I do that?
namespace CaliburnWizardPlay
{
[Export(typeof(DropWindowViewModel))]
public class DropWindowViewModel : PropertyChangedBase, IHaveDisplayName
{
private readonly IWindowManager windowManager;
[ImportingConstructor]
public DropWindowViewModel(IWindowManager windowManager)
{
this.windowManager = windowManager;
}
public string DisplayName
{
get { return "Main Window"; }
set { }
}
public bool AlwaysOnTop
{
get { return Settings.Default.DropWindowAlwaysOnTop; }
set
{
Settings.Default.DropWindowAlwaysOnTop = value;
Settings.Default.Save();
NotifyOfPropertyChange(() => AlwaysOnTop);
//todo: toggle the AOT attribute of the window
}
}
public void FileDropped(DragEventArgs eventArgs)
{
if (eventArgs.Data.GetDataPresent(DataFormats.FileDrop))
{
string[] droppedFilePaths = eventArgs.Data.GetData(DataFormats.FileDrop, true) as string[];
foreach (string path in droppedFilePaths)
{
MessageBox.Show(path);
}
windowManager.ShowWindow(new WizardViewModel());
}
}
}
}
You can use the settings parameter of the ShowWindow method to set any property (e.g. Topmost) on the created window with a dictionary containing propertyname-value pairs:
windowManager.ShowWindow(new WizardViewModel(),
settings: new Dictionary<string,object> { {"Topmost", AlwaysOnTop} });
If you want to change the Topmost property of the already created window I see three options (in the order of preference):
Create an AlwaysOnTop property on the WizardViewModel and store the viewmodel in a private field and delegate the AlwaysOnTop to the WizardViewModel:
private WizardViewModel wizardViewModel;
public void FileDropped(DragEventArgs eventArgs)
{
//...
wizardViewModel = new WizardViewModel()
windowManager.ShowWindow(wizardViewModel);
}
public bool AlwaysOnTop
{
get { return Settings.Default.DropWindowAlwaysOnTop; }
set
{
//...
if (wizardViewModel != null)
wizardViewModel.AlwaysOnTop = value;
}
}
And in your view you can bind the WizardViewModel's AlwaysOnTop property to the window's TopMost property.
You can use the Application.Windows to retrieve the window. E.g. set the Name property of the created Window with the settings dictionary and then:
windowManager.ShowWindow(new WizardViewModel(),
settings: new Dictionary<string,object>
{ {"Topmost", AlwaysOnTop}, {"Name", "WizardWindow"} });
public bool AlwaysOnTop
{
get { return Settings.Default.DropWindowAlwaysOnTop; }
set
{
//...
var wizardViewModel = Application.Current.Windows.OfType<Window>()
.SingleOrDefault(w => w.Name == "WizardWindow");
if (wizardViewModel != null)
wizardViewModel.AlwaysOnTop = value;
}
}
Derive from the WindowManager and register it in your Bootstrapper and then you can override the CreateWindow, EnsureWindow etc. methods to store the created windows somewhere set the additional properties etc.

When can I set default values for properties on server a control?

I have written the following override for the DataFormatString in my BoundField derived control, yet the field is still formatted as a plain number. I assume that this is because the formatting code isn't calling the DataFormatString property but using the private _dataField field. I would like set the base property in my override, but I want to do so based on a declarative FormatType enum property that will determine which default format string to use. Where could I do this?
public override string DataFormatString
{
get
{
var baseString = base.DataFormatString;
if (!string.IsNullOrWhiteSpace(baseString))
{
return FormatStrings.Currency;
}
return baseString;
}
set
{
base.DataFormatString = value;
}
}
EDIT: It turns out declarative property values are set when the control is built by it's parent, so it's pretty safe to assume they won't be properly used until after this phase of the page life cycle. This is what I actually wanted to know.
You can add the DefaultValue attribute at the top of the method:
[DefaultValue(false)]
public bool SomeCondition
{
get { return someCondition; }
set { someCondition = value; }
}
It looks like the parameterless constructor is the best place to do this. I wanted to set some properties to default values based on other properties, but I realised it wasn't necessary if I determined these defaults when needed, versus in the property getters. E.g:
public BoundReportField()
{
_formatType = FieldFormatTypes.String;
}
protected virtual string GetDefaultFormatString(FieldFormatTypes formatType)
{
var prop = typeof(FormatStrings).GetProperty(formatType.ToString()).GetValue(null, null);
return prop.ToString();
}
protected virtual IFormatProvider GetFormatProvider(FieldFormatTypes formatType)
{
var info = (CultureInfo)CultureInfo.CurrentCulture.Clone();
info.NumberFormat.CurrencyDecimalDigits = 0;
info.NumberFormat.CurrencySymbol = "R";
info.NumberFormat.CurrencyGroupSeparator = ",";
info.NumberFormat.CurrencyDecimalSeparator = ".";
return info;
}
private FieldFormatTypes _formatType;
public virtual FieldFormatTypes FormatType
{
get { return _formatType; }
set
{
_formatType = value;
}
}
protected override string FormatDataValue(object dataValue, bool encode)
{
var formatString = DataFormatString;
var formatProvider = GetFormatProvider(_formatType);
if (string.IsNullOrWhiteSpace(formatString))
{
formatString = GetDefaultFormatString(_formatType);
}
ApplyFormatStyles(_fieldCell);
var retString = string.Format(formatProvider, formatString, dataValue);
return retString;
}

Resources