I have tried everything I could find on the internet and still cannot get the event to fire. My page contains 2 buttons as you can see which fire in the Simulator but not on my iphone. I have tried many different solutions found on the internet and the one I am showing here is the last one I attempted.
Here is the buttons defined in my view:
<Button Command="{Binding Source={RelativeSource AncestorType={x:Type ViewModel:EditViewModel}}, Path=UpdateMileage}" CommandParameter="{Binding .}" IsEnabled="True" Text="Update" BackgroundColor="Yellow" Grid.Row="6" Grid.Column="1" Grid.ColumnSpan="1" TextColor="Black" Margin="4"/>
<Button Command="{Binding Source={RelativeSource AncestorType={x:Type ViewModel:EditViewModel}}, Path=Cancel}" CommandParameter="{Binding .}" Text="Cancel" BackgroundColor="Yellow" Grid.Row="6" Grid.Column="2" Grid.ColumnSpan="2" TextColor="Black" Margin="4"/>
The viewModel code is as follows;
public ICommand UpdateMileage
{
get; set;
}
public EditViewModel()
{
UpdateMileage = new Command(UpdateMileageData);
MileageTableDefination mileage = new MileageTableDefination();
mileage = Application.Current.Properties["MileageData"] as MileageTableDefination;
SDate = Convert.ToDateTime(mileage.Date);
EntMiles = mileage.Miles.ToString();
EntGas = mileage.Gas.ToString();
EntCost = mileage.Price.ToString();
if (mileage.Note != null)
EntNote = mileage.Note.ToString();
EntId = mileage.Id;
}
public async void UpdateMileageData()
{
Analytics.TrackEvent("In UpdateMileageData Top ");
int autoId = Convert.ToInt32(Application.Current.Properties["autoId"]);
//Analytics.TrackEvent("Mileage Data in Enter Mileage: AutoId " + autoId);
error = false;
IsVisibleLabel = false;
if (EntMiles == "0" || EntMiles == null)
{
error = true;
IsVisibleLabel = true;
EntError = "Miles Driven Must Be Numeric";
}
else if (!System.Text.RegularExpressions.Regex.IsMatch(EntMiles, @"^[0-9]\d*(\.\d+)?$"))
{
error = true;
IsVisibleLabel = true;
EntError = "Miles Driven Must Be Numeric";
}
else if (Convert.ToDecimal(EntMiles) > 1000)
{
error = true;
//IsVisibleLabel = true;
EntError = "Miles Driven Since Last Fillup";
}
if (EntGas == "0" || EntGas == null)
{
error = true;
IsVisibleLabel = true;
EntError = "Gas Used Must Be Numeric";
}
else if (!System.Text.RegularExpressions.Regex.IsMatch(EntGas, @"^[0-9]\d*(\.\d+)?$"))
{
error = true;
IsVisibleLabel = true;
EntError = "Gas Used Must Be Numeric";
}
if (EntCost == "0" || EntCost == null)
{
error = true;
IsVisibleLabel = true;
EntError = "Cost Must Be Numeric";
}
else if (!System.Text.RegularExpressions.Regex.IsMatch(EntCost, @"^[0-9]\d*(\.\d+)?$"))
{
error = true;
IsVisibleLabel = true;
EntError = "Cost Must Be Numeric";
}
else if (Convert.ToDecimal(EntCost) > 300.00m)
{
error = true;
IsVisibleLabel = true;
EntError = "Cost Must Be Numeric And < $300";
}
Analytics.TrackEvent("In UpdateMileageData After If's Error = " + error);
if (!error)
{
miles.Date = SDate.Date;
miles.StrDate = SDate.Date.ToString("MM/dd/yyyy");
miles.Miles = Convert.ToDecimal(EntMiles);
miles.Gas = Convert.ToDecimal(EntGas);
miles.Id = EntId;
miles.CarId = autoId;
miles.MPG = Math.Round(Convert.ToDecimal(EntMiles) / Convert.ToDecimal(EntGas), 3);
miles.Price = Convert.ToDecimal(EntCost);
miles.Note = EntNote;
MileageItemRepository mir = new MileageItemRepository();
var results = await mir.UpdateMileageAsync(miles);
Analytics.TrackEvent("In UpdateMileageData Results = " + results);
if (results == 1)
{
Application.Current.Properties["UpdatedData"] = miles;
var nav = MyNavigation.GetNavigation();
await nav.PushAsync(new ViewMileage());
}
}
}
As you can see from my code I have logging statements and they are never reached. Any help would be much appreciated. Thanks in advance!
EDIT: Here is the full xaml that contains the buttons
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:Validate="clr-namespace:MileageManagerForms.Validators"
xmlns:ViewModel ="clr-namespace:MileageManagerForms.ViewModels"
x:Class="MileageManagerForms.Views.EditMileage">
<ContentPage.BindingContext>
<ViewModel:EditViewModel/>
</ContentPage.BindingContext>
<Grid BackgroundColor="Purple">
<Grid.RowDefinitions>
<RowDefinition Height="47"/>
<RowDefinition Height="30"/>
<RowDefinition Height="30"/>
<RowDefinition Height="45"/>
<RowDefinition Height="45"/>
<RowDefinition Height="30"/>
<RowDefinition Height="45"/>
<RowDefinition Height="45"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="70"/>
<ColumnDefinition Width="85"/>
<ColumnDefinition Width="60"/>
<ColumnDefinition Width="15"/>
<ColumnDefinition Width="85"/>
<ColumnDefinition Width="40"/>
</Grid.ColumnDefinitions>
<Frame BackgroundColor="#2196F3" Padding="10" CornerRadius="0" Grid.ColumnSpan="7" Grid.Row="0">
<Label Text="Edit Mileage" HorizontalTextAlignment="Center" TextColor="White" FontSize="25" />
</Frame>
<DatePicker x:Name="sDate" Format="MM/dd/yyyy" Date="{Binding SDate}" BackgroundColor="Gray" Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" TextColor="White"/>
<Label Text="{Binding EntError}" FontAttributes="Bold" TextColor="Yellow" FontSize="Small" Grid.Row="2" Grid.Column="1" Grid.ColumnSpan="6" />
<Label Text="Miles:" TextColor="White" FontSize="Small" Grid.Row="3" Grid.Column="0" Margin="9" />
<Entry Text="{Binding EntMiles}" Keyboard="Numeric" FontSize="Small" BackgroundColor="White" TextColor="Black" Grid.Row="3" Grid.Column="1" Margin="8" >
<Entry.Behaviors>
<Validate:MaxLengthValidator MaxLength="6"/>
<Validate:DecimalValidator />
</Entry.Behaviors>
</Entry>
<Label Text="Gas:" TextColor="White" FontSize="Small" Grid.Row="4" Grid.Column="0" Margin="12" Grid.ColumnSpan="2"/>
<Entry Text="{Binding EntGas}" Keyboard="Numeric" FontSize="Small" BackgroundColor="White" TextColor="Black" Grid.Row="4" Grid.Column="1" Margin="8" >
<Entry.Behaviors>
<Validate:MaxLengthValidator MaxLength="6"/>
<Validate:DecimalValidator />
</Entry.Behaviors>
</Entry>
<Label Text="Cost:" TextColor="White" FontSize="Small" Grid.Row="3" Grid.Column="2" Grid.ColumnSpan="3" Margin="9"/>
<Entry Text="{Binding EntCost}" Keyboard="Numeric" FontSize="Small" BackgroundColor="White" TextColor="Black" Grid.Row="3" Grid.Column="3" Grid.ColumnSpan="2" Margin="8" >
<Entry.Behaviors>
<Validate:MaxLengthValidator MaxLength="7"/>
<Validate:DecimalValidator />
</Entry.Behaviors>
</Entry>
<Label Text="Note:" TextColor="White" FontSize="Small" Grid.Row="4" Grid.Column="2" Margin="10" Grid.ColumnSpan="2" HorizontalTextAlignment="Start"/>
<Entry Text="{Binding EntNote}" Keyboard="Default" FontSize="Small" BackgroundColor="White" TextColor="Black" Grid.Row="4" Grid.Column="3" Grid.ColumnSpan="4" Margin="8">
<Entry.Behaviors>
<Validate:MaxLengthValidator MaxLength="20"/>
</Entry.Behaviors>
</Entry>
<Entry Text="{Binding EntId}" Grid.Row="4" Grid.Column="8" Grid.ColumnSpan="2" Margin="8" IsVisible="false"/>
<Button Command="{Binding Source={RelativeSource AncestorType={x:Type ViewModel:EditViewModel}}, Path=UpdateMileage}" CommandParameter="{Binding .}" IsEnabled="True" Text="Update" BackgroundColor="Yellow" Grid.Row="6" Grid.Column="1" Grid.ColumnSpan="1" TextColor="Black" Margin="4"/>
<Button Command="{Binding Source={RelativeSource AncestorType={x:Type ViewModel:EditViewModel}}, Path=Cancel}" CommandParameter="{Binding .}" Text="Cancel" BackgroundColor="Yellow" Grid.Row="6" Grid.Column="2" Grid.ColumnSpan="2" TextColor="Black" Margin="4"/>
</Grid>
As for the question about the binding in the view code behind, I have this;
BindingContext = new EditViewModel();
AncestorTypeis correct. The ancestor must be someVieworLayout, NOT someViewModel. If you look at your XAML,RelativeSourceis tracing back through all the xaml elements that CONTAIN the button. Can you give a link to whatever example code you started from?BindingContext. In view's constructor do you haveBindingContext = new YourViewModel();? Add to question the entire hierarchy of your xaml, down to those button lines. Show the declarations of all of its ancestors. Something like<ContentPage ... x:Class="YourPageName"> <StackLayout> ...to<Button ... />. If the buttons are more deeply nested (indented), then there will be more ancestors to show. If they are inside an ItemTemplate, then it might be all the above followed by<ListView ...><Item.Template><DataTemplate>...<Button ...>.{Binding UpdateMileage}