使用XAML进行依赖注入,是否可行?

3

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>

2个回答

1
我会做的是完全删除IngredientsSearchHandler,并将常规SearchHandlerQueryItemsSource绑定到视图模型上的属性,并在那里对查询进行更改(通过更新ItemsSource)。
视图模型自动注入其依赖项(因为您使用了ViewModelLocator),我不知道任何拦截在xaml中定义的控件创建以使用容器的方法。

太棒了!这个建议非常好用,现在我已经将所有内容封装在我的ViewModel中了!!!希望这能帮助其他人! - steve

1

简短的回答是,您可以使用ContainerProvider在XAML中使用DependencyInjection。

<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>

谢谢,那很有道理!但我不明白的是,这样做如何消除错误?我复制了你所做的,但错误仍然存在,我的搜索处理程序引用被下划线标记。我错过了什么吗?谢谢! - steve
你需要将此转换器作为 controls:IngredientsSearchHandler 的 x:Arguments 参数传递。这是如何使用带参数构造函数初始化控件的方法。 - memsranga
@shanranm 当使用容器提供程序时,您不需要使用x:Arguments,因为它使用DI容器来解析类型。您只需要指定TypeArguments,因为它是一个泛型类型ContainerProvider<T>,它会自动返回类型T - Dan Siegel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接