I'm new to Xamarin forms and have only been working with it for a few months. I have a Xamarin forms app that will be used with Android and iOS and is using the MVVM structure. I have an ObservableCollection
of objects in my ViewModel that I am iterating over with a custom repeater view that extends StackLayout
and inside of the DataTemplate
I have a custom Entry class that extends Entry that is binding its Text
attribute to the object's Value
property (a nullable double).
What I want to do next, is modify the template to hide the Entry
tag if a certain boolean that I am adding into the model has a value of true, and then display a Slider
and a Label
, to show the value of the Slider
.
So far I have been able to bind the Maximum
/Minimum
attributes to properties from my Viewmodel which is great, but whenever I try to bind the Value
property to the Slider
, my XAML won't load up, and I'm not getting any error. I also will need to implement functionality to only allow the user to slide over a given 'increment' (.1, 1, 2, etc). I would like to slide the Slider
and once the user stops sliding, the Value
property is set and stored in the model. I also need to it to pre-load if there is a value already existing, but those two I can get to later.
I think I am going about this incorrectly. I have tried searching through lots of different examples but I cannot for the life of me figure this out.
Here is what my XAML looks like for the slider/label
<Slider x:Name="slider" Value="{Binding Value}"
Maximum="{Binding VM.Question.NumericMaxValue}"/>
<Label x:Name="displayLabel"
Text="{Binding Source={x:Reference slider}, Path=Value,
StringFormat='The slider value is {0:F0}'}"
HorizontalOptions="Center" VerticalOptions="CenterAndExpand" />
A simplified version of my Model because I don't want to put code out there that I maybe shouldn't.
public class MyItemModel
{
private double? _value;
public double? Value
{
get { return _value; }
set
{
if (_value != value)
{
_value = value;
if (!FormatAsTime)
{
if (VM.Question.NumericMaxValue != -1 && Value > VM.Question.NumericMaxValue)
{
Value = VM.Question.NumericMaxValue;
return;
}
if (Value < VM.Question.NumericMinValue)
{
Value = VM.Question.NumericMinValue;
return;
}
RaisePropertyChanged(() => Value);
RaisePropertyChanged(() => HasValue);
SpinDownCommand.RaiseCanExecuteChanged();
SpinUpCommand.RaiseCanExecuteChanged();
}
else
{
RaisePropertyChanged(() => Value);
RaisePropertyChanged(() => HasValue);
}
VM.UpdateCanGoNext();
}
}
}
}
From the code you put (there are some missing key parts),
but I presume you should use TwoWay
binding:
<Slider x:Name="slider"
Value="{Binding Value, Mode=TwoWay}"
Maximum="{Binding VM.Question.NumericMaxValue}"
/>
You also don't need to use a Nullable<double>
for your property (as @jason mentionned it) because the slider control has always a value.
And why your second binding (Maximum
property) is equal to 'VM.Question
...' ?
Is it not the same for the Value
binding ?
ie:
Value="{Binding VM.Value, Mode=TwoWay}" -- ??
To update the value only when the control's thumb has finished to "move", you should use reactive extensions. It allow to you to manipulate events and select the "last" one of a serie for instance:
Rx for Xamarin forms presentation
I let you see and check for more details...