I created a custom view (NavProgressbar) which has a step property.
private static readonly BindableProperty ProgressStepProperty = BindableProperty.Create(
nameof(ProgressStep), typeof(int), typeof(NavProgressbar),
0, BindingMode.TwoWay, propertyChanged: ProgressStepPropertyChanged);
private static void ProgressStepPropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
//update view, removed for brevity
}
public int ProgressStep
{
get => (int)GetValue(ProgressStepProperty);
set => SetValue(ProgressStepProperty, value);
}
In my MvxContentPage I can use it like this by setting the value of ProgressStep
<npb:NavProgressbar
x:Name="NavProgressBar"
ProgressStep="2"/>
That works so far. Now I want to set it from my viewmodel, so in my viewmodel I created a property...
private int _progressStep;
public int ProgressStep
{
get => _progressStep;
set => SetProperty(ref _progressStep, value);
}
...and in my MvxContentPage instead of the fixed value I bind to my viewmodel property by doing
<npb:NavProgressbar
x:Name="NavProgressBar"
ProgressStep="{Binding ProgressStep}"/>
But it does not work. Other bindings to buttons and labels etc work fine. Where is my mistake?
Edit: In my MvxContentPage which has the NavProgressbar I set
xmlns:viewModels="clr-namespace:x.y.z.ViewModels;assembly=myAssembly"
x:TypeArguments="viewModels:myViewModel"
x:DataType="viewModels:myViewModel"
and Resharper shows in the binding
ProgressStep="{Binding path={myViewModel}.ProgressStep}"
so I think the binding context is setup correctly. Maybe it's also important that the view and viewmodel are abstract and I am using subclasses of this abstract view and viewmodel?
Other bindings work as expected, e.g. for a button Resharper shows
<Button
Text="{Binding path={myViewModel}.ButtonText}"
CodePudding user response:
You need to set the BindingContext to point at the ViewModel.
When using {Binding _____}
to connect a C# property, the XAML needs to know what it's binding to. By default, it will bind to the code behind file associated with it. The following might work for you (double check the namespaces are correct):
<npb:NavProgressbar
x:Name="NavProgressBar"
ProgressStep="{Binding ProgressStep}"
<npb:NavProgressbar.BindingContext>
<npb:NavProgressBarViewModel />
</npb:NavProgressbar.BindingContext>
/>
This page from Microsoft has some good examples on how BindingContext works: https://docs.microsoft.com/en-us/xamarin/xamarin-forms/xaml/xaml-basics/data-bindings-to-mvvm
CodePudding user response:
According to the code you provided, everything is right. So if you make sure the property will call the property changed event in the viewmodel, you can check the similar case which has an example show how to bind the bindableproperty in the custom view to the viewmodel.
Case link:Get value of a BindableProperty used in ViewModel in control?
CodePudding user response:
So, the problem was that Resharper suggested to make this property private
private static readonly BindableProperty ProgressStepProperty =
BindableProperty.Create(nameof(ProgressStep), typeof(int), typeof(NavProgressbar), 0, BindingMode.TwoWay, propertyChanged: ProgressStepPropertyChanged);
which I did, but it has to be public
public static readonly BindableProperty ProgressStepProperty =
BindableProperty.Create(nameof(ProgressStep), typeof(int), typeof(NavProgressbar), 0, BindingMode.TwoWay, propertyChanged: ProgressStepPropertyChanged);