Reputation: 15121
I have a DateTimeViewModel
with DateTime
property of type DateTime
.
I can do actually in XAML as follows. And it works.
<StackLayout.BindingContext>
<Binding Path="DateTime">
<Binding.Source>
<toolkit:DateTimeViewModel/>
</Binding.Source>
</Binding>
</StackLayout.BindingContext>
<Label Text="{Binding Hour,StringFormat='The hours are {0}'}" />
<Label Text="{Binding Minute,StringFormat='The minutes are {0}'}" />
<Label Text="{Binding Second,StringFormat='The seconds are {0}'}" />
<Label Text="{Binding Millisecond,StringFormat='The milliseconds are {0}'}" />
However I am interested in learning whether I can remove
<StackLayout.BindingContext>
<Binding Path="DateTime">
<Binding.Source>
<toolkit:DateTimeViewModel/>
</Binding.Source>
</Binding>
</StackLayout.BindingContext>
and replace it with something like as follows (not works anyway)
BindingContext = new DateTimeViewModel();
this.SetBinding(Label.TextProperty, "DateTime");
Could you tell me how to set the binding path programmatically?
To make less confusing, let me add the details here.
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected bool SetProperty<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(field, value)) return false;
field = value;
OnPropertyChanged(propertyName);
return true;
}
private void OnPropertyChanged(string propertyName)
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public class DateTimeViewModel : ViewModelBase
{
public DateTimeViewModel()
{
Device.StartTimer(TimeSpan.FromMilliseconds(15),
() =>
{
DateTime = DateTime.Now;
Counter++;
return true;
}
);
}
private DateTime dateTime = DateTime.Now;
public DateTime DateTime
{
get => dateTime;
private set => SetProperty(ref dateTime, value);
}
private long counter = 0;
public long Counter { get => counter; private set => SetProperty(ref counter, value); }
}
Upvotes: 1
Views: 1615
Reputation: 577
To set the binding path programmatically you have to use the following code:
BindableObject.SetBinding(BindableProperty targetProperty, new Binding() {Path = "path"})
In your case it would be something like the following:
this.SetBinding(Label.TextProperty, new Binding() {Path = "DateTime"});
You should bind properties of the same type, in your code you are trying to bind a Label.TextProperty with a property of the type DateTime. make the DateTime property in your ViewModel one of the type "string", and then do the conversion in the ViewModel to "DateTime" or vice versa.
You should not also set parameters, variables, or functions names equal to their type.
Upvotes: 2