steve
steve

Reputation: 927

Dependency Injection with XAML, is it possible?

I have a class which takes advantage of the new Xamarin Forms Shell Search, to populate the Items source of the search bar I would like to use my repositories to get a list of items.

Using the Prism MVVM framework I would rather use DI than creating a new instance myself. Doing this however, my code does not compile as the Search handler referenced in the XAML code complains about not having a parameterless constructor. Is there a work around this? Or is there a better way? Please do let me know

Search handler class (How I want it to be)

public class IngredientsSearchHandler : SearchHandler
    {
        private readonly IUnitOfWork _unitOfWork;

        public IngredientsSearchHandler(IUnitOfWork unitOfWork)
        {
            _unitOfWork = unitOfWork;
        }

        protected override void OnQueryChanged(string oldValue, string newValue)
        {
            base.OnQueryChanged(oldValue, newValue);

            if (string.IsNullOrWhiteSpace(newValue))
            {
                ItemsSource = null;
            }
            else
            {
                ItemsSource = _unitOfWork.IngredientRepository.GetAll().Where(x => x.Name.ToLower().Contains(newValue.ToLower())).ToList();
            }
        }
    }

View which references search handler

The error is : "There is no argument given that corresponds to the required formal parameter 'unitOfWork' of 'IngredientsSearchHandler.IngredientsSearchHandler(IUnitOfWork)'"

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:controls="clr-namespace:TestApp.Controls"
             xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
             prism:ViewModelLocator.AutowireViewModel="True"
             mc:Ignorable="d"
             x:Class="TestApp.Views.IngredientsView">

    <Shell.SearchHandler>
        <controls:IngredientsSearchHandler Placeholder="Enter ingredient.."
                                           ShowsResults="true"
                                           DisplayMemberName="Name"
                                           Keyboard="Text">
            <controls:IngredientsSearchHandler.ItemTemplate>
                <DataTemplate>
                    <Grid Padding="10">
                        <Label Text="{Binding Name}"
                               FontAttributes="Bold"/>
                    </Grid>
                </DataTemplate>
            </controls:IngredientsSearchHandler.ItemTemplate>
        </controls:IngredientsSearchHandler>
    </Shell.SearchHandler>

    <ContentPage.Content>
            <Label Text="Test"/>
    </ContentPage.Content>
</ContentPage>

Upvotes: 3

Views: 2257

Answers (2)

Haukinger
Haukinger

Reputation: 10883

What I would do is remove IngredientsSearchHandler altogether and bind Query and ItemsSource of a regular SearchHandler to properties on the view model and react to changes to the query there (by updating the ItemsSource).

The view model gets its dependencies injected automatically (because you use the ViewModelLocator), and I'm not aware of any way to intercept the creation of controls defined in xaml to use the container.

Upvotes: 2

Dan Siegel
Dan Siegel

Reputation: 5799

Short answer is yes you can use DependencyInjection in XAML with the ContainerProvider.

<ContentPage xmlns:prism="http://prismlibrary.com"
             xmlns:converters="using:MyProject.Converters">
  <ContentPage.Resources>
    <prism:ContainerProvider x:TypeArguments="converters:SomeConverter" x:Key="someConverter" />
  </ContentPage.Resources>
</ContentPage>

Upvotes: 2

Related Questions