0

The issue that I am having is that when I navigate to the EditTermPage, the title and date fields are not showing the object fields that I am passing over. I believe the object is passed to the EditTermViewModel, but it doesn't seem like it is assigning it the the term Observable property. When I do a breakpoint on the Edit button the term field is populated with the correct information, it just isn't sending it over to the other view model.

Main view:

<CollectionView ItemsSource="{Binding Terms}"
                BackgroundColor="LightGray"> 
    <CollectionView.ItemTemplate>
        <DataTemplate x:DataType="Model:TermModel">
            <Border StrokeThickness="0" Padding="20,10,20,0">
                <Border.Shadow>
                    <Shadow Brush="Black"
                            Opacity="0.5"
                            Radius="10"
                            Offset="5,5"/>
                </Border.Shadow>
                <VerticalStackLayout Padding="20"
                     Margin="0,5,0,20"
                     BackgroundColor="Aqua">
                    <Grid ColumnDefinitions="Auto, *, Auto">
                        <Label Text="{Binding Title}" 
                               x:Name="TermTitle"
                               Grid.Column="0"
                               FontAttributes="Bold"
                               FontSize="Large"/>
                        <Button Text="Edit"
                                Grid.Column="2"
                                Command="{Binding Source={RelativeSource AncestorType=  {x:Type ContentPage}}, Path=BindingContext.EditTermCommand}"
                                CommandParameter="{Binding .}"/>
                    </Grid>
 
                    <HorizontalStackLayout>
                        <Label Text="{Binding TermStartDate, StringFormat='{0:MM/dd/yyyy}'}"
                               x:Name="StartDate"/>
                        <Label Text=" - "/>
                        <Label Text="{Binding TermEndDate, StringFormat='{0:MM/dd/yyyy}'}"
                               x:Name="EndDate"/>
                    </HorizontalStackLayout>
                    <Button Text="Select"
                            WidthRequest="100"
                            Margin="0,30,0,0"
                            x:DataType="ViewModel:TermViewModel"
                            BindingContext="{ViewModel:TermViewModel}"
                            Command="{Binding SelectTermCommand}"/>
                </VerticalStackLayout>
            </Border>
        </DataTemplate>
    </CollectionView.ItemTemplate>
</CollectionView>

Main view model:

public partial class TermViewModel : BaseViewModel
{
    [ObservableProperty]
    public ObservableCollection<TermModel> _terms = new();
    private readonly IDatabase<TermModel> _database;
 
    [ObservableProperty]
    private TermModel _selectedTerm;
 
    public TermViewModel()
    {
        _database = new DatabaseService<TermModel>();
        LoadTerms();
    }
 
    public async Task LoadTerms()
    {
        IsBusy = true;

        try
        {
            this._terms.Clear();
            var terms = await _database.GetItemsAsync();
 
            foreach (var term in terms)
            {
                this._terms.Add(term);
            }
        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex);
            throw;
        }
        finally
        {
            IsBusy = false;
        }
    }
 
    // Button Commands
    [RelayCommand]
    private async Task EditTerm(TermModel term)
    {
        if (term == null)
            return;
        
        await Shell.Current.GoToAsync(nameof(EditTermPage), true, new Dictionary<string, object>
        {
            { nameof(TermModel), term }
        });
    }
}

EditTermPage:

<VerticalStackLayout HorizontalOptions="Center">

<Label Text="Term Details"
       VerticalOptions="Center" 
       HorizontalOptions="Center"
       Padding="20"
       FontSize="Large"/>

<Grid RowDefinitions="*, *, *"
  ColumnDefinitions="*, *">

    <Label Grid.Row="0"
       Grid.Column="0"
       Text="Name"
       VerticalOptions="Center"/>
    <Entry Grid.Row="0"
           Grid.Column="1"
           MaximumWidthRequest="300"
           Text="{Binding Term.Title, Mode=TwoWay}" />

    <Label Grid.Row="1"
       Grid.Column="0"
       Text="Start Date"
       VerticalOptions="Center"/>
    <DatePicker Grid.Row="1"
            Grid.Column="1"
            Date="{Binding Term.TermStartDate, Mode=TwoWay}"/>

    <Label Grid.Row="2"
       Grid.Column="0"
       Text="End Date"
       VerticalOptions="Center"/>
    <DatePicker Grid.Row="2"
            Grid.Column="1"
            Date="{Binding Term.TermEndDate, Mode=TwoWay}"/>
</Grid>
</VerticalStackLayout>

EditTermViewModel:

[QueryProperty(nameof(TermModel), "Term")]
public partial class EditTermViewModel : BaseViewModel
{
    [ObservableProperty]
    private TermModel term;

    public EditTermViewModel()
    {
    }
}
6
  • "I believe the object is passed to the EditTermViewModel" - it is hard to help you if you write something like this. This means nothing and can be either true or false. Please refine your question and put concrete, 100% accurate info about your problem, not beliefs. This indicates like you have problem that you can solve by debugging the app Commented Aug 14 at 5:40
  • Is anything working here? The "main" view binds to a Terms property through ItemsSource="{Binding Terms}" while TermViewModel has a private _terms field, not a Terms property. Same with EditTermPage. This is incomplete code at best Commented Aug 14 at 8:55
  • @PanagiotisKanavos those classes are partial, the fields have annotations, that cause a source generation that results in matching partial classes, that define those properties, that are later used for the binding. It is kinda-sorta the way MAUI works, pretty standard library, and he is not actually supposed to show this code. Commented Aug 14 at 12:32
  • 1
    I like generating code with annotations, but this: [QueryProperty(nameof(TermModel), "Term")] is one the few things that caused me more trouble, that was just not worth the time saved for implementing a single method. Not saying that there is anything wrong with it in particular. And you can definitely still diagnose your problem using it. But I prefer the alternative. Commented Aug 14 at 12:57
  • 2
    @MichałTurczyn this is code that is being generated by the community toolkit lib. Few people know how those things work, fewer know where those lines are, and even fewer have ever debugged them. He puts enough effort to describe his problem, and it may look to you that he is lazy and doesn't want to click F10, but this has nothing to do with the actual situation. Commented Aug 14 at 13:08

1 Answer 1

2

If I have to guess, I would say that there is something minor, like forgetting to put EditTermViewModel as binding context to the EditTermPage.

Anyway, the reason I write this answer is not to guess, but to suggest alternative.

I never like the way how passing data with annotation works. It is very important for me to be able:

  1. To use code before, during or after the data has been passed to the page.

  2. To easily debug, log and diagnose problems on receiving data when navigating.

This is why I use this approach:

https://learn.microsoft.com/en-us/dotnet/api/microsoft.maui.controls.iqueryattributable?view=net-maui-9.0

Remove the annotation, and implement the interface.

It is just one method:

public void ApplyQueryAttributes(System.Collections.Generic.IDictionary<string,object> query)

Put a break point, and you will see if the query has your data or not. If it has it, just assign it to the property. If it doesn't check your page constructor. (I am 99.99% sure it will turn out to be the binding context)

Sign up to request clarification or add additional context in comments.

Comments

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.