MvxException:无法构造和初始化ViewModel

时间:2017-08-07 15:02:21

标签: c# mvvm xamarin.forms mvvmcross

我正在尝试使用ShowViewModel<ViewModel, Type>(parameter)将对象List作为参数传递给同一viewmodel(递归)的不同实例之间的参数。 我在MVVMCross / xamarin表单项目中遇到此错误。

 MvvmCross.Platform.Exceptions.MvxException: Failed to construct and 
initialize ViewModel for type Project.Core.ViewModels.ObjectViewModel from locator MvxDefaultViewModelLocator - check InnerException for more information ---> MvvmCross.Platform.Exceptions.MvxException: Problem creating viewModel of type ObjectViewModel ---> MvvmCross.Platform.Exceptions.MvxIoCResolveException: Failed to resolve parameter for parameter obj of type ObjectItem when creating Project.Core.ViewModels.ObjectViewModel
  at MvvmCross.Platform.IoC.MvxSimpleIoCContainer.GetIoCParameterValues (System.Type type, System.Reflection.ConstructorInfo firstConstructor) [0x00036] in C:\projects\mvvmcross\MvvmCross\Platform\Platform\IoC\MvxSimpleIoCContainer.cs:502 
  at MvvmCross.Platform.IoC.MvxSimpleIoCContainer.IoCConstruct (System.Type type) [0x0002c] in C:\projects\mvvmcross\MvvmCross\Platform\Platform\IoC\MvxSimpleIoCContainer.cs:312 
  at MvvmCross.Platform.Mvx.IocConstruct (System.Type t) [0x00006] in C:\projects\mvvmcross\MvvmCross\Platform\Platform\Mvx.cs:169 
  at MvvmCross.Core.ViewModels.MvxDefaultViewModelLocator.Load (System.Type viewModelType, MvvmCross.Core.ViewModels.IMvxBundle parameterValues, MvvmCross.Core.ViewModels.IMvxBundle savedState) [0x00000] in C:\projects\mvvmcross\MvvmCross\Core\Core\ViewModels\MvxDefaultViewModelLocator.cs:33 

解释更多,这是我的代码:

ObjectPage.xaml

<mvx:MvxContentPage xmlns="http://xamarin.com/schemas/2014/forms"
         xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
         xmlns:mvx="clr-namespace:MvvmCross.Forms.Core;assembly=MvvmCross.Forms"
         x:Class="Project.Core.Pages.ObjectPage"
         Title="Object">
<StackLayout>
    <StackLayout>
        <StackLayout Padding="5,5,5,5">
            <Label Text="{Binding SubTitle}" FontSize="21" VerticalOptions="End"></Label>
        </StackLayout>
        <StackLayout>
            <ListView 
                ItemsSource="{Binding ObjectItems}"
                SelectedItem="{Binding SelectedListItem, Mode=TwoWay}">
                <ListView.ItemTemplate>
                    <DataTemplate>
                        <ViewCell>
                            <Frame HasShadow="True" Margin="10">
                                <StackLayout Margin="8">
                                    <Label Text="{Binding Title}"></Label>
                                </StackLayout>
                            </Frame>
                        </ViewCell>
                    </DataTemplate>
                </ListView.ItemTemplate>
            </ListView>
        </StackLayout>
    </StackLayout>
</StackLayout>

ObjectPage.xaml.cs

namespace Project.Core.Pages
{
    public partial class ObjectPage
    {
        public ObjectPage (ObjectItem obj)
        {
            InitializeComponent ();
            BindingContext = new ObjectViewModel(obj);
        }
    }
}

ObjectViewModel

namespace Project.Core.ViewModels
{
    public class ObjectViewModel : ObjectItemViewModel
    {

        public ObjectViewModel(ObjectItem obj) : base(obj)
        {
        }

        public override void ShowItem()
        {
                ShowViewModel<ObjectViewModel, ObjectItem>(Obj);
        }
    }
}

要解释更多:每个Object都有一个ObjectItem列表。每个ObjectItem还有一个ObjectItem列表。 对象继承自ObjectItem。 这是一个例子:

Objects = new List<Object>
            {
                new Object
                {
                    Title = "Title",
                    SubTitle="subtitle",
                    ObjectItems = new List<ObjectItem>
                    {
                        new ObjectItem{Title = "title goes here" },
                        new ObjectItem{Title = "another objectItem title"},
                    }
                }
             }

为了加载这些项目,我创建了一个类视图模型,ObjectViewModel从该模型继承了

ObjectItemViewModel.cs

 namespace Project.Core.ViewModels
{
    public class ObjectItemViewModel : MvxViewModel<ObjectItem>
{
    public string Title => (this.Obj == null ? "/!\\ Titre" : this.Obj.Title);
    public string SubTitle => (this.Obj == null ? "/!\\ Sous Titre" : this.Obj.SubTitle);
    private List<ObjectItemViewModel> _ObjectItems;
    public List<ObjectItemViewModel> ObjectItems
        {
            get => _ObjectItems;

            set
            {
                _ObjectItems = value;
                RaisePropertyChanged(() => ObjectItems);
            }
        }
        private ObjectItem _Obj;
        public ObjectItem Obj
        {
            get => _Obj;
            set
            {
                _Obj= value;
                RaisePropertyChanged(() => Obj);
            }
        }
        public ObjectItemViewModel _selectedListItem;
        public ObjectItemViewModel SelectedListItem
        {
            get
            {
                return _selectedListItem;
            }
            set
            {
                if (SetProperty(ref _selectedListItem, value))
                    OnSelectedChangedCommand.Execute(value);
            }
        }

        public ObjectItemViewModel(ObjectItem obj)
        {
            this.Obj = obj;
            loadItems();
        }

        private MvxCommand<ObjectItemViewModel> _onSelectedChangedCommand;

        private ICommand OnSelectedChangedCommand
        {
            get
            {
                return _onSelectedChangedCommand ?? (_onSelectedChangedCommand = new MvxCommand<ObjectItemViewModel>((item) =>
                {
                    if (item == null)
                    {
                        Debug.WriteLine("Item null");

                        return;
                    }
                    item.ShowItem();
                }));
            }
        }


        public virtual void ShowItem()
        {
            //DO nothing


        }

        public void loadItems()
        {
            if (this.Obj != null &&
                this.Obj.ObjectItems != null &&
                this.Obj.ObjectItems.Count > 0)
            {
                ObjectItems = new List<ObjectItemViewModel>();
                foreach (ObjectItem objectItem in this.Obj.ObjectItems)
                {
                    if (objectItem.MemoItems != null && objectItem.ObjectItems.Count == 1)
                    {
                        ObjectItems.Add(new InfoViewModel(objectItem));
                    }
                    else
                    {

                        ObjectItems.Add(new ObjectViewModel(objectItem));
                        Debug.WriteLine("Item crée" + objectItem.Title);
                    }
                }

            }
        }

        public override Task Initialize(ObjectItem parameter)
        {
            Obj = parameter;
            return Task.FromResult(0);

        }
    }
}

1 个答案:

答案 0 :(得分:2)

你放在ViewModel的ctor中的所有内容,MvvmCross都将它视为通过依赖注入获得的东西。因此,在您的情况下,由于ObjectItem未在MvvmCross IoC容器中注册,因此ShowViewModel无法解析并放入构造函数中。

通常如何解决这个问题,就是使用Init中的ViewModel方法来传递对象作为ShowViewModel调用中的参数。

如果您使用MvvmCross 5.x或更新版本,则在使用新的Initialize时已移至NavigationService,但基本要素大致相同。

我认为在你的情况下最快的方法是在你的ObjectViewModel中添加一个空的构造函数。然后添加Init方法,在其中分配Obj道具并调用loadItems(),类似于非空的ctor。如下所示:

public class ObjectItemViewModel : MvxViewModel<ObjectItem>
{
    public ObjectItemViewModel() { }

    public void Init(ObjectItem obj)
    {
        Obj = obj;
        loadItems();
    }

    // rest of code
}

ObjectItemViewModel移除ctor,然后将ObjectViewModel改为:

public class ObjectViewModel : ObjectItemViewModel
{
    public override void ShowItem()
    {
        ShowViewModel<ObjectViewModel, ObjectItem>(Obj);
    }
}