2017-08-07 39 views
0

ShowViewModel<ViewModel, Type>(parameter)を使用して、同じビューモデル(再帰的)の異なるインスタンス間でオブジェクトのリストをパラメータとして渡そうとしています。 MVVMCross/xamarinフォームプロジェクトでこのエラーが発生します。MvxException:ViewModelの構築と初期化に失敗しました

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); 
     } 
    } 
} 

以上を説明するには、次の各オブジェクトは、ObjectItemsのリストを持っています。各ObjectItemにはObjectItemのリストもあります。 ObjectはObjectItemから継承します。ここで は一例です:

​​3210

これらの項目をロードするには、私はObjectViewModelはあなたのctorに入れ

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

     } 
    } 
} 
+0

ただ、パフォーマンスの観測を - あなたのページ上の不要なネストされたスタックレイアウトの多くを持っています。ページのルートには別のものがあり、リストビューをラップするものがあります。このページの「ビジュアルツリーサイズを減らす」セクションを見てください。https://developer.xamarin.com/guides/xamarin-forms/deployment-testing/performance/ –

答えて

1

すべてを継承し、そこから、クラスのviewmodelを作成しましたViewModelのMvvmCrossは、Dependency Injectionを介して取得する必要があるものとして扱います。したがって、あなたのケースでは、ObjectItemがMvvmCross IoCコンテナに登録されていないので、ShowViewModelは解決できず、コンストラクタに入れられません。

これは通常解決されますが、代わりにViewModelInitメソッドを使用して、ShowViewModel呼び出しでオブジェクトをパラメータとして渡すことです。

MvvmCross 5.x以降を使用している場合は、新しいNavigationServiceを使用するとInitializeに移動しましたが、基本的な違いは同じです。

私は、あなたのケースでこれを回避する最速の方法は、あなたのObjectViewModelに空のコンストラクタを追加することだと思います。次に、Obj小道具を割り当て、空でないctorと同様のloadItems()を呼び出すInitメソッドを追加します。だから、のようなもの:

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

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

    // rest of code 
} 

ObjectViewModelこの作り、その後、ObjectItemViewModelからCTORを削除します。

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

は初期化のためのものではありませんか? – hanaa

+0

私は既にInitializeを実装しています(ObjectItemViewModelの終わりを見てください)。私は本当にあなたが書いたことを理解していない...どのコンストラクタを削除することをお勧めしますか? – hanaa

+0

Initializeは、NavigationServiceを使用している場合にのみ呼び出されます。ここでは使用していないため、呼び出されません。あなたは空のctorとInitメソッドを追加する必要があります...どうしてそれは明確ではありませんか? – Cheesebaron

関連する問題