2

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();
6
  • are they contained in a template? if not, I don't see why you need such a complex binding expression Commented Apr 30, 2022 at 2:02
  • To add to Jason's comment, please show what those XAML lines are inside of. If their parent (or higher ancestor) is ListView.ItemTemplate or CollectionView.ItemTemplate or DataTemplate or other template, that is important to know. Also, I doubt very much that AncestorType is correct. The ancestor must be some View or Layout, NOT some ViewModel. If you look at your XAML, RelativeSource is tracing back through all the xaml elements that CONTAIN the button. Can you give a link to whatever example code you started from? Commented Apr 30, 2022 at 2:09
  • Add to question the line of code that sets view's BindingContext. In view's constructor do you have BindingContext = 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 ...>. Commented Apr 30, 2022 at 2:31
  • 1
    based on the XAML you posted, the binding should be as simple as {Binding UpdateMileage} Commented Apr 30, 2022 at 11:46
  • That is the way I originally had it coded and it did not work. I also had the beginning part of the method of the code view model as follows, public Command Cancel => new Command(async () => {}); as opposed to the way the update shows now it was like the cancel here. Commented Apr 30, 2022 at 14:34

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.