私はクロス プラットフォームのモバイル プロジェクトで MvvmCross を使用しており、同じ共有ビューモデルを使用している MonoTouch プロジェクトに 2 つの異なるビューがあり、MvvmCross で同じビューモデルを使用して異なるビューに移動するようにコードを構造化する方法がわかりません。
3 に答える
MvvmCrossプラットフォームで使用されるデフォルトの規則は、リフレクションを使用してすべてのビューを自動的に登録することです。
これは、基本のセットアップクラスで行われます-https ://github.com/slodge/MvvmCross/blob/master/Cirrious/Cirrious.MvvmCross/Platform/MvxBaseSetup.cs :
    protected virtual void InitializeViews()
    {
        var container = this.GetService<IMvxViewsContainer>();
        foreach (var pair in GetViewModelViewLookup())
        {
            Add(container, pair.Key, pair.Value);
        }
    }
ここでGetViewModelViewLookup、ViewModelタイプのディクショナリをViewタイプに返します。
    protected virtual IDictionary<Type, Type> GetViewModelViewLookup(Assembly assembly, Type expectedInterfaceType)
    {
        var views = from type in assembly.GetTypes()
                    let viewModelType = GetViewModelTypeMappingIfPresent(type, expectedInterfaceType)
                    where viewModelType != null
                    select new { type, viewModelType };
        return views.ToDictionary(x => x.viewModelType, x => x.type);
    }
ユニバーサルiPad/iPhoneアプリでは、ビューモデルごとに複数のビューを含めたい場合があります。iPadで1つのビューを使用し、iPhoneで1つのビューを使用します。
これを行うために、ビューを「型破り」としてマークするために使用できる属性がいくつかあります(文字通り今すぐです!)。これらは次のとおりです。
- MvxUnconventionalViewAttribute - これを使用して、ビューが慣例に含まれてはならないことをマークします
- https://github.com/slodge/MvvmCross/blob/master/Cirrious/Cirrious.MvvmCross/Views/Attributes/MvxUnconventionalViewAttribute.cs _
 
- MvxConditionalConventionalViewAttribute - 抽象属性-これをオーバーライドして、包含/除外のための独自のカスタムロジックを提供します
- https://github.com/slodge/MvvmCross/blob/master/Cirrious/Cirrious.MvvmCross/Views/Attributes/MvxConditionalConventionalViewAttribute.cs _
 
- MvxFormFactorSpecificViewAttribute - iOS/タッチのみ
- 検出されたiPhoneフォームファクターが現在のデバイスと一致する場合にのみビューを含む属性
- https://github.com/slodge/MvvmCross/blob/master/Cirrious/Cirrious.MvvmCross/Touch/Views/Attributes/MvxFormFactorSpecificViewAttribute.cs _
 
これらの最後のものは、おそらくこの場合に必要なものです-次のように宣言された2つのビューを使用して、MainViewModelの単純なiPhone/iPadスイッチングを実装できます。
[MvxFormFactorSpecificView(MvxTouchFormFactor.Phone)]
public class MyIPhoneView : BaseView<MainViewModel>
{
    // iphone specific view ...
}
[MvxFormFactorSpecificView(MvxTouchFormFactor.Pad)]
public class MyIPadView : BaseView<MainViewModel>
{
    // ipad specific view ...
}
または、非常にカスタムな構成が必要な場合は、すべての「従来型」の動作をオーバーライドできます。GetViewModelViewLookupたとえば、次の独自のオーバーライドを実装できます。
protected override IDictionary<Type, Type> GetViewModelViewLookup(Assembly assembly, Type expectedInterfaceType)
{
    if (IsIPad)
    {
        return new Dictionary<Type, Type>() 
        {
            { typeof(HomeViewModel), typeof(IPadHomeView) },
            { typeof(DetailViewModel), typeof(IPadDetailView) },
            { typeof(AboutViewModel), typeof(SharedAboutView) },
        };
    }
    else
    {
        return new Dictionary<Type, Type>() 
        {
            { typeof(HomeViewModel), typeof(IPhoneHomeView) },
            { typeof(DetailViewModel), typeof(IPhoneDetailView) },
            { typeof(AboutViewModel), typeof(SharedAboutView) },
        };
    }
}
最終的には、iPadアプリのビューだけでなくViewModelも追加する必要があると判断する可能性があることに注意してください。iPadには結局のところはるかに大きな画面があります。この場合、手動で追加できます。最終的に、アプリが数百万人のユーザーにヒットした場合、タブレットコードを電話コードから完全に分岐させることもできますが、通常は、数百万人のユーザーに到達するまで待つことができます...
最近 MvvmCross を使い始め、v4.2.1 を使用しています。一部名前が変わっているようです。次のように、iPhone と iPad のビューを別々に 1 つの ViewModel を使用しています。
[MvxFormFactorSpecific(MvxIosFormFactor.Phone)]
public class MyIPhoneView : BaseView<MainViewModel>
{
    // iphone specific view ...
}
[MvxFormFactorSpecific(MvxIosFormFactor.TallPhone)]
public class MyTallIPhoneView : BaseView<MainViewModel>
{
    // tall iphone specific view ...
}
[MvxFormFactorSpecific(MvxIosFormFactor.Pad)]
public class MyIPadView : BaseView<MainViewModel>
{
    // ipad specific view ...
}