Search code examples
xamlmauiextension-methods

How to use method extension in Maui xaml?


I have a Dto object:

public class SearchResultDto
{
  public bool IsOne { get; set; };

  public bool IsTwo { get; set; }
}

And I have a method extension:

public static class SearchResultDtoExtension{
  public static bool IsBoth(this SearchResultDto dto)
  {
    return dto.IsOne && dto.IsTwo;
  }
}

At my ViewModel I can successful use searchResultDto.IsBoth();

I want this extension use in xaml like:

IsVisible={Binding IsBoth()}

It does not work.

How can I use a method extension in xaml?

my code:

<listView:SfListView.ItemTemplate>
    <DataTemplate x:DataType="contracts:SearchResultDto">
            <VerticalStackLayout IsVisible="{Binding **IsBoth()**}"

Solution

  • As explained in comments you can't bind methods in XAML, you could instead use one of the two approaches:

    1. Using a ValueConverter:
    public class IsBothConverter : IValueConverter
    {
        public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
            => (value as SearchResultDto)?.IsBoth();
    
    
        public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    
        <ContentPage.Resources>
            <ResourceDictionary>
                <local:IsBothConverter x:Key="isBothConverter" />
            </ResourceDictionary>
        </ContentPage.Resources>
    ...
    
     <VerticalStackLayout IsVisible="{Binding ., Converter={StaticResource isBothConverter}}" />
    
    1. Using an auto property (like @julian suggested in comments) Both inside your ViewModel: Note that whenever the property of type SearchResultDto changed we raise a property changed event for Both property also.
    SearchResultDto dto = new() { IsOne = true, IsTwo = true };
    
    public SearchResultDto Dto
    {
        get => dto;
        set
        {
            dto = value;
            OnPropertyChanged(nameof(Dto));
            OnPropertyChanged(nameof(Both));
        }
    }
    
    public bool Both => (dto is null) ? false : dto.IsOne && dto.IsTwo;
    

    I see that you are inside a datatemplate, thus you have to ensure a correct Source and x:DataType when binding to Both:

     <VerticalStackLayout IsVisible="{Binding Path="Both", Source="..."}" />
    
    1. Using a third auto property inside your model (this goes against mvvm pattern as the model and the view are not properly decoupled)
    public class SearchResultDto
    {
        public bool IsOne { get; set; }
        public bool IsTwo { get; set; }
        public bool IsBoth => IsOne && IsTwo;
    }
    
     <VerticalStackLayout IsVisible="{Binding IsBoth}" />