【问题标题】:MvxException: Failed to construct and initialize ViewModelMvxException:无法构造和初始化 ViewModel
【发布时间】:2017-08-07 15:02:20
【问题描述】:

我正在尝试使用ShowViewModel<ViewModel, Type>(parameter) 在同一视图模型(递归)的不同实例之间传递对象列表作为参数。 我的 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);

        }
    }
}

【问题讨论】:

标签: c# mvvm xamarin.forms mvvmcross


【解决方案1】:

您放入 ViewModel 的 ctor 中的所有内容,MvvmCross 都将其视为需要通过依赖注入获取的内容。所以在你的情况下,由于ObjectItem 没有在 MvvmCross IoC 容器中注册,ShowViewModel 无法解析并放入构造函数中。

解决这个问题的方法通常是在ViewModel 中使用Init 方法,而不是在ShowViewModel 调用中将对象作为参数传递。

如果您使用 MvvmCross 5.x 或更高版本,则在使用新的 NavigationService 时,它已移至 Initialize,但基本内容或多或少相同。

我认为在您的情况下解决此问题的最快方法是向您的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);
    }
}

【讨论】:

  • 这不就是 Initialize 的用途吗?
  • 我已经实现了 Initialize(查看 ObjectItemViewModel 的末尾)。我真的不明白你写了什么......你建议删除哪个构造函数?
  • Initialize 仅在您使用 NavigationService 时调用,您在这里没有使用它,因此它不会被调用。你只需要添加一个空的 ctor 和 Init 方法......这怎么不清楚?
  • 我使用 ShowViewModel 是因为 NAvigationService.Navigate() 中存在一个未解决的问题。您建议如何修复我的代码?
  • 我使用的是 MVVMCross 5.0.6,所以 Initialize 应该可以工作
猜你喜欢
  • 2018-06-16
  • 1970-01-01
  • 1970-01-01
  • 2018-06-04
  • 2020-07-12
  • 2012-05-03
  • 2021-12-20
  • 2019-10-07
  • 2021-02-07
相关资源
最近更新 更多